2013-08-27 38 views
14

Tôi đang cố gắng hiểu tại sao không thể thực hiện thao tác UI bằng nhiều chuỗi. Đây có phải là yêu cầu trong các khung công tác khác như OpenGL hay cocos2d không?Tại sao các hoạt động UIKit phải được thực hiện trên luồng chính?

Làm thế nào về các ngôn ngữ khác như C# và javascript? Tôi đã cố gắng tìm kiếm trong google nhưng mọi người đề cập đến một cái gì đó về chủ đề POSIX mà tôi không hiểu.

Trả lời

13

Trong ca cao chạm, UIApplication tức là trường hợp ứng dụng của bạn được gắn vào sợi chính vì chuỗi này được tạo bởi UIApplicatioMain(), chức năng điểm nhập của Cocoa Touch. Nó thiết lập vòng lặp sự kiện chính, bao gồm vòng lặp chạy của ứng dụng và bắt đầu xử lý các sự kiện. vòng lặp sự kiện chính của ứng dụng nhận được tất cả các sự kiện UI tức liên lạc, cử chỉ, vv

Từ docs UIApplicationMain(),

Chức năng này instantiates đối tượng áp dụng từ lớp gốc và instantiates các đại biểu (nếu có) từ cho và đặt đại biểu cho ứng dụng. Nó cũng thiết lập vòng lặp sự kiện chính, bao gồm vòng lặp chạy của ứng dụng và bắt đầu xử lý các sự kiện. Nếu tệp Info.plist của ứng dụng chỉ định tệp nib chính cần tải, bằng cách bao gồm khóa NSMainNibFile và tên tệp nib hợp lệ cho giá trị, hàm này sẽ tải tệp nib đó.

Những sự kiện ứng dụng giao diện người dùng được tiếp tục chuyển tiếp đến UIResponder 's sau chuỗi phản ứng thường như UIApplication ->UIWindow ->UIViewController ->UIView -> subviews (UIButton, vv.)

Ứng xử lý sự kiện như nhấn nút, nhấn, thu phóng bằng pinch, vuốt v.v. được dịch là thay đổi trong giao diện người dùng. Do đó, bạn có thể thấy các chuỗi sự kiện này xảy ra trên luồng chính, đó là lý do tại sao UIKit, khuôn khổ chứa các trình đáp ứng nên hoạt động trên chuỗi chính.

Từ tài liệu một lần nữa UIKit,

Đối với hầu hết các phần, các lớp học UIKit nên chỉ được sử dụng từ chủ đề chính của ứng dụng. Điều này đặc biệt đúng đối với các lớp bắt nguồn từ UIResponder hoặc có liên quan đến việc thao tác với giao diện người dùng của ứng dụng của bạn theo bất kỳ cách nào.

EDIT

Tại sao drawRect cần phải được trên chủ đề chính?

drawRect: được gọi là UIKit là một phần của vòng đời UIView. Vì vậy, drawRect: bị ràng buộc với chủ đề chính. Vẽ theo cách này là tốn kém bởi vì nó được thực hiện bằng cách sử dụng CPU trên sợi chính. Đồ họa tăng tốc phần cứng được cung cấp bằng cách sử dụng kỹ thuật CALayer (Core Animation).

CALayer mặt khác đóng vai trò như một cửa hàng sao lưu cho chế độ xem. Sau đó, khung nhìn sẽ chỉ hiển thị bitmap được lưu trong bộ nhớ cache của trạng thái hiện tại của nó. Mọi thay đổi đối với thuộc tính chế độ xem sẽ dẫn đến thay đổi trong cửa hàng sao lưu được GPU thực hiện trên bản sao được sao lưu. Tuy nhiên, chế độ xem vẫn cần cung cấp nội dung ban đầu và cập nhật chế độ xem định kỳ. Tôi đã không thực sự làm việc trên OpenGL nhưng tôi nghĩ rằng nó cũng sử dụng các lớp (tôi có thể sai).

Tôi đã cố gắng trả lời điều này theo sự hiểu biết tốt nhất của mình. Hy vọng rằng sẽ giúp!

+0

