আইওএস - একাধিক যুক্তি এবং ডেলিটারির সাথে একটি সঞ্চালক নির্বাচনকারী কীভাবে প্রয়োগ করবেন?


90

আমি আইওএস নবাগত। আমার নিম্নরূপে একটি নির্বাচক পদ্ধতি রয়েছে -

- (void) fooFirstInput:(NSString*) first secondInput:(NSString*) second
{

}

আমি এরকম কিছু বাস্তবায়নের চেষ্টা করছি -

[self performSelector:@selector(fooFirstInput:secondInput:) withObject:@"first" withObject:@"second" afterDelay:15.0];

তবে এটি আমাকে ত্রুটি দেয় -

Instance method -performSelector:withObject:withObject:afterDelay: not found

আমি কী মিস করছি সে সম্পর্কে কোনও ধারণা?

উত্তর:


143

ব্যক্তিগতভাবে, আমি মনে করি যে আপনার প্রয়োজনগুলির আরও ঘনিষ্ঠ সমাধান হ'ল এনএসআইভোকেশন ব্যবহার।

নীচের মতো কিছু কাজ করবে:

ইনডেক্সপথ এবং ডেটাসোর্স একই পদ্ধতিতে সংজ্ঞায়িত দুটি উদাহরণ ভেরিয়েবল।

SEL aSelector = NSSelectorFromString(@"dropDownSelectedRow:withDataSource:");

if([dropDownDelegate respondsToSelector:aSelector]) {
    NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[dropDownDelegate methodSignatureForSelector:aSelector]];
    [inv setSelector:aSelector];
    [inv setTarget:dropDownDelegate];

    [inv setArgument:&(indexPath) atIndex:2]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
    [inv setArgument:&(dataSource) atIndex:3]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation

    [inv invoke];
}

4
রাজি। এটি সঠিক উত্তর হওয়া উচিত। খুব সহায়ক সমাধান। বিশেষত আমার ক্ষেত্রে যেখানে একাধিক যুক্তিযুক্ত পদ্ধতিটির স্বাক্ষরটি পরিবর্তনের অনুমতি নেই।
অভিজিৎমিশ্রা

এটি দুর্দান্ত সমাধান হিসাবে দেখায়। এই কৌশলটির সাহায্যে পদ্ধতিটি থেকে কোনও রিটার্ন মান পাওয়ার কোনও উপায় আছে কি?
ডেভিড পেটিগ্রু

15
আপনি এই কৌশলটি দিয়ে কীভাবে বিলম্ব নির্দিষ্ট করবেন?
মৃত্যু_উ

4
@ দেথ_উ, এর পরিবর্তে invoke, কল করুন: [inv performSelector:@selector(invoke) withObject:nil afterDelay:1]; আমাকে অবশ্যই সম্মত করতে হবে এটি একটি দুর্দান্ত সমাধান। সবাইকে কোডিং শুভ!
ম্যাক্সিম চেত্রুসাকা

4
কথোপকথনের জন্য দেরীতে, তবে একটি প্রশ্ন আছে। ড্রপডাউনলেট কী?
মিনেস্ট্রোন-স্যুপ

97

কারণ [NSObject performSelector:withObject:withObject:afterDelay:]পদ্ধতি হিসাবে এমন কোনও জিনিস নেই ।

আপনি কিছু একক উদ্দেশ্য সি (যেমন একটি এনএসআরাই, একটি এনএসডি অভিধান, কিছু কাস্টম অবজেক্টিভ সি টাইপ) এর সাথে প্রেরণ করতে চান এমন ডেটা এনক্যাপুলেট করতে হবে এবং তারপরে এটি সেই [NSObject performSelector:withObject:afterDelay:]পদ্ধতিতে পাস করতে হবে যা সুপরিচিত এবং পছন্দসই।

উদাহরণ স্বরূপ:

NSArray * arrayOfThingsIWantToPassAlong = 
    [NSArray arrayWithObjects: @"first", @"second", nil];

[self performSelector:@selector(fooFirstInput:) 
           withObject:arrayOfThingsIWantToPassAlong  
           afterDelay:15.0];

আমি যদি পরে ডেলি পরম সরিয়ে ফেলি তবে আমি ত্রুটি পাই না। এর অর্থ কি ডিলেটার পরে একাধিক পরম ব্যবহার করার অনুমতি নেই?
সুচি

4
আপনি কোনও ত্রুটি পান না, তবে আমি বাজি ধরব যে রান সময় আপনি "নির্বাচককে পাওয়া যায় নি" ব্যতিক্রম পাবেন (এবং আপনি যে জিনিসটি সম্পাদন করার চেষ্টা করছেন সেটি কল হবে না) ... চেষ্টা করে দেখুন। :-)
মাইকেল ডাউটারম্যান

