NSDefaultRunLoopMode so với NSRunLoopCommonModes


114

Bất cứ khi nào tôi cố gắng để tải về một tập tin đằng sau lớn UIScrollView, MPMapViewhoặc một cái gì đó, quá trình tải bị dừng lại ngay sau khi tôi chạm vào màn hình iPhone. Rất may, một bài đăng trên blog tuyệt vời của Jörn gợi ý một tùy chọn thay thế, sử dụng NSRunLoopCommonModesđể kết nối.

Điều đó giúp tôi xem xét chi tiết về hai chế độ, NSDefaultRunLoopMode và NSRunLoopCommonModes, nhưng tài liệu apple không vui lòng giải thích, ngoài việc nói

NSDefaultRunLoopMode

Chế độ xử lý các nguồn đầu vào khác với các đối tượng NSConnection. Đây là chế độ chạy vòng lặp được sử dụng phổ biến nhất.

NSRunLoopCommonModes

Các đối tượng được thêm vào vòng chạy bằng cách sử dụng giá trị này vì chế độ được giám sát bởi tất cả các chế độ vòng chạy đã được khai báo là thành viên của tập hợp các chế độ “chung”; xem mô tả của CFRunLoopAddCommonMode để biết chi tiết.

CFRunLoopAddCommonMode

Nguồn, bộ định thời và bộ quan sát được đăng ký vào một hoặc nhiều chế độ vòng chạy và chỉ chạy khi vòng chạy đang chạy ở một trong các chế độ đó. Các chế độ chung là một tập hợp các chế độ vòng lặp chạy mà bạn có thể xác định một tập hợp các nguồn, bộ hẹn giờ và bộ quan sát được chia sẻ bởi các chế độ này. Ví dụ: thay vì đăng ký một nguồn cho từng chế độ vòng lặp chạy cụ thể, bạn có thể đăng ký một lần nó vào chế độ giả phổ biến của vòng chạy và nó sẽ được tự động đăng ký trong mỗi chế độ vòng lặp chạy trong chế độ chung được đặt. Tương tự như vậy, khi một chế độ được thêm vào tập hợp các chế độ chung, mọi nguồn, bộ hẹn giờ hoặc người quan sát đã được đăng ký với chế độ giả phổ biến sẽ được thêm vào chế độ chung mới được thêm vào.

Bất cứ ai có thể vui lòng giải thích hai bằng ngôn ngữ của con người?

Câu trả lời:


204

Vòng lặp chạy là một cơ chế cho phép hệ thống đánh thức các luồng đang ngủ để chúng có thể quản lý các sự kiện không đồng bộ. Thông thường khi bạn chạy một luồng (ngoại trừ luồng chính), có một tùy chọn để bắt đầu luồng đó trong một vòng lặp chạy hoặc không. Nếu chuỗi chạy một số sắp xếp hoặc hoạt động kéo dài mà không có tương tác với các sự kiện bên ngoài và không có bộ định thời, bạn không cần vòng lặp chạy, nhưng nếu chuỗi của bạn cần phản hồi các sự kiện đến, nó phải được gắn vào vòng lặp chạy để đánh thức chuỗi khi có sự kiện mới. Đây là trường hợp của các NSURLConnectionluồng được tạo, vì chúng chỉ đánh thức khi có các sự kiện đến (từ mạng).

Mỗi luồng có thể được liên kết với nhiều vòng lặp, hoặc có thể được liên kết với một vòng chạy cụ thể có thể được thiết lập để hoạt động ở các chế độ khác nhau. "Chế độ vòng lặp chạy" là một quy ước được OS sử dụng để thiết lập một số quy tắc về thời điểm cung cấp các sự kiện nhất định hoặc thu thập chúng để được phân phối sau đó.

Thông thường tất cả các vòng chạy được đặt ở "chế độ mặc định", thiết lập một cách mặc định để quản lý các sự kiện đầu vào. Ví dụ: ngay sau khi sự kiện kéo chuột (Mac OS) hoặc chạm (trên iOS) xảy ra thì chế độ cho vòng chạy này được đặt thành theo dõi sự kiện; điều này có nghĩa là luồng sẽ không được đánh thức trên các sự kiện mạng mới nhưng những sự kiện này sẽ được phân phối sau đó khi sự kiện đầu vào của người dùng kết thúc và vòng lặp chạy lại được đặt thành chế độ mặc định; rõ ràng đây là một lựa chọn của các kiến ​​trúc sư hệ điều hành để ưu tiên cho các sự kiện của người dùng thay vì các sự kiện nền.

