PerformSelector süzgəcinə səbəb ola bilər, çünki seçici bilinmir.

ARC derleyicisindən aşağıdakı xəbərdarlıqları alıram:

 "performSelector may cause a leak because its selector is unknown". 

İşdə budur:

 [_controller performSelector:NSSelectorFromString(@"someMethod")]; 

Niyə bu xəbərdarlıq ala bilərəm? Derleyici bir seçicinin var olub olmadığını yoxlaya bilməyəcəyini anlayıram, amma bu neden bir sızıntıya neden ola bilər? Və bu xəbərdarlığı artıq qəbul etməmək üçün kodumu necə dəyişə bilərəm?

1146
10 авг. Eduardo Scoz tərəfindən təyin olunan 10 av . 2011-08-10 23:23 '11 at 11:23 PM 2011-08-10 23:23
@ 20 cavab

Həll

Derleyici bu barədə hər hansı bir səbəbdən xəbərdarlıq edir. Çox nadir hallarda, bu xəbərdarlıq sadəcə nəzərə alınmır və asanlıqla əvəz edilməlidir. İşdə necə:

 if (!_controller) { return; } SEL selector = NSSelectorFromString(@"someMethod"); IMP imp = [_controller methodForSelector:selector]; void (*func)(id, SEL) = (void *)imp; func(_controller, selector); 

Və ya daha çətin (qorunmadan oxumaq çətin olsa da):

 SEL selector = NSSelectorFromString(@"someMethod"); ((void (*)(id, SEL))[_controller methodForSelector:selector])(_controller, selector); 

Təsvir

Burada nə olur, nəzarətçiyə müvafiq olan üsul üçün C funksiyası göstəricisi üçün nəzarətçidən soruşursunuz. Bütün NSObject methodForSelector: cavab verir, lakin siz də Objective-C iş vaxtında class_getMethodImplementation istifadə edə bilərsiniz (yalnız bir protokol varsa, məsələn, id<SomeProto> ). Bu funksiya göstəriciləri IMP s adlanır və typedef ed ( id (*IMP)(id, SEL, ...) ) 1 funksiyasındakı sadə göstəricilərdir. Bu, faktiki metod imzasına yaxın ola bilər, lakin həmişə tam olaraq eşleşmeyebilir.

IMP _cmd olduğunuzda, ARC-ə lazım olan bütün detalları (Objective-C metoduna hər bir çağırışdan ibarət olan iki gizli arqument, self_cmd də daxil olmaqla) daxil edən funksiya göstəricisinə qeyd etmək lazımdır. Bu, sağ tərəfdə üçüncü xəttdə ( (void *) işlənir, sadəcə nə etdiyinizi bilən kompilyatoru xəbərdar edir və göstərici növləri uyğun deyil, çünki xəbərdarlıq yarada bilməz).

Nəhayət, bir funksiya göstərici 2 çağırırsınız.

Hərtərəfli nümunə

Seçici arqumentlər götürdüyü və ya bir dəyər qaytardıqda vəziyyəti bir az dəyişməlisiniz:

 SEL selector = NSSelectorFromString(@"processRegion:ofView:"); IMP imp = [_controller methodForSelector:selector]; CGRect (*func)(id, SEL, CGRect, UIView *) = (void *)imp; CGRect result = _controller ? func(_controller, selector, someRect, someView) : CGRectZero; 

Xəbərdarlıq etmək fikrindədir

Bu xəbərdarlığın səbəbi ARC ilə iş vaxtının çağırdığınız üsulun nəticəsi ilə əlaqədardır. Nəticə ola bilər: void , int , char , NSString * , id və s. ARC, bu məlumatları, işlədiyiniz obyektin tip başlığından əldə edir. 3