আমি কিভাবে এখানে বুল টাইপ পাস করব?
ভাইরাত

এটিকে একটি উদ্দেশ্য সি স্টাইলের বস্তু তৈরি করুন (যেমন " NSNumber * whatToDoNumber = [NSNumber numberWithBool: doThis];") এবং এটি একটি প্যারামিটার হিসাবে পাস করুন, @ ভিরাটা।
মাইকেল ডাউটারম্যান

4
এটি একটি আলাদা প্রশ্ন @ রাজ ... দয়া করে এটি আলাদাভাবে পোস্ট করুন।
মাইকেল ডাউটারম্যান

34

আপনি আপনার পরামিতিগুলিকে একটি বস্তুতে প্যাকেজ করতে পারেন এবং মাইকেল হিসাবে আপনার মূল পদ্ধতিটি কল করতে একটি সহায়ক পদ্ধতি ব্যবহার করতে পারেন এবং এখন অন্যরা পরামর্শ দিয়েছে।

আরেকটি বিকল্প হ'ল প্রেরণ_পরে, যা একটি নির্দিষ্ট সময় নেবে এবং এটিকে সজ্জিত করবে।

double delayInSeconds = 15.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);

dispatch_after(popTime, dispatch_get_main_queue(), ^(void){

    [self fooFirstInput:first secondInput:second];

});

বা, যেমন আপনি ইতিমধ্যে আবিষ্কার করেছেন, যদি আপনার কেবলমাত্র বিলম্বের প্রয়োজন হয় না তবে আপনি ব্যবহার করতে পারেন - performSelector:withObject:withObject:


এই পদ্ধতির সম্পর্কেও ভাল এটি হ'ল আপনি __weakনিজের ভান টাইমারকে কেবল একটি দুর্বল লিঙ্কটি নিজের কাছে ফিরিয়ে দিতে ব্যবহার করতে পারেন - যাতে আপনি কৃত্রিমভাবে আপনার অবজেক্টের জীবনকাল বর্ধন করেন না এবং উদাহরণস্বরূপ যদি আপনার সঞ্চালক নির্বাচক: আফ্রিকাডেলি: লেজের মতো কিছুটা প্রভাব ফেলে পুনরাবৃত্তি (যদিও পুনরাবৃত্তি ছাড়াই) তবে এটি ধরে রাখার চক্রটি সমাধান করে।
টমি

4
হ্যাঁ এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। এটি আরও উপযুক্ত এবং সরাসরি এগিয়ে।
রুহুল

7

সবচেয়ে সহজ বিকল্পটি হ'ল উভয় আর্গুমেন্ট যুক্ত একটি একক প্যারামিটার গ্রহণের জন্য আপনার পদ্ধতিটি পরিবর্তন করা, যেমন একটি NSArrayবা NSDictionary(অথবা দ্বিতীয় পদ্ধতিটি যা একটি প্যারামিটার নেয়, আনপ্যাক করে, এবং প্রথম পদ্ধতিটি কল করে, এবং তারপরে একটি দ্বিতীয় পদ্ধতিতে কল করে) বিলম্ব)।

উদাহরণস্বরূপ, আপনার মতো কিছু থাকতে পারে:

- (void) fooOneInput:(NSDictionary*) params {
    NSString* param1 = [params objectForKey:@"firstParam"];
    NSString* param2 = [params objectForKey:@"secondParam"];
    [self fooFirstInput:param1 secondInput:param2];
}

এবং তারপরে ফোন করতে, আপনি এটি করতে পারেন:

[self performSelector:@selector(fooOneInput:) 
      withObject:[NSDictionary dictionaryWithObjectsAndKeys: @"first", @"firstParam", @"second", @"secondParam", nil] 
      afterDelay:15.0];

যদি পদ্ধতিটি সংশোধন করা যায় না, তবে বলুন এটি ইউআইকিট বা অন্য কিছুতে বাস করে? শুধু তাই নয়, পদ্ধতি পরিবর্তন করে ব্যবহারের NSDictionaryধরণের সুরক্ষাও হারায়। আদর্শ নয়।
ফতুহোকু