Nếu bạn quyết định thay đổi chế độ vòng chạy cho NSURLConnectionluồng của mình , bằng cách sử dụng scheduleInRunLoop:forModes:, thì bạn có thể gán luồng cho một chế độ vòng chạy đặc biệt , thay vì vòng chạy mặc định cụ thể. Chế độ giả đặc biệt được gọi NSRunLoopCommonModeslà được sử dụng bởi nhiều nguồn đầu vào bao gồm theo dõi sự kiện. Ví dụ: gán NSURLConnectionphiên bản của cho chế độ chung có nghĩa là liên kết các sự kiện của nó với "chế độ theo dõi" ngoài "chế độ mặc định". Một ưu điểm / nhược điểm của việc liên kết các luồng NSRunLoopCommonModeslà luồng sẽ không bị chặn bởi các sự kiện chạm.

Các chế độ mới có thể được thêm vào các chế độ thông thường, nhưng đây là một hoạt động ở mức khá thấp.

Tôi muốn kết thúc bằng cách thêm một số ghi chú:

  • Thông thường, chúng ta cần sử dụng một tập hợp các hình ảnh hoặc hình thu nhỏ được tải xuống từ mạng với chế độ xem bảng. Chúng tôi có thể nghĩ rằng việc tải xuống những hình ảnh này từ mạng trong khi chế độ xem bảng đang cuộn có thể cải thiện trải nghiệm người dùng (vì chúng tôi có thể nhìn thấy hình ảnh trong khi cuộn), nhưng điều này không có lợi vì tính linh hoạt của việc cuộn có thể bị ảnh hưởng rất nhiều. Trong ví dụ này với NSURLConnectionmột vòng lặp chạy không nên được sử dụng; sẽ tốt hơn nếu sử dụng các UIScrollViewphương thức ủy quyền để phát hiện khi kết thúc cuộn và sau đó cập nhật bảng và tải xuống các mục mới từ mạng;

  • Bạn có thể cân nhắc sử dụng GCD để giúp bạn "che chắn" mã của mình khỏi các vấn đề quản lý vòng lặp chạy. Trong ví dụ trên, bạn có thể cân nhắc việc thêm các yêu cầu mạng của mình vào một hàng đợi nối tiếp tùy chỉnh.


9
Viggio24 thân mến, cảm ơn bạn rất nhiều vì lời giải thích rõ ràng và chính xác này. Tôi sẽ yêu cầu Apple đưa nhận xét của bạn vào hướng dẫn API của họ. ;)
Stkim1

7
câu trả lời của viggio24 là hoàn hảo. Đối với những người quan tâm, tôi sẽ chỉ ra rằng Phiên 208 (Ứng dụng mạng cho iPhone OS, Phần 2) từ WWDC 2010 chứa phần giới thiệu về các vòng chạy. Nếu bạn quan tâm hãy xem. Hy vọng nó giúp.
Lorenzo B

19
Chỉ cần một lưu ý cho bản thân tôi: NSRunLoopCommonModescho phép sự kiện hẹn giờ trong khi cuộn vào UIScrollView. NSDefaultRunLoopModengăn chặn bộ đếm thời gian trong khi cuộn.
eonil,

2
Tôi thấy rất thú vị khi nhận xét về bản cập nhật chế độ xem cuộn, vì nó đề cập đến một chủ đề rất thách thức. Chỉ để thêm các chi tiết khác về điều này: Khi bạn đặt chế độ cho Kết nối NSURLC, điều này chỉ ảnh hưởng đến việc thực thi các lệnh gọi lại được ủy quyền. Tôi hiểu rằng việc cập nhật scrollView ở đây có thể dẫn đến sự cố về hiệu suất, nhưng tại sao điều này lại xảy ra? Nếu câu trả lời là hình ảnh phải được tải vào bộ nhớ, bạn có thể làm điều đó bằng cách ghi vào bối cảnh đồ họa trên nền và cập nhật lớp luồng chính của chế độ xem sau khi thực hiện việc này. điều này nghe có hợp lý không?
nebillo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.