2016-04-20 13 views
2

Beispiel (in meinem View-Controller):Ich finde mich selbst mit "wenn Selbst! = Null" viel wegen [schwaches Selbst] ... ist das normal?

RESTApi.fetchUser() { [weak self] Void in 
    if self != nil { //the view controller is still here. 
     self!.items.append(stuff) 
     self!.whatever 

    } 
} 

merke ich, dass ich von self! überall if self != nil sofort, gefolgt bin mit. Gibt es einen besseren Weg? Ich denke, das ist gegen den Swift-Weg.

Hinweis: Ich benutze [schwaches Selbst], weil mein ViewController könnte Null sein (wenn der Benutzer zurückgeht, bevor der REST Api die Daten herunterlädt).

+0

Wird die Datei nicht selbst erfasst, so dass es keine Rolle spielt, ob der Benutzer zurückkehrt, bevor die REST-API beendet wurde? – ryantxr

+0

Ich bin mir nicht sicher. Ich verwende immer [schwaches Selbst], wenn es um ViewControllers geht. Kann sonst noch jemand dazu Stellung nehmen? – TIMEX

+0

Es scheint ein gemeinsames Muster zu sein. Ich denke, wenn Sie es nicht schwach machen, kann das eingefangene Selbst einen Referenzzyklus einführen und die Speicherverwaltung durcheinander bringen. – Thilo

Antwort

9

Warum verwenden Sie nicht if let?

if let unwrappedSelf = self { 
    unwrappedSelf.items.append(stuff) 
    ... 
} 

Sie auch guard let verwenden:

guard let unwrappedSelf = self else { return } 

unwrappedSelf.items.append(stuff) 
... 
+0

Danke, das ist cool. Gibt es einen Unterschied zwischen meinem und deinem Weg? – TIMEX

+2

'If let' ist idiomatischer. Entfernt das '!'. Du könntest auch 'Wache machen, sonst komm 'zurückgehen. – Thilo

+0

@TIMEX Thilo ist korrekt. Ich füge die "Wache" zu meiner Antwort hinzu. – tktsubota

6

Idle Sie guard verwenden müssen, die dann die if

guard let strongSelf = self else { return } 

strongSelf.items.append(stuff) 
0

mehr frei ist Wenn Sie nur Methoden auf self aufrufen werden, wenn die Schließung wird aufgerufen, dann müssen Sie nicht einmal if let, guard let oderverwenden. Der Code unten funktioniert auch ganz gut, die Methoden zu nennen, wenn self nicht gleich Null ist, und nichts zu tun, wenn er:

RESTApi.fetchUser() { [weak self] in 
    self?.items.append(stuff) 
    self?.whatever() 
} 

Dieses bedingte Abwickeln in allen Fällen, außer denen, verwendbar ist, wo Sie brauchen self oder passieren Eigenschaft von self als ein Argument zu einem nicht-optionalen Funktionsparameter, oder weisen Sie self oder eine Eigenschaft von self zu einer Variablen mit einem nicht-optionalen Typ zu.

Als eine breitere Anmerkung, es gibt nicht unbedingt eine Notwendigkeit, self in diesem Szenario sowieso schwach zu machen. Das wird normalerweise nur benötigt, wenn self die Schließung beibehält, die self innerhalb als ein ivar referenziert (Kreisreferenz). In Ihrem Fall ist es RestApi, die einen Verweis auf die Schließung enthält, und der View-Controller, den self bezieht, würde von der Schließung beibehalten, bis die Schließung zurückgegeben wird. An diesem Punkt, wenn der View-Controller vom Benutzer bereits zurückgewiesen wurde und die Referenz des Closings die letzte Referenz darauf war, wird sie nach dem Abschluss des Closings aufgehoben (keine zirkuläre Referenz).

So schwach self in diesem Beispiel nur gilt, wenn Sie speziell das Szenario des Verweigerns des View-Controllers, um die Instanz freigeben möchten, und die Schließung, um dann überhaupt nichts auszuführen.

+0

Ein guter Punkt, aber eine schwache Referenz ist immer noch sinnvoll, wenn der View-Controller Null ist. Es hat keinen Sinn, das abgerufene Ergebnis zu verarbeiten.(Angenommen, das abgerufene Ergebnis wird nur für die Anzeige im View-Controller verwendet) – user1046037