2012-06-20 19 views
16

Tôi biết UIView không phải là chủ đề an toàn vì vậy tôi không thể thêm một chế độ xem trên một chủ đề nền, để làm việc xung quanh điều này là nó ok để tạo ra một UIView trên một chủ đề nền sau đó thêm nó vào chủ đề chính?Bạn có muốn tạo UIView trên một chủ đề nền không?

Lưu ý: lý do im không làm điều này trên chủ đề chính là vì mã thực sự của tôi phức tạp hơn nhiều và do đó phải mất một lúc để tạo tất cả các chế độ xem và điền vào các giá trị. Tôi không muốn giao diện người dùng trở nên không đáp ứng khi tôi làm điều này vì vậy tôi đang cố gắng giải quyết vấn đề này.

ví dụ ..

-(void)addLabel//called on background thread 
{ 
    UILabel * label = [[UILabel alloc]initWithFrame:CGRectMake(0,0,40,100)]; 
    [label setText:@"example"] 
    [self.view performSelector:@selector(addSubview:) onThread:[NSThread mainThread] withObject:example waitUntilDone:YES]; 
} 

Cảm ơn trước.

+0

Tôi tin rằng bạn có chính xác. Tạo nó trên nền nhưng cập nhật giao diện người dùng trên chính. –

Trả lời

15

Từ UIView:

Threading cân nhắc

thao tác với giao diện người dùng của ứng dụng của bạn phải xảy ra trên các chủ đề chính. Vì vậy, bạn nên luôn luôn gọi các phương thức của lớp UIView từ mã đang chạy trong luồng chính của ứng dụng của bạn. Thời gian duy nhất điều này có thể không thực sự cần thiết là khi tạo đối tượng xem, nhưng tất cả các thao tác khác sẽ xảy ra trên luồng chính.

Cuộc gọi đến initWithFrame: rõ ràng không phải là chủ đề an toàn. Cuộc gọi tới số setText: có thể không an toàn với chuỗi, nằm trong mệnh đề "thao tác". Đây chắc chắn không phải là hứa hẹn để được thread-an toàn.

Làm việc của bạn để tìm ra dữ liệu trên một chuỗi nền. Sau đó tạo các khung nhìn của bạn trên chuỗi chính. Nếu có một số lượng lớn lượt xem, bạn có thể thử chia nhỏ công việc bằng cách sử dụng một số cuộc gọi dispatch_async() vào hàng đợi chính. Điều này có thể cho phép giao diện người dùng vẫn đáp ứng; Tôi đã không thử nghiệm rộng rãi với nó.

Bạn cũng có thể xem xét chuyển từ UIView sang CALayer nếu có thể. Hầu hết các công việc CALayer có thể được thực hiện trên các chủ đề nền. Nếu bạn có một số lượng lớn các lượt xem, điều đó có thể không hiệu quả. Nếu chỉ mất một thời gian dài để tính toán dữ liệu cho các chế độ xem, điều đó cho thấy bạn không tách riêng thông tin Mô hình và Chế độ xem. Các lớp Model nên tính toán mọi thứ cần thiết một cách độc lập với việc tạo các khung nhìn.

+5

Tôi xin lỗi nhưng bạn có thể làm rõ câu trả lời của mình ? Trích dẫn từ táo đặc biệt nói rằng việc tạo ra một khung cảnh trong nền là ổn, nhưng bạn đang nói nó không phải. Tại sao? –

+0

@iamataptool có lẽ bạn có thể tạo UIView một cách an toàn với phương thức 'init' nhưng không phải với phương thức' initWithFrame: '? – DanSkeel

+0

Mẹo của CALayer thực hiện ngày và tuần của tôi. Cảm ơn rất nhiều! –

0

Các Drawing and Printing Guide trạng thái:

Quan trọng Các lớp UIKit thường không được đề an toàn. Tất cả các thao tác liên quan đến bản vẽ phải được thực hiện trên chuỗi chính của ứng dụng của bạn.

Vì vậy, khi tôi hiểu điều này, có vẻ như vấn đề duy nhất liên quan đến "hoạt động liên quan đến bản vẽ". Nếu chúng ta giả định rằng một lớp đúng chỉ thực hiện thao tác như vậy trong phương thức drawRect: của nó, thì cách tiếp cận mà bạn đề xuất sẽ ổn.

+0

Trong trường hợp của tôi, ứng dụng của tôi đang tỉnh dậy thông qua 'UIApplicationLaunchOptionsLocalNotificationKey', do đó, nó ở chế độ nền. Có ok không, Nếu tôi thực hiện các phần bổ sung phụ khi ứng dụng ở chế độ nền? https://stackoverflow.com/questions/46584566/how-to-stop-handle-ui-operations-in-ios-when-app-moves-to-background-state – Nil

3

Tôi sử dụng Xcode phiên bản 9.0 beta 3 (9M174d), nhận cảnh báo.

[UView init] phải được gọi từ chủ đề chính chỉ

Vì vậy, tôi nghĩ rằng bạn nên tạo UI trong chủ đề chính tốt hơn

Hiện hình dưới đây:

enter image description here