ARC-nin geri qaytarma dəyərini nəzərə alacağı yalnız 4 şey vardır: 4

  • Qeyri-obyektlərin olmaması ( void , int , və s.)
  • Niyyətin dəyərini saxlaya, sonra artıq istifadə edildikdə buraxın (standart ehtimal)
  • Yeni obyekt dəyərləri artıq istifadə edilmədikdə buraxın ( init / copy ailəsində və ya ns_returns_retained ilə ns_returns_retained )
  • Heç bir şey etməyin və geri qaytarılan obyektin dəyərinin yerli sahədə etibarlı olacağını fərz et (daxili azad hovuzunun tükənməsinə qədər, ns_returns_autoreleased təyin ns_returns_autoreleased )

Calling methodForSelector: metodun qaytarılması dəyəri bir obyektdir, lakin saxlamır / azad edir. Beləliklə, obyektinizin sərbəst buraxılmasını gözlədiyiniz halda, sızıntı yarada bilərsiniz (məsələn, çağırdığınız üsul yeni bir obyekt qaytarır).

Geri çağırmağa çalışdığınız seçicilər üçün void və ya digər qeyri-obyektlər, bu xəbərdarlığı gözardı etmək üçün kompilyator funksiyalarını daxil edə bilərsiniz, lakin bu təhlükə ola bilər. C>methodForSelector: dən qaytarılan obyektin dəyərini saxlaya və azad edə bilməyəcəyinə inanmaq üçün bir səbəb yoxdur methodForSelector: istifadə etmək istəmirsinizsə belə. Derivə baxımından bu, bir şeydir. Bu demektir ki, əgər çağırdığınız metod, bir someMethod , bir obyekti ( void daxil) geri someMethod , saxlanılacaq / azad ediləcək və işləyəcək zibil göstəricisinin dəyərini əldə edə bilərsiniz.

Əlavə arqumentlər

Biri hesab edir ki, bu, yerinə yetirilməkləSelektor ilə eyni xəbərdarlıq olacaq performSelector:withObject: və bu metodun parametrləri necə istifadə etdiyini bəyan etmədən eyni problemlərlə qarşılaşa bilərsiniz. ARC siz istehlak parametrlərini bəyan etməyə imkan verir və metod bu parametrdən istifadə edirsə, ehtimal ki, bir zombi mesajı və qəza göndərməyinizə son qoyacaqsınız. Körpü döküm ilə bunu etmə yolları var, amma həqiqətən yuxarıda IMP metodologiyası və funksiyası göstərici funksiyalarını istifadə etmək daha yaxşı olardı. İstehlak edilən parametrlər nadir hallarda problem olduğundan bu mümkün deyil.

Statik selektor

Maraqlıdır ki, derleyici statik olaraq elan edilmiş statik bəyannamələrdən şikayət etməyəcəkdir:

 [_controller performSelector:@selector(someMethod)]; 

Bunun səbəbi kompilyatorun seçici və obyektin kompilyasiya vaxtı barədə həqiqətən bütün məlumatları yaza bilməsi. Heç bir şey haqqında heç bir fərziyyəyə ehtiyac yoxdur. (Mən bir il əvvəl mənə baxdıq, mənbəyə baxdıq, amma indi heç bir əlaqəm yoxdur).

Boğulma

Bu xəbərdarlığın basdırılması zəruri və kodun yaxşı bir şəkildə dizayn ediləcəyi bir vəziyyət barədə düşünmək cəhdi ilə gəlirəm. Biri, bu xəbərdarlıqları susdurmaq lazım olduqda (və yuxarıdan düzgün işləmir) təcrübəsi olduqda bölüşün.

Daha ətraflı oxuyun

Bunu da idarə etmək üçün NSMethodInvocation yarada bilərsiniz, ancaq bunun üçün daha çox mətn girişi və daha yavaş tələb olunur, bunun üçün heç bir səbəb yoxdur.

Tarixi

performSelector: üsullar ailəsi ilk dəfə Objective-C-də əlavə performSelector: , ARC mövcud olmadı. ARC yaratdıqda, Apple, bu metodlar üçün bir xəbərdarlıq yaratmaq qərarına gəldi ki, geliştiricileri seçilmiş bir selektordan istifadə edərək özbaşına mesajlar göndərərkən necə yaddaşın necə istifadə ediləcəyini dəqiq şəkildə müəyyənləşdirmək üçün digər vasitələrdən istifadə etməyə yönəldilməlidir. Objective-C-də, developers bunu C-tərzi tökmə istifadə edərək göstəricilərə xam göstəricilərə edə bilər.

