-পারফর্মসিলিেক্টর ব্যবহার করে: বনাম। কেবল পদ্ধতিটি কল করা


116

আমি এখনও অবজেক্টিভ-সি-তে নতুন ধরনের আছি এবং আমি ভাবছি যে নিম্নলিখিত দুটি বিবৃতিগুলির মধ্যে পার্থক্য কী?

[object performSelector:@selector(doSomething)]; 

[object doSomething];

উত্তর:


191

মূলত পারফরম্যাসলেক্টর আপনাকে নির্বাচিতকে প্রদত্ত বস্তুতে কোন নির্বাচককে কল করতে ডায়নামিকভাবে নির্ধারণ করতে দেয়। অন্য কথায় রানটাইমের আগে নির্বাচককে নির্ধারণ করা দরকার না।

এগুলি সমতুল্য হলেও:

[anObject aMethod]; 
[anObject performSelector:@selector(aMethod)]; 

দ্বিতীয় ফর্মটি আপনাকে এটি করতে দেয়:

SEL aSelector = findTheAppropriateSelectorForTheCurrentSituation();
[anObject performSelector: aSelector];

আপনি বার্তা প্রেরণের আগে।


3
এটি উল্লেখ করার মতো যে আপনি প্রকৃতপক্ষে TheEP उचितSelectorForCCreCituation () এর ফলাফলটি একজন নির্বাচককে অর্পণ করবেন, তারপরে [anObject সঞ্চালনকারী নির্বাচন করুন: একটি নির্বাচনকারী]। @ নির্বাচনকারী একটি এসইএল উত্পাদন করে।
ড্যানিয়েল ইয়াঙ্কোভস্কি

4
ব্যবহার performSelector:এমন কিছু যা আপনি সম্ভবত আপনার ক্লাসে লক্ষ্য-অ্যাকশন প্রয়োগ করলেই সম্ভব হয়। ভাইবোন performSelectorInBackground:withObject:এবং performSelectorOnMainThread:withObject:waitUntilDone:প্রায়শই আরও দরকারী। একটি ব্যাকগ্রাউন্ড থ্রেড তৈরি করার জন্য, এবং উল্লিখিত ব্যাকগ্রাউন্ড থ্রেড থেকে মূল থ্রেডে ফলাফলগুলি আবার কল করার জন্য।
পেইলডাব্লু

2
performSelectorসতর্কতা সংকলন দমন করতে দরকারী। যদি আপনি জানেন যে পদ্ধতিটি বিদ্যমান রয়েছে (যেমন ব্যবহারের পরে respondsToSelector) তবে এটি Xcode কে "প্রতিক্রিয়া জানাতে পারে না" বলতে বাধা দেবে your_selector। সতর্কতার আসল কারণটি অনুসন্ধান করার পরিবর্তে এটি ব্যবহার করবেন না । ;)
মার্চ

আমি স্ট্যাকওভারফ্লোতে অন্য কিছু থ্রেডে পড়েছিলাম যে পারফরম্যান্সলেক্টর ব্যবহারটি একটি ভয়াবহ ডিজাইনের প্রতিচ্ছবি এবং এটিতে প্রচুর থাম্ব ছিল। আমি আশা করি আমি এটি আবার খুঁজে পেতে পারে। আমি গুগল অনুসন্ধান করেছি, ফলাফলগুলি স্ট্যাকওভারফ্লোতে সীমাবদ্ধ রেখেছি এবং 18,000 ফলাফল পেয়েছি। Eww।
লজিকসৌরাস রেক্স

"একটি ভয়ঙ্কর ডিজাইনের প্রতিচ্ছবি" অত্যধিক সরল istic ব্লকগুলি উপলভ্য হওয়ার আগে আমাদের যা ছিল এটি ছিল এবং সমস্ত ব্যবহারগুলি তখন বা এখন খারাপ হয় না। যদিও এখন যে ব্লক হয় পাওয়া যায়, যে সম্ভবত নতুন কোড যদি না আপনি খুব সহজ কিছু করছ জন্য একটি ভাল পছন্দ।
এথন

16

এই প্রশ্নের খুব প্রাথমিক উদাহরণের জন্য,

[object doSomething];
[object performSelector:@selector(doSomething)]; 

যা হতে চলেছে তাতে কোনও পার্থক্য নেই। doSomething সিঙ্ক্রোনজ করে অবজেক্ট দ্বারা কার্যকর করা হবে। কেবলমাত্র "ডসোমিংথিং" একটি খুব সহজ পদ্ধতি, এটি কোনও কিছুই ফেরায় না এবং কোনও প্যারামিটারের প্রয়োজন হয় না।

এটি কি আরও কিছু জটিল ছিল, যেমন:

(void)doSomethingWithMyAge:(NSUInteger)age;

জিনিসগুলি জটিল হয়ে উঠবে, কারণ [অবজেক্টটি ডুসিংথিংথওয়াইথ মাইএজ: 42];

