8

Đây là vấn đề đã khiến tôi lo lắng một thời gian. Tôi vẫn còn khá mới với một số các mẫu này, do đó bạn sẽ phải tha thứ cho tôi (và sửa tôi) nếu tôi sử dụng bất kỳ điều khoản nào không chính xác.Làm cách nào để triển khai mẫu định vị dịch vụ trong Cocoa Touch trên nhiều dự án?

My Phương pháp

tôi đã tạo ra một công cụ trò chơi. Tất cả các đối tượng trong công cụ trò chơi của tôi sử dụng đảo ngược kiểm soát để có được sự phụ thuộc. Tất cả các phụ thuộc này đều thực hiện các giao thức và không bao giờ được truy cập trực tiếp trong dự án, trừ trong giai đoạn bootstrapping. Để có được những vật thể này, tôi có khái niệm về một định vị dịch vụ. Công việc của dịch vụ định vị là định vị một đối tượng phù hợp với một giao thức cụ thể và trả về nó. Nó giống như một nhà máy, nhưng nó cũng phải xử lý các phụ thuộc.

Để cung cấp dịch vụ cho công cụ định vị dịch vụ, tôi có những gì tôi gọi là thông số dịch vụ. Trình định vị dịch vụ biết về tất cả các đặc tả dịch vụ trong dự án, và khi một đối tượng được yêu cầu, cố gắng lấy một cá thể của một đối tượng phù hợp với giao thức được cung cấp từ mỗi đối tượng. Đối tượng này sau đó được trả lại cho người gọi. Điều thú vị về việc thiết lập này là bộ định danh dịch vụ cũng biết về một trình định vị dịch vụ, vì vậy nếu nó có bất kỳ phụ thuộc nào, nó chỉ yêu cầu trình định vị dịch vụ cho các phụ thuộc cụ thể đó.

Để đưa ra một ví dụ, tôi có một đối tượng được gọi là HighScoreManager. HighScoreManager triển khai giao thức PHighScoreManager. Bất cứ lúc nào nếu một thể hiện của PHighScoreManager là cần thiết, nó có thể được lấy ra bằng cách gọi:

id<PHighScoreManager> highScoreManager = [ServiceLocator resolve: @protocol(PHighScoreManager)]; 

Do đó, đảo ngược tầm kiểm soát. Tuy nhiên, hầu hết thời gian thậm chí không cần thiết để làm điều này, bởi vì hầu hết các lớp đều nằm trong một trình chỉ định dịch vụ, nếu một lớp yêu cầu PHighScoreManager làm phụ thuộc, thì nó được truy lục thông qua bộ định vị dịch vụ. Vì vậy, tôi có một cách tiếp cận căn hộ tốt đẹp để đảo ngược kiểm soát.

My Vấn đề

Bởi vì tôi muốn mã từ công cụ trò chơi của tôi để được chia sẻ, tôi đã biên soạn nó như một thư viện tĩnh. Điều này làm việc tuyệt vời cho tất cả mọi thứ khác, nhưng có vẻ để có được một chút khó khăn với các dịch vụ định vị. Vấn đề là một số thay đổi dịch vụ trên cơ sở game đến game. Trong ví dụ trên của tôi, điểm số trong một trò chơi có thể là thời gian và một điểm khác có thể là điểm. Vì vậy, HighScoreManager phụ thuộc vào một thể hiện của PHighScoreCreator, nó cho nó biết cách tạo ra một objecct PScore.

Để cung cấp PHighScoreCreator cho HighScoreManager, tôi cần có thông số dịch vụ cho trò chơi của mình. Cách duy nhất tôi có thể nghĩ đến để thực hiện điều này là sử dụng phiên bản Ca cao phản xạ. Sau khi đào bới, tôi phát hiện ra các lớp học có thể phát hiện được thông qua NSBundle, nhưng có vẻ như không có cách nào để có được gói hiện tại. Vì vậy, nếu tôi muốn có thể tìm kiếm các đặc tả dịch vụ của mình, tôi sẽ phải biên dịch logic trò chơi của mình thành gói của riêng nó, và sau đó tìm kiếm công cụ này trong gói này và tải nó. Để làm được điều này, tôi phải tạo một dự án thứ ba để chứa cả mã động cơ và gói logic trò chơi, trong thực tế tôi muốn chỉ có một dự án trò chơi sử dụng thư viện tĩnh động cơ.

Câu hỏi Bất My

Vì vậy, sau khi tất cả điều đó, câu hỏi của tôi là

  1. Có cách nào tốt hơn để làm những gì tôi đang cố gắng để hoàn thành trong Cocoa Touch, hoặc
  2. Có cách nào để khám phá các lớp học phù hợp với giao thức quy định dịch vụ của tôi từ gói chính không?

Cảm ơn sự giúp đỡ và dành thời gian đọc câu hỏi.

-helixed

Trả lời

1

Có một cái nhìn tại địa chỉ:

  • + [NSBundle mainBundle];
  • + [NSBundle bundleForClass:];
  • + [Gói NSBundleWithIdentifier:];
  • + [NSBundle allBundles];
  • + [NSBundle allFrameworks];

Chúng cho phép bạn tương tác theo chương trình với các gói khác nhau khi chạy. Một khi bạn có một bó để làm việc với có một số chiến lược bạn có thể sử dụng để tìm các lớp cụ thể mà bạn đang tìm kiếm. Ví dụ:

  1. Truy xuất mã định danh gói - đây sẽ là NSString như @ "com.example.GameEngineClient".
  2. Chuyển đổi nó thành tên lớp Objective-C hợp pháp bằng cách xóa mọi thứ trước dấu chấm cuối cùng hoặc thay thế tất cả dấu chấm bằng dấu gạch dưới hoặc bất kỳ thứ gì và sau đó thêm tên giao thức được xác định trước. Giao thức của bạn từ trên cao, ví dụ, có thể dẫn đến một chuỗi như @ "GameEngineClient_PHighScoreManager".
  3. Nhận lớp được chỉ định của gói cho giao thức của bạn bằng cách sử dụng NSClassFromString().

Bây giờ bạn có thể tạo một thể hiện của lớp được cung cấp bởi tác giả gói, thực hiện bất kỳ giao thức nào bạn đã chỉ định.

Thời gian chạy Objective-C là một điều tuyệt vời!

+0

Tôi đã thử đi đường dẫn này và vấn đề là bạn không thể biết trước thời gian tên lớp sẽ được bao gồm trong gói. Do đó, bạn không thể lặp qua tất cả các lớp trong gói. – LandonSchropp

+0

Tôi đã chỉnh sửa câu trả lời để cung cấp một số đề xuất về việc cần làm tiếp theo sau khi bạn có một phiên bản NSBundle. Hi vọng điêu nay co ich. :-) –

+0

Tôi có cảm giác điều này có thể không được phép trong ứng dụng iPhone nhưng có thể tôi đã sai. Tôi khá chắc chắn táo không muốn bạn tải các lớp học tại thời gian chạy trên iPhone. Nhưng câu hỏi hay. –

1

Có vẻ như bạn cần sử dụng các chức năng của Objective-C runtime. Trước tiên, bạn có thể nhận danh sách tất cả các lớp học có sẵn qua objc_getClassList. Sau đó, bạn có thể lặp qua tất cả các lớp và kiểm tra xem chúng có tuân theo giao thức của bạn với class_conformsToProtocol hay không. Bạn không nên sử dụng +conformsToProtocol: thư ở đây vì có các lớp trong thời gian chạy không hỗ trợ công cụ chọn này.

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