Swift-in tətbiqi ilə, Apple üsulları performSelector: ailəsini sənədləşdirdi performSelector: "həqiqətən təhlükəli" və onlar Swift üçün mövcud deyildir.

Vaxt keçdikcə bu inkişafı gördük:

  • Objective- performSelector: erkən versiyaları performSelector: (manual yaddaş idarə edilməsi)
  • performSelector: -C performSelector: üçün ARC xəbərdarlıqları ilə performSelector:
  • performSelector: çıxış imkanı yoxdur və bu üsulları "təbii performSelector: " kimi sənədləşdirir.

Adlandırılmış selektorlara əsaslanan mesajların göndərilməsi fikri, lakin "təhlükəli olmayan" funksiyadır. Bu ideya Objective-C-də, eləcə də bir çox digər proqramlaşdırma dillərində uğurla istifadə edilmişdir.


1 Bütün Objective-C metodları metodu çağırıldıqda örtük şəkildə əlavə olunan iki gizli argümanı, self_cmd .

2 NULL funksiyasına çağırış C-də təhlükəsiz deyil. Bir nəzarətçinin varlığını yoxlamaq üçün istifadə olunan qorunma bir obyektin olduğunu təmin edir. Buna görə, biz methodForSelector: IMP əldə methodForSelector: (baxmayaraq ki, _objc_msgForward ola bilər, mesaj ötürmə sisteminə yaza bilərsiniz). Prinsipcə, qoruma ilə biz zəng etmək üçün bir funksiyanı olduğumuzu bilirik.

3 Əslində, obyektləri id olaraq elan id , səhv məlumat ala bilər və bütün başlıqları idxal etmirsiniz. Derleyicinin düşündüyü kodda bir qəza ola bilərsiniz. Bu çox nadir, ancaq ola bilər. Adətən, yalnız iki metoddan hansı imza seçmək üçün bilmədiyi bir xəbərdarlıq alırsınız.

4 Daha ətraflı məlumat üçün saxlanılan qaytarma dəyərlərietibarsız qaytarma dəyərləri üçün ARC istinadına baxın.

1107
19 нояб. Cavab 19 noyabrda verildi 2013-11-19 00:44 '13 at 0:44 2013-11-19 00:44

Xcode 4.2-də LLVM 3.0 kompilyatorunda aşağıdakı xəbərdarlıqları bastırabilirsiniz:

 #pragma c> 

Bir neçə yerdəki bir səhv varsa və Pragmas'ı gizlətmək üçün C makrosetini istifadə etmək istəyirsinizsə, xəbərdarlığı bastırmanı asanlaşdırmaq üçün bir makroyu təyin edə bilərsiniz:

 #define SuppressPerformSelectorLeakWarning(Stuff) \ do { \ _Pragma("c> 
border=0

Bu kimi bir makro istifadə edə bilərsiniz:

 SuppressPerformSelectorLeakWarning( [_target performSelector:_action withObject:self] ); 

Tamamlanmış bir mesajın nəticəsinə ehtiyacınız varsa, bunu edə bilərsiniz:

 id result; SuppressPerformSelectorLeakWarning( result = [_target performSelector:_action withObject:self] ); 
1160
28 окт. Scott Thompson tərəfindən verilmiş cavabı Oct 28 2011-10-28 22:30 '11 'də 22:30' da 2011-10-28 22:30 'da

Bu barədə fərziyyəm budur: seçici kompilyatora məlum deyil, ARC düzgün yaddaş idarə edilməsini təmin edə bilməz.

Əslində, yaddaş idarəçiliyi xüsusi bir konvensiya ilə bir metod adı ilə əlaqəli olan zamanlar var. Xüsusilə, rahatlıq qurucularını üsullar yaratmaqla müqayisədə düşünürəm; müqavilə ilə ilk reallaşdırma avtomatik həyata obyekt; son saxlanılan bir obyektdir. Konvensiya selektor adlarına əsaslanır, belə ki, əgər kompilyator seçicini bilmirsə, o zaman düzgün yaddaş idarəetməsini təmin edə bilməz.

