Bạn không hiểu mô hình luồng nhiều và có thể bạn sẽ tự bắn mình vào chân nếu bạn bắt đầu thêm mã không đồng bộ mà không thực sự hiểu những gì đang diễn ra.
Mã bạn đã viết chạy trong chuỗi ứng dụng chính. Nhưng khi bạn nghĩ về nó, bạn không phải viết hàm main
- bạn chỉ cần thực hiện ủy nhiệm ứng dụng và gọi lại sự kiện (chẳng hạn như trình xử lý cảm ứng) và bằng cách nào đó chúng chạy tự động khi thời gian đến. Đây không phải là một phép thuật, đây chỉ đơn giản là một đối tượng Cocoa gọi là Run Loop.
Chạy vòng lặp là đối tượng nhận tất cả các sự kiện, quá trình hẹn giờ (như trong NSTimer
) và chạy mã của bạn. Điều đó có nghĩa rằng khi bạn, ví dụ, làm điều gì đó khi người dùng chạm vào một nút, cây gọi trông hơi như thế này:
main thread running
main run loop
// fire timers
// receive events — aha, here we have an event, let’s call the handler
view::touchesBegan…
// use tapped some button, let’s fire the callback
someButton::touchUpInside
yourCode
Bây giờ yourCode
làm những gì bạn muốn làm và Run Vòng tiếp tục chạy. Nhưng khi mã của bạn mất quá nhiều thời gian để hoàn thành, chẳng hạn như trong trường hợp của bạn, Run Loop phải đợi và do đó các sự kiện sẽ không được xử lý cho đến khi mã của bạn kết thúc. Đây là những gì bạn thấy trong ứng dụng của bạn.
Để giải quyết tình huống, bạn phải chạy thao tác dài trong một chuỗi khác. Điều này không phải là rất khó, nhưng bạn sẽ phải suy nghĩ về một vài vấn đề tiềm năng.Chạy trong chủ đề khác có thể dễ dàng như gọi performSelectorInBackground
:
[appDelegate performSelectorInBackground:@selector(GetApps) withObject:nil];
Và bây giờ bạn phải nghĩ ra một cách để nói với ứng dụng dữ liệu đã được nạp, chẳng hạn như sử dụng một thông báo hoặc gọi một selector trên chính chủ đề. Bằng cách này: lưu trữ dữ liệu trong ứng dụng đại biểu (hoặc thậm chí sử dụng ứng dụng đại biểu để tải dữ liệu) không phải là giải pháp rất thanh lịch, nhưng đó là một câu chuyện khác.
Nếu bạn chọn giải pháp performSelectorInBackground
, hãy xem câu hỏi liên quan về memory management in secondary threads. Bạn sẽ cần hồ bơi tự động của riêng mình để bạn không bị rò rỉ các đối tượng tự động phát hiện.
Đang cập nhật câu trả lời sau một thời gian - ngày nay nó thường là tốt nhất để chạy mã trong nền sử dụng Grand Central Dispatch:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// No explicit autorelease pool needed here.
// The code runs in background, not strangling
// the main run loop.
[self doSomeLongOperation];
dispatch_sync(dispatch_get_main_queue(), ^{
// This will be called on the main thread, so that
// you can update the UI, for example.
[self longOperationDone];
});
});
Yea, tôi đã đọc lên những điều này, nhưng vẫn còn rất nhiều điều để hiểu, nhưng tôi sẽ hiểu, bạn đã đưa tôi đi đúng hướng. cảm ơn. Tôi đã sử dụng thành phần TBXML, vì vậy, tôi đoán tôi cần phải viết lên một cách đơn giản để hiểu cách nó hoạt động. anyway, Một câu hỏi khác có liên quan là, nếu người dùng chọn đóng chế độ xem, có cách nào để chấm dứt cuộc gọi selectorInBackground không? trên ViewDidUnload ..? – Sam
Điều đó phụ thuộc. Trong các trường hợp đơn giản, bạn chỉ có thể bỏ qua vấn đề và mã phần thông báo để nó không bị ngắt khi chế độ xem bị loại bỏ sớm. Một giải pháp chống đạn hơn có thể được viết bằng cách sử dụng chế độ 'NSURLConnection' không đồng bộ hoặc hàng đợi hoạt động, cả hai đều có một phương thức để hủy bỏ hoạt động đang tiến hành. – zoul
Đoạn mã cuối cùng thật tuyệt vời, đó chính là điều tôi đang tìm kiếm. Cảm ơn nhiều! – kisileno