2008-10-03 32 views
5

Nếu tôi sinh ra một chủ đề mới, và sau đó bên trong nó tôi đẩy một bộ điều khiển mới lên UINavigationController của tôi, sử dụng mã như thế này ...NSThread và UIViewController tương tác

(a) không làm việc

-(void)myCallbackInThread 
{ 
    // move on... 
    UIApplication* app = [UIApplication sharedApplication]; 
    [app changeView]; 
} 

sau đó tôi thấy rằng khung nhìn xuất hiện, nhưng không phản hồi lại đầu vào của người dùng.

Nếu tôi thay đổi mã như thế này

(b) làm việc

-(void)myCallbackInThread 
{ 
    // move on... 
    UIApplication* app = [UIApplication sharedApplication]; 
    [app performSelectorOnMainThread:@selector(moveToMain) withObject:nil waitUntilDone:FALSE]; 
} 

Sau đó, mọi thứ hoạt động tốt.

Bất kỳ gợi ý nào về lý do tại sao?

+0

Bạn có nhận được kết quả đầu ra nào trong cửa sổ bảng điều khiển không? Tôi đã tìm thấy với luồng trên iPhone nếu bạn đang làm điều gì đó hài hước mà nó xuất ra thông điệp tường trình. – Lounges

Trả lời

2

Trong trường hợp của bạn, nó thực sự phụ thuộc vào những gì đang xảy ra trong [app changeView], nhưng lý do nó dừng đáp ứng rất có thể là bạn không có sự kiện điều phối vòng chạy trên chuỗi mới, thứ cấp của bạn (chi tiết bên dưới). Nói chung, tuy nhiên, nó là một ý tưởng rất xấu để cập nhật GUI từ một chuỗi thứ cấp. Như bạn đã phát hiện, tất cả các sự kiện này sẽ đi qua chuỗi chính.

Lý do chính mà ví dụ thứ hai của bạn hoạt động và không phải là thứ nhất của bạn là UIApplication thiết lập và xử lý vòng lặp chạy và bộ điều phối sự kiện cho bạn trên chuỗi chính. Vì vậy, khi bạn gọi performSelectorInMainThread, bộ chọn sẽ được gửi đến vòng lặp chạy chính có thể xử lý đầu vào gui của bạn và các sự kiện khác. Trình điều phối sự kiện cũng được chạy và quản lý bởi UIApplication trên luồng chính.

Về cơ bản, không thực hiện bất kỳ hoạt động quản lý GUI nào trên chuỗi phụ. Gửi những bài đó cho chủ đề chính. Và nếu bạn cần xử lý trên chuỗi phụ (đối với những thứ như bộ hẹn giờ hoặc cuộc gọi asynch, v.v.) thì bạn phải bắt đầu và quản lý vòng lặp chạy của riêng bạn trên chuỗi đó (xem NSRunLoop để biết thêm về cách quản lý vòng lặp chạy của bạn).

2

Chỉ cần thấy điều này trong các tài liệu luồng iPhone

Nếu ứng dụng của bạn có một giao diện người dùng đồ họa , nó được khuyến khích rằng bạn nhận được sự kiện người dùng liên quan đến và khởi cập nhật giao diện từ chủ đề chính ứng dụng của bạn . Cách tiếp cận này giúp tránh đồng bộ hóa các vấn đề liên quan đến việc xử lý người dùng sự kiện và nội dung cửa sổ bản vẽ. Một số khung công tác, chẳng hạn như Cocoa, thường yêu cầu hành vi này, nhưng nó cũng có lợi thế là đơn giản hóa logic để quản lý giao diện người dùng của bạn.

Tôi vẫn không thấy điều gì thực sự gây ra thứ gì đó hiển thị nhưng không thể nhận dữ liệu người dùng, nhưng tôi sẽ làm theo hướng dẫn đó trong tương lai.

2

Như tài liệu nói, "Nếu bạn không chắc chắn về một hoạt động đồ họa cụ thể, hãy lên kế hoạch thực hiện nó từ chuỗi chính của bạn".

Một nguyên tắc tốt để làm theo là, nếu một lớp học không được ghi rõ ràng là an toàn chỉ, thì có thể là không. Ngoài ra, mã không được ghi thành tài liệu an toàn chỉ có thể không bị lỗi nhanh khi được sử dụng bởi nhiều luồng, nhưng có thể chỉ biểu hiện hành vi không xác định, như bạn đã thấy.

0

Hầu như không có mã giao diện người dùng nào trong UIKit hoặc AppKit là luồng an toàn. Làm thế nào nó không thành công là không liên quan, bởi vì nếu bạn đang lo lắng về cách nó không bạn đang làm một cái gì đó mà sẽ dẫn đến tất cả các loại lỗi lạ sẽ thay đổi một cách tinh tế giữa các hệ điều hành khác nhau phát hành anyway.

Lời khuyên tốt nhất của tôi là không sử dụng mọi thứ từ chủ đề nền trừ khi các tài liệu nói là an toàn.

Các vấn đề liên quan