Bu doğruysa, hər şeyi yaddaş idarəçiliyində olduğuna əmin olsanız (məsələn, üsullarınızın təyin etdikləri obyektləri qaytarmırsınız) əmin olduğunuz halda kodu təhlükəsiz istifadə edə bilərsiniz.

205
10 авг. cavab verildi sergio 10 aug. 2011-08-10 23:43 '11 at 11:43 pm 2011-08-10 23:43

WARNING_CFLAGS Ayarları layihənizdə, Digər Diqqətləndirici Bayraqlar bölməsində ( WARNING_CFLAGS ) əlavə edin - -Wno-arc-performSelector-leaks

Artıq seçdiyiniz seçicinin obyektinizin saxlanmasına və ya kopyalanmasına səbəb olmur.

119
31 окт. Cavab 0xced 31 oct verilir . 2011-10-31 16:57 '11 'da 16:57' da 2011-10-31 16:57

Derivat xəbərdarlığı ləğv edə bilənə qədər bir həll prosesi olaraq, iş vaxtından istifadə edə bilərsiniz

 objc_msgSend(_controller, NSSelectorFromString(@"someMethod")); 

əvəzinə

 [_controller performSelector:NSSelectorFromString(@"someMethod")]; 

Lazımdır

 #import <objc/message.h> 
109
16 авг. Cavab verildi jluckyiv 16 aug. 2011-08-16 07:56 '11 'də saat 07:56' da 2011-08-16 07:56

Parametr seçicisini istifadə edərək yalnız fayl xətasını yox saymaq üçün aşağıdakı kimi #pragma əlavə edin:

 #pragma c> 

Bu, bu xətt üzrə xəbərdarlıqları görməyəcək, amma hələ də bütün layihələrinizə imkan verir.

87
19 янв. Cavab Barlow Tucker Jan 19 tərəfindən verilir 2012-01-19 00:31 '12 at 0:31 2012-01-19 00:31

Qəribə, amma doğrudur: əgər bu məqbul olsa (yəni, nəticə etibarsızdır və bir dəfə runloop dövrünü işlədirsinizsə), sıfır olsa belə gecikdirin:

 [_controller performSelector:NSSelectorFromString(@"someMethod") withObject:nil afterDelay:0]; 

Bu, ehtimal ki, kompilyatoru heç bir obyektin geri qaytarılmadığını və hər hansı bir şəkildə dolaşdığına əmin olduğunu ehtimal edir.

66
11 нояб. cavab mat 11 noyabr verilir . 2012-11-11 22:19 '12 at 10:19 PM 2012-11-11 22:19

Yuxarıda verilən cavabı əsas götürərək yenilənmiş makro. Bu, bir qaytarma bəyanatı ilə hətta kodunuzu saxlamağa imkan verməlidir.

 #define SUPPRESS_PERFORM_SELECTOR_LEAK_WARNING(code) \ _Pragma("c> 
34
07 мая '13 в 17:58 2013-05-07 17:58 Cavab verilir syvex 07 May '13 at 17:58 2013-05-07 17:58