আর "পারফরমেসিলেক্টর" এর কোনও বৈকল্পিকের সাথে আর ডাকা যাবে না, কারণ পরামিতিগুলির সাথে সমস্ত বৈকল্পিক কেবলমাত্র বস্তুর পরামিতি গ্রহণ করে।

এখানে নির্বাচক হবেন "doSomethingWithMyAge:" তবে কোনও প্রচেষ্টা

[object performSelector:@selector(doSomethingWithMyAge:) withObject:42];  

কেবল সংকলন করা হবে না। এনএসএনম্বারটি পাস করা: 42 এর পরিবর্তে @ (42) কোনওভাবেই সহায়তা করবে না, কারণ পদ্ধতিটি একটি মৌলিক সি প্রকারের প্রত্যাশা করে - কোনও বস্তু নয়।

এছাড়াও, 2 টি পরামিতি পর্যন্ত সঞ্চালনকারী বৈকল্পিক রয়েছে, আর নেই। যদিও পদ্ধতিগুলিতে অনেক সময় আরও অনেকগুলি পরামিতি থাকে।

আমি খুঁজে পেয়েছি যে পারফেক্টস সিলেক্টরের সিঙ্ক্রোনাস ভেরিয়েন্টগুলি:

- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

সর্বদা কোনও বস্তু ফিরিয়ে দিন, আমি একটি সাধারণ BOOL বা NSUIntegerও ফিরিয়ে দিতে সক্ষম হয়েছি এবং এটি কার্যকর হয়েছে।

