8

यह एक समस्या है जो मुझे थोड़ी देर के लिए परेशान कर रही है। मैं अभी भी इन पैटर्न में से कुछ के साथ बहुत नया हूं इसलिए यदि आप किसी भी शब्द का गलत इस्तेमाल करते हैं तो आपको मुझे माफ कर देना होगा (और मुझे सही करें)।मैं कई परियोजनाओं में कोको टच में सेवा लोकेटर पैटर्न को कैसे कार्यान्वित कर सकता हूं?

मेरे क्रियाविधि

मैं एक खेल इंजन बना लिया है। मेरे गेम इंजन में सभी ऑब्जेक्ट्स निर्भरता प्राप्त करने के लिए नियंत्रण में उलटा उपयोग करते हैं। इन निर्भरताओं में सभी प्रोटोकॉल लागू होते हैं और बूटस्ट्रैपिंग चरण के अलावा, परियोजना में सीधे कभी नहीं पहुंचते हैं। इन वस्तुओं को प्राप्त करने के लिए, मेरे पास एक सेवा लोकेटर की अवधारणा है। सेवा लोकेटर का काम किसी ऑब्जेक्ट को ढूंढना है जो एक विशिष्ट प्रोटोकॉल के अनुरूप होता है और इसे वापस कर देता है। यह एक कारखाने की तरह है, लेकिन यह निर्भरताओं को भी संभालना चाहिए।

सेवा लोकेटर को सेवाएं प्रदान करने के लिए, मेरे पास सेवा विनिर्देशक कहते हैं। सेवा लोकेटर परियोजना में सभी सेवा विनिर्देशकों के बारे में जानता है, और जब किसी ऑब्जेक्ट का अनुरोध किया जाता है, तो उनमें से प्रत्येक से प्रदान किए गए प्रोटोकॉल के अनुरूप किसी ऑब्जेक्ट का उदाहरण प्राप्त करने का प्रयास किया जाता है। फिर यह ऑब्जेक्ट कॉलर को वापस कर दिया जाता है। इस सेट अप के बारे में क्या अच्छा है सेवा विनिर्देशक सेवा लोकेटर के बारे में भी जानता है, इसलिए यदि इसकी कोई निर्भरता है, तो यह केवल उन विशिष्ट निर्भरताओं के लिए सेवा लोकेटर से पूछता है।

उदाहरण देने के लिए, मेरे पास HighScoreManager नामक एक ऑब्जेक्ट है। HighScoreManager PHighScoreManager प्रोटोकॉल लागू करता है। किसी भी समय अगर PHighScoreManager का एक उदाहरण के लिए आवश्यक है, यह फोन करके प्राप्त किया जा सकता है:

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

इस प्रकार, नियंत्रण के उलट। हालांकि, अधिकांश समय ऐसा करने के लिए भी आवश्यक नहीं है, क्योंकि अधिकांश कक्षाएं सेवा विनिर्देशक में स्थित होती हैं, अगर किसी को एक निर्भरता के रूप में PHighScoreManager की आवश्यकता होती है, तो यह सेवा लोकेटर के माध्यम से पुनर्प्राप्त की जाती है। इस प्रकार, मेरे नियंत्रण में उलझन के लिए एक अच्छा फ्लैट दृष्टिकोण है।

मेरे समस्या

मैं चाहता हूँ क्योंकि मेरे खेल इंजन से कोड साझा करने के लिए, मैं इसे एक स्थिर पुस्तकालय के रूप में तैयार की है। यह सब कुछ के लिए कमाल काम करता है, लेकिन सेवा लोकेटर के साथ थोड़ा मुश्किल लगता है। समस्या यह है कि गेम पर गेम के आधार पर कुछ सेवाएं बदलती हैं। मेरे उपर्युक्त उदाहरण में, एक गेम में स्कोर एक समय हो सकता है और दूसरे में यह अंक हो सकता है। इस प्रकार, हाईस्कोर मैनेजर PHighScoreCreator के उदाहरण पर निर्भर करता है, जो यह बताता है कि कैसे एक पीएसकोर objecct बनाने के लिए।

हाईस्कोर मैनेजर को PHighScoreCreator प्रदान करने के लिए, मुझे अपने गेम के लिए एक सेवा विनिर्देशक होना चाहिए। इसे पूरा करने के बारे में सोचने का एकमात्र तरीका प्रतिबिंब के कोको संस्करण का उपयोग करना था। चारों ओर खोदने के बाद, मुझे पता चला कि कक्षाएं एनएसबंडल के माध्यम से खोजने योग्य थीं, लेकिन ऐसा लगता है कि वर्तमान बंडल पाने का कोई तरीका नहीं है। इस प्रकार, अगर मैं अपने सेवा विनिर्देशों को खोजने में सक्षम होना चाहता हूं, तो मुझे अपने गेम तर्क को अपने बंडल में संकलित करना होगा, और फिर इंजन को इस बंडल को खोजना होगा और इसे लोड करना होगा। ऐसा करने के लिए मुझे इंजन कोड और गेम लॉजिक बंडल दोनों को घर बनाने के लिए एक तीसरी परियोजना बनाना होगा, जब वास्तव में मैं सिर्फ एक गेम प्रोजेक्ट बनाना चाहता हूं जो इंजन स्थैतिक पुस्तकालय का उपयोग करता है।

