অবজেক্টিভ-সি দিয়ে রানটাইমের সময়ে কীভাবে আমি গতিশীলভাবে একটি নির্বাচক তৈরি করতে পারি?


93

আমি জানি কীভাবে SELসংকলনের সময় একটি তৈরি করতে হয় @selector(MyMethodName:)তবে আমি যা করতে চাই তা হ'ল একটি থেকে একটি নির্বাচনকারী নির্বাচন করুন NSString। এটা কি সম্ভব?

আমি কি করতে পারি:

SEL selector = @selector(doWork:);
[myobj respondsToSelector:selector];

আমি কী করতে চাই: (সিউডো কোড, এটি অবশ্যই কাজ করে না)

SEL selector = selectorFromString(@"doWork");
[myobj respondsToSelector:selector];

আমি অ্যাপল এপিআই ডক্স অনুসন্ধান করেছি, কিন্তু এমন কোনও উপায় খুঁজে পাইনি যা সংকলন-সময় @selector(myTarget:)সিনট্যাক্সের উপর নির্ভর করবে না ।

উত্তর:


180

আমি কোনও উদ্দেশ্য-সি প্রোগ্রামার নই, নিছক সহানুভূতিশীল, তবে সম্ভবত এনএসইলেক্টরফ্র্যামস্ট্রিং আপনার প্রয়োজন। রানটাইম রেফারেন্সে এটি স্পষ্টতার কথা উল্লেখ করেছে যা আপনি কোনও স্ট্রিংকে কোনও নির্বাচকের কাছে রূপান্তর করতে এটি ব্যবহার করতে পারেন।


5
আমার গুগল-ফুতে আমার ব্রাশ করা দরকার। আমি যা চেয়েছিলাম ঠিক সেটাই ছিল (বা এটি যেমন ছিল তেমন ছিল না)।
ক্রেগব

বেশ কয়েকদিন আগে আমি উদ্দেশ্য-সি 2.0 ডক্সের মাধ্যমে পড়েছি বলে আমার বুকমার্কগুলিতে আমার তখনও লিঙ্কগুলি উড়ন্ত ছিল।
টর্স্টেন মেরেক

40

এক্সকোড ডকুমেন্টেশন অনুসারে, আপনার স্যুইচুডকোডটি মূলত এটি ঠিক হয়ে যায়।

@ সিলেক্টর () নির্দেশিকার সাথে সংকলন সময়ে এসইএল ভেরিয়েবলগুলিতে মান নির্ধারণ করা সবচেয়ে দক্ষ। যাইহোক, কিছু ক্ষেত্রে, কোনও প্রোগ্রামের জন্য রানটাইমের সময় একটি চরিত্রের স্ট্রিংকে নির্বাচককে রূপান্তর করতে হবে। এটি এনএসএসইলেক্টর থেকে স্ট্রিং ফাংশন দিয়ে করা যেতে পারে:

setWidthHeight = NSSelectorFromString(aBuffer);

সম্পাদনা: বামার খুব ধীর। : পি


4
NSStringFromSelector(@"doWork")এটিকে অন্য উপায়ে রূপান্তর করে (কেবল
fyi

8
আমার মনে হয় আপনার অর্থ, এনএসএসটিংফ্র্যামসিলিটর (@ সিলেক্টর (ডু ওয়ার্ক))
জেএসওয়াইন

এবং সেই নির্বাচক অনুমিতভাবে কি করবেন? আমাদের কোনও ব্লক বা কিছু নির্দিষ্ট করা উচিত নয়?
user4951

13

আমি যে বলার আছে চাই এটা জটিল একটু বেশি চেয়ে পূর্ববর্তী উত্তরদাতাদের 'উত্তরগুলি পরামর্শ দিয়ে থাকি ... যদি তোমরা সত্যিই চাই একটি নির্বাচক তৈরি ... শুধু "Call একটি" আপনি "প্রায় ডিম্বপ্রসর করেছি" .. ।

আপনাকে একটি ফাংশন পয়েন্টার তৈরি করতে হবে যা আপনার "নতুন" পদ্ধতি দ্বারা ডাকা হবে .. সুতরাং কোনও পদ্ধতির জন্য যেমন [self theMethod:(id)methodArg];আপনি লিখতে চান ...

void (^impBlock)(id,id) = ^(id _self, id methodArg) { 
     [_self doSomethingWith:methodArg]; 
};

এবং তারপরে আপনার এই IMPব্লকটি গতিময়ভাবে জেনারেট করতে হবে , এবার, "স্ব", পাস SELএবং কোনও যুক্তি ...

void(*impFunct)(id, SEL, id) = (void*) imp_implementationWithBlock(impBlock);

এবং এটি আপনার ক্লাসে যুক্ত করুন, পুরো স্তন্যপায়ীটির জন্য সঠিক পদ্ধতির স্বাক্ষর সহ (এই ক্ষেত্রে "v@:@", অকার্যকর রিটার্ন, অবজেক্ট কলার, অবজেক্ট আর্গুমেন্ট)

 class_addMethod(self.class, @selector(theMethod:), (IMP)impFunct, "v@:@");

আপনি এই ধরণের রানটাইম শেননিগানগুলির কয়েকটি ভাল উদাহরণ দেখতে পাচ্ছেন , আমার একটি রেপোসে, এখানে।


5

আমি জানি এটির উত্তর অনেক আগে থেকেই দেওয়া হয়েছিল তবে এখনও আমি ভাগ করতে চাই। এটি ব্যবহার করেও করা sel_registerNameযায়।

প্রশ্নের উদাহরণ কোডটি আবার এভাবে লেখা যেতে পারে:

SEL selector = sel_registerName("doWork:");
[myobj respondsToSelector:selector];

4
আসলে, NSSelectorFromString@ টর্স্টেন-মারেকে উল্লেখ করেছেন sel_registerNameহুডের নীচে ব্যবহার । অ্যাপলেডেভ : "এনএসএসইলেক্টরফ্রস্ট্রস্ট্রিং সেলট্রেজিটারনেমে সেল্টরনামের একটি ইউটিএফ -8 এনকোডেড চরিত্রের উপস্থাপনাটি পাস করে এবং সেই ফাংশনটির দ্বারা প্রাপ্ত মানটি ফেরত দেয়"
পিএলজি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.