Bu kodda derleyici bayraqları və ya birbaşa işləmə zəngləri yoxdur:

 SEL selector = @selector(zeroArgumentMethod); NSMethodSignature *methodSig = [[self class] instanceMethodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; [invocation setSelector:selector]; [invocation setTarget:self]; [invocation invoke]; 

NSInvocation , performSelector dan fərqli olaraq performSelector bu, hər hansı bir üsulla işləyəcək bir sıra arqumentlər təyin etməyə imkan verir.

30
01 февр. Benedict Cohen tərəfindən verilmiş cavab 01 fevral. 2012-02-01 18:46 '12 saat 06:46 'da 2012-02-01 18:46

Budur, burada bir çox cavab var, amma bu bir az fərqli olduğundan, bir neçə cavabı birləşdirərək, mən onları qoyacağımı düşündüm. Seçicinin bir boşluq qaytardığını yoxlayır və kompilyator xəbərdarlığını basdıran NSObject kateqoriya istifadə edirəm.

 #import <Foundation/Foundation.h> #import <objc/runtime.h> #import "Debug.h" // not given; just an assert @interface NSObject (Extras) // Enforce the rule that the selector used must return void. - (void) performVoidReturnSelector:(SEL)aSelector withObject:(id)object; - (void) performVoidReturnSelector:(SEL)aSelector; @end @implementation NSObject (Extras) // Apparently the reason the regular performSelect gives a compile time warning is that the system doesn't know the return type. I'm going to (a) make sure that the return type is void, and (b) disable this warning // See http://stackoverflow.com/questions/7017281/performselector-may-cause-a-leak-because-its-selector-is-unknown - (void) checkSelector:(SEL)aSelector { // See http://stackoverflow.com/questions/14602854/objective-c-is-there-a-way-to-check-a-selector-return-value Method m = class_getInstanceMethod([self class], aSelector); char type[128]; method_getReturnType(m, type, sizeof(type)); NSString *message = [[NSString alloc] initWithFormat:@"NSObject+Extras.performVoidReturnSelector: %@.%@ selector (type: %s)", [self class], NSStringFromSelector(aSelector), type]; NSLog(@"%@", message); if (type[0] != 'v') { message = [[NSString alloc] initWithFormat:@"%@ was not void", message]; [Debug assertTrue:FALSE withMessage:message]; } } - (void) performVoidReturnSelector:(SEL)aSelector withObject:(id)object { [self checkSelector:aSelector]; #pragma c> 
20
21 февр. Cavab 21 fevralda Chris Prince tərəfindən verilir . 2014-02-21 07:32 '14 da 7:32 2014-02-21 07:32

Nəsil üçün, şapkamı ringə atmağa qərar verdim :)

Son zamanlarda target / selector paradiqmindən protokol, blok, və s. Ancaq bir neçə dəfə istifadə etdiyim performSelector üçün bir əvəz var:

 [NSApp sendAction: NSSelectorFromString(@"someMethod") to: _controller from: nil]; 

objc_msgSend() ilə çox qiymətə malik olmayan, performSelector yerinə performSelector üçün təmiz, ARC-təhlükəsiz və demək olar ki, eyni əvəz kimi görünür.

Baxmayaraq ki, iOS-da bir ekvivalent varmı?

16
26 февр. Cavab 26 fevralda Patrik Perini tərəfindən verilir . 2012-02-26 07:17 '12 at 7:17 2012-02-26 07:17

Matt Gallowayın bu axındakı cavabını niyə izah edir?

Aşağıdakıları nəzərdən keçirin:

 id anotherObject1 = [someObject performSelector:@selector(copy)]; id anotherObject2 = [someObject performSelector:@selector(giveMeAnotherNonRetainedObject)]; 

İndi ARC 1 sayını qoruyarkən ilk obyektin bir obyektə döndüyünü bilir və ikincisi avtomatik tətbiq olunan bir obyekti qaytarır?

Qaytarma dəyərini görməmisinizsə, xəbərdarlıqları bastırmaq təhlükəsiz görünür. Performansı seçəndən xilas bir obyekt almaq lazımdırsa, ən yaxşı nə əmin deyiləm - "bunu etməyin" istisna olmaqla.

15
15 мая '12 в 23:17 2012-05-15 23:17 cavab c roald 15 may '12 saat 23:17 'də verilir 2012-05-15 23:17

