2016-05-23 15 views
0

Mit einem NSNotificationCenter Block, ich habe [unowned Selbst] zu verwenden, um einen starken Referenzzyklus zu vermeiden: müssenWarum ist ein starker Referenzzyklus mit NSNotificationCenter möglich, aber nicht mit UIView.animateWithDuration?

NSNotificationCenter.defaultCenter() 
    .addObserverForName(UIApplicationWillEnterForegroundNotification, 
     object: nil, 
     queue: nil, 
     usingBlock: { [unowned self] (notification : NSNotification!) -> Void in 
      self.add(123) 
     }) 

jedoch in UIView.animateWithDuration, ich weiß nicht [unowned Selbst] verwenden:

UIView.animateWithDuration(0.5, animations: {() -> Void in 
     self.someOutlet.alpha = 1.0 
     self.someMethod() 
    }) 

Was ist der Unterschied?

Antwort

3

Der einzige Unterschied zwischen dem Animationsblock und dem Benachrichtigungsmittelblock ist, dass die Animation Block extrem kurzlebig-es wird sofort ausgeführt wird, und dann freigegeben.

In beiden Fällen erfassen die Blöcke self; aber nur der Code NSNotificationCenter ist problematisch, weil das Benachrichtigungszentrum einen Verweis auf den Block für unbegrenzte Zeit halten wird, da die Benachrichtigung jederzeit passieren kann.

Beachten Sie, dass sich dies von einem Zirkelverweis unterscheidet. Eine kreisförmige Bezugs wird oft durch ein Objekt erstellt einen Verweis auf einen Halteblock, der sich selbst erfasst, wie folgt aus:

self.myBlock = { 
    self.doSomething() 
} 

Das kreisförmige Referenz bedeutet, dass self niemals freigegeben werden. Das Benachrichtigungszentrum ist keine zirkuläre Referenz (da self keinen Verweis auf das Benachrichtigungszentrum enthält), es handelt sich lediglich um eine normale Referenz, die gehalten wird, bis der Beobachter entfernt wird.

1

Die Blöcke animations:() -> Void und completion: ((Bool) -> Void)? für eine UIView-Animation behalten keinen Verweis auf self bei. Diese früheren Post ist sehr informativ zum Thema

Do we need to use __weak self inside UIAnimationBlocks in ARC?


Der Benachrichtigungsblock (NSNotification) -> Void hat einen Verweis auf sich selbst behalten, indem sie sie in als herrenlos in Ihrem Fall vorbei, es sollte nicht die Zählung beibehalten erhöhen. Ich versuche sicherzustellen, dass ich bei jeder Referenz, die ich in den Verschluss hineinlasse, entweder "unbenannt" oder "schwach" benutze. Es gibt einen großen Beitrag dazu hier gefunden http://krakendev.io/blog/weak-and-unowned-references-in-swift


Aber ich empfehle verwenden Benachrichtigungen bleiben weg, vor allem mit Blöcken, wie es vielleicht ein Fehler in diesem Artikel darauf hingewiesen, die schockierend war, als ich es gelesen.

http://sealedabstract.com/code/nsnotificationcenter-with-blocks-considered-harmful/

+0

Whoa das ist verrückt, also ist es nur wegen eines Cocoa Bug ich muss das tun? – TruMan1

+0

@ TruMan1Die Antwort, die ich zur Verfügung gestellt habe, zeigte nur ein Problem mit dem Benachrichtigungscenter. Der wahre Grund ist, dass Sie vermeiden wollen, einen starken Referenzzyklus zu erstellen. Ich habe meine Antwort aktualisiert, um das zu berücksichtigen – AntonTheDev