পারফেক্টসলেক্টরের দুটি প্রধান ব্যবহারের মধ্যে একটি হল পূর্ববর্তী উত্তরে বর্ণিত হিসাবে আপনি যে পদ্ধতিটি কার্যকর করতে চান তার নাম গতিময়ভাবে রচনা করা। উদাহরণ স্বরূপ

 SEL method = NSSelectorFromString([NSString stringWithFormat:@"doSomethingWithMy%@:", @"Age");
[object performSelector:method];

অন্য ব্যবহারটি হ'ল সংক্ষিপ্ত আকারে আপত্তি জানাতে একটি বার্তা প্রেরণ করা, এটি বর্তমান রান-লুপ পরে কার্যকর করা হবে। এর জন্য, আরও বেশ কয়েকটি পারফর্মস্লেেক্টর বৈকল্পিক রয়েছে।

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes;
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;
- (void)performSelector:(SEL)aSelector target:(id)target argument:(id)arg order:(NSUInteger)order modes:(NSArray *)modes;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;
- (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg;

(হ্যাঁ আমি এগুলি এনএসটিস্ট্রেড, এনএসরুনলুপ এবং এনএসবজেক্টের মতো কয়েকটি ফাউন্ডেশন শ্রেণির বিভাগ থেকে সংগ্রহ করেছি)

প্রতিটি ভেরিয়েন্টের নিজস্ব নিজস্ব আচরণ রয়েছে তবে সবগুলি কিছু মিলিয়ে ভাগ করে নেয় (কমপক্ষে ওয়েটউন্টিলডোন কোনও ক্ষেত্রে সেট করা থাকে না)। "পারফরমেন্সলেক্টর" কলটি তত্ক্ষণাত্ ফিরে আসত এবং আপত্তি করার বার্তাটি কিছু সময়ের পরে কেবল বর্তমান রানলুপে রাখা হবে।

বিলম্বিত কার্যকর হওয়ার কারণে - স্বাভাবিকভাবে কোনও নির্বাচনের পদ্ধতি অনুসারে কোনও রিটার্ন মান উপলব্ধ হয় না, সুতরাং এই সমস্ত অ্যাসিনক্রোনাস বৈকল্পিকগুলিতে - (অকার্যকর) ফেরতের মান value

আমি আশা করি আমি এটি কোনওভাবে কভার করেছি ...


12

@ennuikiller স্পট ইন রয়েছে। মূলত, গতিশীলভাবে উত্পন্ন নির্বাচিতরা যখন আপনি কোডটি সংকলন করবেন তখন যে পদ্ধতিটির নাম আপনি কল করবেন সেটির নামটি (এবং সাধারণত সম্ভবত সম্ভব নয়) জানেন না for

একটি মূল পার্থক্য হ'ল -performSelector:এবং বন্ধুরা ( বহু-থ্রেডযুক্ত এবং বিলম্বিত রূপগুলি সহ ) কিছুটা সীমিত যে এগুলি 0-2 পরামিতি সহ পদ্ধতিগুলির সাথে ব্যবহারের জন্য ডিজাইন করা হয়েছে। উদাহরণস্বরূপ, -outlineView:toolTipForCell:rect:tableColumn:item:mouseLocation:6 টি প্যারামিটারের সাথে কল করা এবং ফেরত দেওয়া NSStringবেশ অযৌক্তিক, এবং সরবরাহিত পদ্ধতির দ্বারা সমর্থিত নয়।


5
এটি করতে, আপনাকে একটি NSInvocationঅবজেক্ট ব্যবহার করতে হবে ।
ডেভ দেলং

6
আর একটি পার্থক্য: performSelector:এবং বন্ধুরা সকলেই বস্তুর যুক্তি গ্রহণ করে, যার অর্থ আপনি তাদের কল করতে ব্যবহার করতে পারবেন না (উদাহরণস্বরূপ) setAlphaValue:, কারণ এটির যুক্তিটি ভাসমান।
চক

4

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

একটি NSInvocationছাড়া এটি binds একসঙ্গে অধিক বিবরণের একটি অনুরূপ উদ্দেশ্য করে তোলে। এটি কেবল ক্রিয়া অংশকেই অন্তর্ভুক্ত করে না, এতে লক্ষ্য বস্তু এবং পরামিতিগুলিও অন্তর্ভুক্ত থাকে। আপনি যখন এখনই নয় ভবিষ্যতে নির্দিষ্ট পরামিতিগুলির সাথে কোনও নির্দিষ্ট অবজেক্টে কোনও পদ্ধতিতে কল করতে চান এটি দরকারী। আপনি একটি উপযুক্ত তৈরি করতে পারেন NSInvocationএবং এটি পরে ফায়ার করতে পারেন ।


5
নির্বাচকরা আসলে কোনও ফাংশন পয়েন্টারের মতো নয় যে ফাংশন পয়েন্টার এমন কিছু যা আপনি যুক্তি দিয়ে কল করতে পারেন এবং কোনও নির্বাচক এটি প্রয়োগকারী যে কোনও বস্তুর উপর একটি বিশেষ পদ্ধতি কল করতে ব্যবহার করতে পারেন; কোনও নির্বাচকের কাছে ফাংশন পয়েন্টারের মতো অনুরোধের সম্পূর্ণ প্রসঙ্গ থাকে না।
বুবুম

1
নির্বাচকরা ফাংশন পয়েন্টারগুলির মতো নয়, তবে আমি এখনও মনে করি তারা একই রকম। তারা ক্রিয়া প্রতিনিধিত্ব করে। সি ফাংশন পয়েন্টারগুলি ক্রিয়াগুলিও উপস্থাপন করে। অতিরিক্ত প্রসঙ্গে ছাড়া কোনওটিই কার্যকর নয়। নির্বাচকদের একটি অবজেক্ট এবং পরামিতি প্রয়োজন; ফাংশন পয়েন্টারগুলির জন্য প্যারামিটারগুলির প্রয়োজন হয় (এতে কোনও অপারেট পরিচালনা করতে পারে যা পরিচালনা করতে পারে)। আমার বক্তব্যটি হাইলাইট করা ছিল যে তারা কীভাবে এনএসআইভোকেশন অবজেক্ট থেকে আলাদা, যাতে সমস্ত প্রয়োজনীয় প্রসঙ্গ থাকে। সম্ভবত আমার তুলনা বিভ্রান্তিকর ছিল, সেই ক্ষেত্রে আমি ক্ষমা চাইছি।
ড্যানিয়েল ইয়াঙ্কোভস্কি

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

-7

দুজনের মধ্যে আরও একটি সূক্ষ্ম পার্থক্য রয়েছে।

    [object doSomething]; // is executed right away

    [object performSelector:@selector(doSomething)]; // gets executed at the next runloop

অ্যাপল ডকুমেন্টেশন থেকে এখানে উদ্ধৃত অংশ

"সঞ্চালনকারী: উইল অবজেক্ট: আফ্রিকা: ডেলি: পরবর্তী থ্রেডে পরবর্তী রান লুপ চক্র চলাকালীন এবং একটি alচ্ছিক বিলম্ব সময়কালের পরে নির্দিষ্ট নির্বাচককে সম্পাদন করে Because কারণ এটি পরবর্তী রান লুপ চক্রটি নির্বাচক সঞ্চালনের জন্য অপেক্ষা করে, এই পদ্ধতিগুলি থেকে একটি স্বয়ংক্রিয় মিনি বিলম্ব সরবরাহ করে বর্তমানে সম্পাদনকারী কোড। একাধিক কাতারে নির্বাচিতরা ক্রমানুসারে একের পর এক সঞ্চালিত হয় ""


1
আপনার উত্তর সত্যই ভুল। আপনি যে ডকুমেন্টেশনটি উদ্ধৃত করেছেন performSelector:withObject:afterDelay:সেগুলি সম্পর্কে , তবে প্রশ্ন এবং আপনার স্নিপেট ব্যবহার করছে performSelector:, যা সম্পূর্ণ ভিন্ন পদ্ধতি। এর জন্য দস্তাবেজগুলি থেকে: < performSelector:aSelector
quotote

3
স্পষ্টতার জন্য জোশকে ধন্যবাদ জানাই। আপনি সঠিক; আমি ভেবেছিলাম performSelector/performSelector:withObject/performSelector:withObject:afterDelayসকলেই একই আচরণ করে যা ভুল ছিল।
এভিআই
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.