@ c-yol problemi təsvir edən düzgün link təmin edir. Aşağıda mənim nümunəniSelektor bir yaddaş sızıntısına səbəb olduqda görə bilərsiniz.

 @interface Dummy : NSObject <NSCopying> @end @implementation Dummy - (id)copyWithZone:(NSZone *)zone { return [[Dummy alloc] init]; } - (id)clone { return [[Dummy alloc] init]; } @end void CopyDummy(Dummy *dummy) { __unused Dummy *dummyClone = [dummy copy]; } void CloneDummy(Dummy *dummy) { __unused Dummy *dummyClone = [dummy clone]; } void CopyDummyWithLeak(Dummy *dummy, SEL copySelector) { __unused Dummy *dummyClone = [dummy performSelector:copySelector]; } void CloneDummyWithoutLeak(Dummy *dummy, SEL cloneSelector) { __unused Dummy *dummyClone = [dummy performSelector:cloneSelector]; } int main(int argc, const char * argv[]) { @autoreleasepool { Dummy *dummy = [[Dummy alloc] init]; for (;;) { @autoreleasepool { //CopyDummy(dummy); //CloneDummy(dummy); //CloneDummyWithoutLeak(dummy, @selector(clone)); CopyDummyWithLeak(dummy, @selector(copy)); [NSThread sleepForTimeInterval:1]; }} } return 0; } 

Mənim nümunəmdə yaddaş sızıntısına səbəb olan yeganə üsul CopyDummyWithLeak edir. Bunun səbəbi ARC'nin copySelector'in saxlanan bir obyekti qaytardığını bilmir.

Yaddaş Sızdırma Toolunu çalıştırdıysanız aşağıdakı görüntüyü görürsünüz: 2019

14
25 дек. Cavab Pavel Osipov tərəfindən dekabrın 25-də verilir. 2012-12-25 13:23 '12 at 13:23 PM 2012-12-25 13:23

Scott Thomson makrosunu daha çox yönəldin:

 // String expander #define MY_STRX(X) #X #define MY_STR(X) MY_STRX(X) #define MYSilenceWarning(FLAG, MACRO) \ _Pragma("c> 

Sonra aşağıdakı kimi istifadə edin:

 MYSilenceWarning(-Warc-performSelector-leaks, [_target performSelector:_action withObject:self]; ) 
5
04 авг. Cavab Ben Flynn 04 aug tərəfindən verilir . 2015-08-04 00:46 '15 at 0:46 2015-08-04 00:46

ARC istifadə etdiyiniz üçün iOS 4.0 və ya daha sonra istifadə etməlisiniz. Bu, blokları istifadə edə bilərsiniz. Əgər seçicinin sizi məhv etdiyini xatırlayırsınızsa, bir blok götürmək əvəzinə ARC əslində baş verənləri daha yaxşı izləyə və yaddaşda sızan bir şəkildə təsadüfən daxil olma riskinə ehtiyacınız olmayacaq.

4
23 нояб. Cavab 23 noyabrda Honusa tərəfindən verilir. 2011-11-23 05:33 '11 at 5:33 2011-11-23 05:33

Uyarıları bastırmayın!

Derleyici ilə messing üçün ən azı 12 alternativ həlli var.
İlk tətbiq edərkən ağıllı olmağınızla yanaşı, yer üzündə bir neçə mühəndis sizin addımlarınızı izləyə və bu kod nəhayət pozulacaq.

Təhlükəsiz marşrutlar:

Bütün bu həllər, orijinal niyyətinizdən bir dərəcə dəyişikliklə işləyəcək. İstəsəniz param nil ola bilər:

Təhlükəsiz marşrut, eyni konseptual davranış:

 // GREAT [_controller performSelectorOnMainThread:selector withObject:anArgument waitUntilDone:YES]; [_controller performSelectorOnMainThread:selector withObject:anArgument waitUntilDone:YES modes:@[(__bridge NSString *)kCFRunLoopDefaultMode]]; [_controller performSelector:selector onThread:[NSThread mainThread] withObject:anArgument waitUntilDone:YES]; [_controller performSelector:selector onThread:[NSThread mainThread] withObject:anArgument waitUntilDone:YES modes:@[(__bridge NSString *)kCFRunLoopDefaultMode]]; 

Təhlükəsiz marşrut, bir az fərqli davranış:

( bu cavabı görə bilərsiniz)
Əvəzinə [NSThread mainThread] hər hansı bir mövzu istifadə edin.

 // GOOD [_controller performSelector:selector withObject:anArgument afterDelay:0]; [_controller performSelector:selector withObject:anArgument afterDelay:0 inModes:@[(__bridge NSString *)kCFRunLoopDefaultMode]]; [_controller performSelectorOnMainThread:selector withObject:anArgument waitUntilDone:NO]; [_controller performSelectorOnMainThread:selector withObject:anArgument waitUntilDone:NO]; [_controller performSelectorOnMainThread:selector withObject:anArgument waitUntilDone:NO modes:@[(__bridge NSString *)kCFRunLoopDefaultMode]]; [_controller performSelectorInBackground:selector withObject:anArgument]; [_controller performSelector:selector onThread:[NSThread mainThread] withObject:anArgument waitUntilDone:NO]; [_controller performSelector:selector onThread:[NSThread mainThread] withObject:anArgument waitUntilDone:NO modes:@[(__bridge NSString *)kCFRunLoopDefaultMode]]; 

Təhlükəli marşrutlar

Bəzi cür kompilyator siqnalı tələb olunur, bu da qırılacaq. Xatırladaq ki, hal-hazırda boşluqlar sürətlənib .

 // AT YOUR OWN RISK [_controller performSelector:selector]; [_controller performSelector:selector withObject:anArgument]; [_controller performSelector:selector withObject:anArgument withObject:nil]; 
3
31 дек. Cavab 31 dekabrda SwiftArchitect tərəfindən verilir . 2015-12-31 06:58 '16 'da 6:58' da, 2015-12-31 06:58

Mənə bir sıra problemləri olan blok yanaşmasını istifadə etmək əvəzinə:

  IMP imp = [_controller methodForSelector:selector]; void (*func)(id, SEL) = (void *)imp; 

NSInvocation istifadə edəcəyəm, məsələn:

  -(void) sendSelectorToDelegate:(SEL) selector withSender:(UIButton *)button if ([delegate respondsToSelector:selector]) { NSMethodSignature * methodSignature = [[delegate class] instanceMethodSignatureForSelector:selector]; NSInvocation * delegateInvocation = [NSInvocation invocationWithMethodSignature:methodSignature]; [delegateInvocation setSelector:selector]; [delegateInvocation setTarget:delegate]; // remember the first two parameter are cmd and self [delegateInvocation setArgument: atIndex:2]; [delegateInvocation invoke]; } 
2
21 мая '15 в 11:52 2015-05-21 11:52 cavab 21 may, 21 may saat 11: 52-da verilir

Hər hansı bir arqument qəbul etməyiniz valueForKeyPath istifadə etmək valueForKeyPath . Bu, hətta bir Class obyekti üçün də mümkündür.

 NSString *colorName = @"brightPinkColor"; id uicolor = [UIColor class]; if ([uicolor respondsToSelector:NSSelectorFromString(colorName)]){ UIColor *brightPink = [uicolor valueForKeyPath:colorName]; ... } 
1
15 февр. Cavab 15 fevralda arsenius tərəfindən verilir . 2017-02-15 07:08 '17 də 7:08 2017-02-15 07:08

Burada protokolu da istifadə edə bilərsiniz. Belə bir protokol yaradın:

 @protocol MyProtocol -(void)doSomethingWithObject:(id)object; @end 

Sektorunuzun zəng etməsi lazım olduğu üçün sinifdə @property olmalıdır.

 @interface MyObject @property (strong) id<MyProtocol> source; @end 

@selector(doSomethingWithObject:) çağırmanız lazımdır, aşağıdakıları edin:

 [self.source doSomethingWithObject:object]; 
-2
ответ дан Damon 03 авг. '13 в 14:34 2013-08-03 14:34

Есть еще один способ обойти это предупреждение.

 <del>[instanceSelector performSelector:stopSelector];</del> 

Использовать метод overDelay overloaded

 [instanceSelector performSelector:stopSelector withObject:self afterDelay:0.0]; 
-2
ответ дан antonio 03 дек. '17 в 5:07 2017-12-03 05:07

Другие вопросы по меткам или Задайте вопрос