@ ফাতুহোকু - এটি প্যারেন্টেটিকাল দ্বারা আচ্ছাদিত; "একটি দ্বিতীয় পদ্ধতি যুক্ত করুন যা একটি একক প্যারামিটার নেয়, আনপ্যাক করে এবং প্রথম পদ্ধতিটিকে কল করে"। এটি প্রথম পদ্ধতিটি যেখানে বাস করে তা নির্বিশেষে কাজ করে। ধরণের সুরক্ষার ক্ষেত্রে, সিদ্ধান্তটি performSelector:(বা NSInvocation) ব্যবহারের সিদ্ধান্ত নেওয়ার মুহুর্তে এটি হারিয়ে গেছে । যদি এটি উদ্বেগের বিষয় হয়ে থাকে তবে সম্ভবত সেরা বিকল্পটি হ'ল জিসিডি দিয়ে যাওয়া।
23oth50 এ আরথ

6
- (void) callFooWithArray: (NSArray *) inputArray
{
    [self fooFirstInput: [inputArray objectAtIndex:0] secondInput: [inputArray objectAtIndex:1]];
}


- (void) fooFirstInput:(NSString*) first secondInput:(NSString*) second
{

}

এবং এর সাথে কল করুন:

[self performSelector:@selector(callFooWithArray) withObject:[NSArray arrayWithObjects:@"first", @"second", nil] afterDelay:15.0];

5

আপনি প্রদত্ত সমস্ত প্রকারের সঞ্চালনকারী নির্বাচন করতে পারেন: পদ্ধতিগুলি এখানে:

http://developer.apple.com/library/mac/#docamentation/Cocoa/References/Foundation/Class/nsobject_Class/References/References.html

এখানে বিভিন্ন ধরণের বৈচিত্র রয়েছে তবে এমন কোনও সংস্করণ নেই যা একাধিক অবজেক্টের পাশাপাশি দেরি করে। পরিবর্তে আপনার নিজের যুক্তিগুলি এনএসএররে বা এনএসডি অভিধানে গুটিয়ে রাখতে হবে।

- performSelector:
- performSelector:withObject:
- performSelector:withObject:withObject:
– performSelector:withObject:afterDelay:
– performSelector:withObject:afterDelay:inModes:
– performSelectorOnMainThread:withObject:waitUntilDone:
– performSelectorOnMainThread:withObject:waitUntilDone:modes:
– performSelector:onThread:withObject:waitUntilDone:
– performSelector:onThread:withObject:waitUntilDone:modes:
– performSelectorInBackground:withObject: 

2

আমি এনএসআইএনওভোকেশন উপায়টি খুব পছন্দ করি না। আসুন এটি সহজ এবং পরিষ্কার রাখুন:

// Assume we have these variables
id target, SEL aSelector, id parameter1, id parameter2;

// Get the method IMP, method is a function pointer here.
id (*method)(id, SEL, id, id) = (void *)[target methodForSelector:aSelector];

// IMP is just a C function, so we can call it directly.
id returnValue = method(target, aSelector, parameter1, parameter2);

সুন্দর! 'লক্ষ্য' দিয়ে 'ভিসি' প্রতিস্থাপন করুন
আন্তন

1

আমি কেবল কিছু সুইজলিং করেছি এবং আসল পদ্ধতিটি কল করার দরকার ছিল। আমি যা করেছি তা হ'ল একটি প্রোটোকল তৈরি করছিল এবং আমার বিষয়টিকে এতে নিক্ষেপ করছিল। আরেকটি উপায় হ'ল পদ্ধতিটি কোনও বিভাগে সংজ্ঞায়িত করা, তবে একটি সতর্কতা দমন করতে হবে (# প্রগমা ক্ল্যাং ডায়াগোনস্টিক উপেক্ষা করা "-জিনমুক্ত-বাস্তবায়ন")।


0

একটি সহজ এবং পুনরায় ব্যবহারযোগ্য উপায় হ'ল প্রসারিত NSObjectএবং বাস্তবায়ন

- (void)performSelector:(SEL)aSelector withObjects:(NSArray *)arguments;

কিছুটা এইরকম:

- (void)performSelector:(SEL)aSelector withObjects:(NSArray *)arguments
{
    NSMethodSignature *signature = [self methodSignatureForSelector: aSelector];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature: signature];
    [invocation setSelector: aSelector];

    int index = 2; //0 and 1 reserved
    for (NSObject *argument in arguments) {
        [invocation setArgument: &argument atIndex: index];
        index ++;
    }
    [invocation invokeWithTarget: self];
}

0

আমি কেবল বৈশিষ্ট্য হিসাবে আমার সমস্ত পরামিতি ধারণ করে একটি কাস্টম অবজেক্ট তৈরি করব এবং তারপরে সেই একক বস্তুটিকে প্যারামিটার হিসাবে ব্যবহার করব

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.