Tôi đồng ý với hầu hết những gì bạn đã nói. Hãy để chúng tôi giả định rằng trả lời là về chủ đề chính và chúng tôi cần chủ đề chính để nhận các sự kiện nhưng những gì về rendering UIView? Tại sao chúng ta cần drawRect trên thread chính. Rất nhiều bản vẽ cũng có thể được thực hiện và tối ưu hóa bởi muti-threading tại sao khung UIKit không cho phép điều đó? Ngoài ra, tôi nghĩ rằng UIKIt là GPU tăng tốc sử dụng đa luồng. Tôi có thể sai về điều này. –

+0

@KunalBalani Vui lòng kiểm tra chỉnh sửa của tôi – Amar

+0

Xem http://stackoverflow.com/questions/21139300/having-uiview-drawrect-occur-in-a-background-thread –

-1

Vì bạn muốn người dùng có thể thấy các thay đổi giao diện người dùng khi chúng xảy ra. Nếu bạn có thể thực hiện thay đổi giao diện người dùng trong chuỗi nền và hiển thị chúng khi hoàn tất, có vẻ như ứng dụng không hoạt động đúng.

Tất cả các hoạt động phi UI (hoặc ít nhất là những người mà tôi rất tốn kém, như tải công cụ hoặc làm các truy vấn cơ sở dữ liệu) nên diễn ra trên một sợi nền, trong khi tất cả các giao diện người dùng thay đổi phải luôn luôn xảy ra trên thread chính để cung cấp trải nghiệm người dùng mượt mà.

Tôi không biết nó giống như thế nào trong C# cho các ứng dụng Windows Phone, nhưng tôi cho rằng nó sẽ giống nhau. Trên Android, hệ thống thậm chí sẽ không cho phép bạn làm những việc như tải xuống trên chuỗi chính, khiến bạn tạo trực tiếp chuỗi nền.

Theo quy tắc chung - khi bạn nghĩ chủ đề chính, hãy nghĩ "những gì người dùng nhìn thấy".

1

C# hoạt động giống nhau (xem ví dụ tại đây: Keep the UI thread responsive). Cập nhật giao diện người dùng phải được thực hiện trong chuỗi giao diện người dùng - hầu hết những thứ khác nên được thực hiện trong phần nền có thể.

Nếu điều đó sẽ không phải là trường hợp có lẽ sẽ là một địa ngục đồng bộ giữa tất cả các bản cập nhật mà phải được thực hiện trong giao diện người dùng ...

-1

Mỗi hệ thống, mỗi thư viện, cần phải được quan tâm về an toàn thread và phải làm mọi thứ để đảm bảo an toàn luồng, trong khi đồng thời tìm kiếm tính chính xác và hiệu suất.

Trong trường hợp giao diện người dùng iOS và MacOS X, quyết định đã được thực hiện để làm cho chuỗi giao diện người dùng an toàn bằng cách chỉ cho phép các phương thức giao diện người dùng được gọi và thực thi trên chuỗi chính. Và đó là nó.

Vì có rất nhiều điều phức tạp xảy ra cần ít nhất tuần tự hóa để ngăn chặn sự hỗn loạn xảy ra, tôi không thấy rất nhiều từ việc cho phép giao diện người dùng trên chuỗi nền.

1

từ: https://www.objc.io/issues/2-concurrency/thread-safe-class-design/

Đó là một quyết định thiết kế có ý thức từ phía Apple để không có UIKit được thread-safe. Làm cho chuỗi an toàn sẽ không mua cho bạn nhiều về hiệu suất; nó trong thực tế sẽ làm cho nhiều điều chậm hơn. Và thực tế là UIKit được gắn với chủ đề chính làm cho nó rất dễ dàng để viết các chương trình đồng thời và sử dụng UIKit. Tất cả những gì bạn phải làm là đảm bảo rằng các cuộc gọi vào UIKit luôn được thực hiện trên luồng chính.

Vì vậy, theo điều này thực tế là các đối tượng UIKit phải được truy cập trên luồng chính là quyết định thiết kế của táo để ưu tiên hiệu suất.

+0

Tôi không đồng ý với điều này. Đây là tất cả các nền tảng bao gồm symbian, android, blackberry và hầu hết chúng tồn tại trước iOS. Java servlets và các công cụ GUI khác cũng vậy. Chúng không bị giới hạn trên nền tảng di động. –

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