Ich bin gerade auf Blöcke gestoßen und ich denke, sie sind genau das, wonach ich suche, abgesehen von einer Sache: Ist es möglich, eine Methode [self methodName] aus einem Block heraus aufzurufen?
Das versuche ich zu tun:
-(void)someFunction{
Fader* fader = [[Fader alloc]init];
void (^tempFunction)(void) = ^ {
[self changeWindow:game];
//changeWindow function is located in superclass
};
[fader setFunction:tempFunction];
}
Ich habe seit ein paar Tagen gesucht und kann keine Beweise dafür finden, dass dies möglich ist.
Ist das überhaupt möglich oder versuche ich, Blöcke für etwas zu verwenden, für das sie nicht bestimmt sind?
Der Grund, warum ich Blöcke verwende, ist, dass ich eine Fader-Klasse erstellt habe und einen Block speichern möchte, damit er ausgeführt wird, wenn er ausgeblendet ist.
Vielen Dank
EDIT: Okay, ich habe den Vorschlag hinzugefügt, aber ich erhalte immer noch einen EXC_BAD_ACCESS-Fehler ...
-(void)someFunction{
Fader* fader = [[Fader alloc]init];
__block MyScreen* me = self;
void (^tempFunction)(void) = ^ {
[me changeWindow:game];
//changeWindow function is located in superclass
};
[fader setFunction:tempFunction];
[fader release];
}
Vielleicht darf ich dem Fader nicht die Funktion geben ...?
Antworten:
Ja, das kannst du machen.
Beachten Sie jedoch, dass der Block beibehalten wird
self
. Wenn Sie diesen Block in einem Ivar speichern, können Sie leicht einen Aufbewahrungszyklus erstellen, was bedeutet, dass keiner von beiden jemals freigegeben wird.Um dies zu umgehen, können Sie Folgendes tun:
- (void) someMethodWithAParameter:(id)aParameter { __block MySelfType *blocksafeSelf = self; void (^tempFunction)(void) = ^ { [blocksafeSelf changeWindow:game]; }; [self doSomethingWithBlock:tempFunction]; }
Das
__block
Schlüsselwort bedeutet (unter anderem), dass das referenzierte Objekt nicht beibehalten wird.quelle
function
Eigenschaft Ihres Schaltflächenobjekts einecopy
Eigenschaft und keineretain
Eigenschaft ist.self
, ein baumelnder Zeiger zu werden und eine RTE zu verursachen, wenn der Block aufgerufen wird, nachdem d aufgerufenself
wurdedealloc
. Vor ARC konnten Sie die MAZeroingWeakRef-Bibliothek von Mike Ash verwenden, um einen sicheren Verweis aufself
den Block zu erstellen . Nach ARC können Sie unter iOS 5.0 und höher das zusätzliche Schlüsselwort verwenden__weak
, um Ihre Referenz auf sich selbst zu einer schwachen Nullreferenz zu machen.self.someProperty = ...
ist das Gleiche wie[self setSomeProperty:...]
. Sie erfassen immer nochself
im Block, haben also immer noch einen starken Referenzzyklus.Die akzeptierte Antwort ist veraltet . Die Verwendung
__block
in diesem Fall kann zu Fehlern führen!Um dieses Problem zu vermeiden, empfiehlt es sich, einen schwachen Verweis
self
wie folgt zu erfassen :- (void)configureBlock { XYZBlockKeeper * __weak weakSelf = self; self.block = ^{ [weakSelf doSomething]; // capture the weak reference // to avoid the reference cycle } }
Weitere Informationen finden Sie in der Apple-Dokumentation - Vermeiden Sie starke Referenzzyklen bei der Selbstaufnahme .
quelle
__block
gibt dir Zugriff innerhalb des Blocks, macht ihn aber nicht schwach.__block CURRENTViewController *blocksafeSelf = self; [homeHelper setRestAsCheckIn:strRestId :^(NSObject *temp) { [blocksafeSelf YOURMETHOD:params]; }];
quelle
Ja, warum nicht. Wenn
tempFunction
es sich um eine Instanzmethode handelt, können Sie dies tun. Die aufgerufene Methode sollte zugänglich sein, ist die einzige Einschränkung.quelle
tempFunction
ist keine Instanzmethode - es ist ein Block.tempFunction
sich in einer Instanzmethode befinden ..."Betrachten Sie dies (was ich für die beste Vorgehensweise halte)
@implementaion ViewController - (void) viewDidLoad { __weak typeof(self) wself = self; [xxx doSomethingUsingBlock: ^{ __strong typeof(wself) self = wself; [self anotherMessage]; }]; } @end
Darüber hinaus können Sie Wrapper-Makros definieren.
#define MakeWeakSelf __weak typeof(self) wself = self #define MakeStrongSelf __strong typeof(wself) self = wself
quelle
Ich frage mich, ob Sie [Fader setFunction: tempFunction]; dann ist synchron oder asynchron. Blöcke werden in MRR auf stack.so verschoben. Wenn Sie sie nicht beibehalten, wird sie abgesprungen.
-(void)someFunction{ Fader* fader = [[Fader alloc]init]; void (^tempFunction)(void) = ^ { [self changeWindow:game]; //changeWindow function is located in superclass }; [fader setFunction:tempFunction]; //if the tempFunction execute there will be right. }//there the tempFunction pop off //....some thing go on //execute the tempFunction will go wrong.
quelle