मेरे असली सवाल

तो यह सब के बाद, मेरे सवाल का

  1. वहाँ क्या मैं कोको टच में पूरा करने के लिए कोशिश कर रहा हूँ करने के लिए एक बेहतर तरीका है, या
  2. क्या कक्षाओं को खोजने का कोई तरीका है जो मुख्य बंडल से मेरे सेवा विनिर्देश प्रोटोकॉल के अनुरूप है?

मदद के लिए धन्यवाद और प्रश्न पढ़ने के लिए समय लेना।

-helixed

उत्तर

1

पर एक नज़र डालें:

  • + [NSBundle mainBundle];
  • + [एनएसबंडल बंडलफॉर क्लास:];
  • + [एनएसबंडल बंडलविथ इंडेंटिफायर:];
  • + [एनएसबंडल ऑलबंडल्स];
  • + [एनएसबंडल allFrameworks];

ये आपको रनटाइम पर विभिन्न बंडलों के साथ प्रोग्रामेटिक रूप से बातचीत करने की अनुमति देते हैं। एक बार आपके पास काम करने के लिए एक बंडल हो जाने के बाद आप कई विशिष्ट रणनीतियों को ढूंढ सकते हैं जिन्हें आप विशिष्ट वर्ग (एसएस) ढूंढने के लिए नियोजित कर सकते हैं। उदाहरण के लिए:

  1. बंडल पहचानकर्ता को पुनर्प्राप्त करें - यह @ "com.example.GameEngineClient" जैसे एनएसएसटींग होगा।
  2. इसे अंतिम बिंदु से पहले सब कुछ अलग करके, या अंडरस्कोर के साथ सभी बिंदुओं को बदलने या फिर एक पूर्वनिर्धारित प्रोटोकॉल नाम को जोड़कर कानूनी उद्देश्यों-सी कक्षा के नाम में परिवर्तित करें। उदाहरण के लिए, उपर्युक्त से आपका प्रोटोकॉल परिणामस्वरूप "स्ट्रिंग" @ GameEngineClient_PHighScoreManager "हो सकता है।
  3. NSClassFromString() का उपयोग करके अपने प्रोटोकॉल के लिए बंडल की नामित कक्षा प्राप्त करें।

अब आप बंडल लेखक द्वारा प्रदान की गई कक्षा का एक उदाहरण बना सकते हैं, जो आपके द्वारा निर्दिष्ट प्रोटोकॉल को लागू करता है।

उद्देश्य-सी रनटाइम एक सुंदर चीज़ है!

+0

मैंने इस पथ पर जाने की कोशिश की और समस्या यह है कि आप समय से पहले नहीं जान सकते कि बंडल में किस वर्ग के नाम शामिल किए जाएंगे। इसलिए, आप बंडल में सभी कक्षाओं के माध्यम से पुन: प्रयास नहीं कर सकते हैं। – LandonSchropp

+0

मैंने एनएसबंडल इंस्टेंस के बाद आगे क्या करना है इसके बारे में कुछ सुझाव देने के लिए उत्तर संपादित किया है। उम्मीद है की यह मदद करेगा। :-) –

+0

मुझे एहसास है कि इसे किसी iPhone ऐप में अनुमति नहीं दी जा सकती है, लेकिन मैं गलत हो सकता हूं। मुझे पूरा यकीन है कि सेब नहीं चाहता कि आप आईफोन पर रनटाइम पर कक्षाएं लोड कर रहे हों। लेकिन महान सवाल है। –

1

लगता है जैसे आपको Objective-C runtime के कार्यों का उपयोग करने की आवश्यकता है। सबसे पहले आप objc_getClassList के माध्यम से सभी उपलब्ध कक्षाओं की एक सूची प्राप्त कर सकते हैं। फिर आप सभी कक्षाओं में पुन: प्रयास कर सकते हैं और जांच सकते हैं कि वे class_conformsToProtocol के साथ आपके प्रोटोकॉल के अनुरूप हैं या नहीं। आपको +conformsToProtocol: संदेशों का उपयोग नहीं करना चाहिए, क्योंकि रनटाइम में कक्षाएं हैं जो इस चयनकर्ता का समर्थन नहीं करती हैं।