2016-04-25 10 views
1

Viele Posts scheinen von Benachrichtigungen abzuweichen, wenn versucht wird, Funktionen zu synchronisieren, aber es gibt auch andere Posts, die davor warnen, Callbacks zu schließen, weil sie versehentlich Objekte behalten und Speicherprobleme verursachen können.Bedenken hinsichtlich des Speichers bei der Wahl zwischen Benachrichtigung und Rückruf bei Netzwerkanrufen?

In einer benutzerdefinierten Ansicht Controller ist eine Funktion foo, die die Klasse Bar verwendet, um Daten vom Server zu erhalten.

class CustomViewController : UIViewController { 

    function foo() { 
     // Do other stuff 
     // Use Bar to get data from server 
     Bar.getServerData() 
    } 

} 

Option 1:getServerData definieren einen Rückruf zu akzeptieren. Definieren Sie den Rückruf als einen Abschluss innerhalb CustomViewController.

Option 2: Verwenden Sie NSNotifications anstelle eines Rückrufs. Geben Sie in getServerData einen NSNotification ein, wenn der Server Daten zurückgibt, und stellen Sie sicher, dass CustomViewController für die Benachrichtigung registriert ist.

Option 1 scheint aus allen Gründen wünschenswert, die Menschen vor NSNotification warnen (z. B. Compiler-Prüfungen, Rückverfolgbarkeit), aber kein Callback verursacht ein potenzielles Problem, bei dem CustomViewController unnötigerweise beibehalten wird und daher möglicherweise Speicherprobleme entstehen?

Wenn ja, ist der richtige Weg, um das Risiko zu mindern, indem Sie einen Rückruf verwenden, aber keine Schließung verwenden? Mit anderen Worten: Definieren Sie eine Funktion innerhalb von CustomViewController mit einer Signatur, die dem getServerData Callback entspricht, und übergeben Sie den Zeiger an diese Funktion an getServerData?

+0

IMHO, beide sind gültige Ansätze. Option 1 ist viel prägnanter, verständlicher und leichter zu korrigieren. Daher wird Option 1 bevorzugt. Es scheint jedoch, dass Sie durch andere Antworten fehlgeleitet sind: Speicherverwaltung und Synchronisierung sind orthogonale Konzepte und haben ihre eigenen Probleme. – CouchDeveloper

Antwort

0

Ich gehe immer mit Option 1 müssen Sie nur daran erinnern, mit [weak self] oder was auch immer Sie brauchen, um zu "schwächen", um Speicherprobleme zu vermeiden.

Ein echtes Beispiel:

filterRepository.getFiltersForType(filterType) { [weak self] (categories) in 
    guard let strongSelf = self, categories = categories else { return } 
    strongSelf.dataSource   = categories 
    strongSelf.filteredDataSource = strongSelf.dataSource 
    strongSelf.tableView?.reloadData() 
} 

So in diesem Beispiel können Sie sehen, dass ich Bezug auf self zum Abschluss Schließung passieren, aber als weak Referenz. Dann überprüfe ich, ob das Objekt noch existiert - wenn es noch nicht freigegeben wurde, mit guard Anweisung und Entpacken weak Wert.

Definition von Netzanruf mit Abschluss Schließung:

class func getFiltersForType(type: FilterType, callback: ([FilterCategory]?) ->()) { 
    connection.getFiltersCategories(type.id).response { (json, error) in 
     if let data = json { 
      callback(data.arrayValue.map { FilterCategory(attributes: $0) }) 
     } else { 
      callback(nil) 
     } 
    } 
} 
+2

Das Bedürfnis nach "schwachem Selbst" ist oft übertrieben. Sie benötigen einen Zirkelverweis, um einen Retain-Zyklus und damit ein Speicherleck zu generieren. In Ihrem Beispiel erfasst der Abschluss "self", aber das 'FilterRepository' erfasst den Abschluss nicht in einer strong Eigenschaft, sodass, sobald 'getFiltersForType' den Abschluss auslöst, dieser auf dem Abschluss gehalten wird.Das bedeutet, dass der Verschluss gelöst wird und die Verschlüsse am aufrufenden Objekt ('self') gehalten werden, so dass alles schön aufräumt. – Paulw11

+0

@ Paulw11 danke für den Kommentar, ich habe einen Fehler beim Kopieren des Codes gemacht,' filterRepository' ist eine Eigenschaft in meinem Datenquellenobjekt, daher "schwach" – Krodak

+0

Es spielt keine Rolle, 'filterRepository' - Sie haben nur das Potenzial für ein Leck, wenn Sie etwas tun wie' self.closureProperty = Callback' in 'getFiltersForType' – Paulw11

0

Ich stehe für Verschlüsse in diesem Fall. Um unnötige Rücklagen zu vermeiden, müssen Sie nur sicherstellen, dass der Verschluss ordnungsgemäß capture list definiert ist.