2015-09-15 9 views
19

C'è un similar question su come weakify/strongify sé, a cui risponde, ma mi chiedo come utilizzare "self", senza verso destra-alla deriva causata da if let:Come "strongify" optional auto utilizzando guardia Swift 2.0

Welcome to Apple Swift version 2.0 (700.0.59 700.0.72). Type :help for assistance. 
    2> import Foundation 
    3> class Foo { 
    4.  func guardOptSelf() ->() throws -> Void { 
    5.   return { [weak self] in 
    6.    guard let self = self else { throw NSError(domain: "I was destroyed!", code: 1, userInfo: nil) } 
    7.    self.doSomethingNonOptionalSelf()   
    8.   } 
    9.  } 
    10. } 
repl.swift:6:19: error: pattern matching in a condition requires the 'case' keyword 
      guard let self = self else { throw NSError(domain: "I was destroyed!", code: 1, userInfo: nil) } 
       ^
        case 
repl.swift:6:23: error: binary operator '~=' cannot be applied to two 'Foo?' operands 
      guard let self = self else { throw NSError(domain: "I was destroyed!", code: 1, userInfo: nil) } 

risposta

30

È possibile ombra self; hai solo bisogno di apici inversi per indicare che "sai cosa stai facendo". Per esempio:

foo.doSomethingAsyncWithBar(bar) { [weak self] result in 
    guard let `self` = self else { return } 
    self.receivedResult(result) 
} 

Oppure, nel tuo esempio:

2> import Foundation 
3> class Foo { 
4.  func guardOptSelf() ->() throws -> Void { 
5.   return { [weak self] in 
6.    guard let `self` = self else { throw NSError(domain: "I was destroyed!", code: 1, userInfo: nil) } 
7.    self.doSomethingNonOptionalSelf()   
8.   } 
9.  } 
10. } 
+1

Ah, bello! Non conoscevo la funzionalità della lingua backtick. Sembra che anche questo non sia influenzato dalle impostazioni di avviso del compilatore per ombreggiatura variabile, quali librerie come libextobjc devono sopprimere nella loro implementazione di @ weakify/strongify –

+9

Anche se funziona, non è affidabile in quanto Chris Lattner di Apple lo ha dichiarato come un "bug del compilatore". - e poiché si tratta di un bug, potrebbe essere corretto in futuro: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160118/007425.html –

+0

Non sono sicuro che io capire completamente la domanda, né la tua risposta. ** 1) ** La domanda è chiedersi 'cosa dovremmo fare se un' sé 'catturato viene espulso prima che sia finito? ** 2) ** Per fare ciò, dobbiamo fare un passo in più, cioè più del normale '[self debole]'. Dovremmo catturarlo usando un riferimento forte come 'guard let' ** 3) ** per rendere le cose belle e fluide usiamo i backtick in modo che' self' venga scartato, perché usare 'weak' converte' self' in un opzionale e noi può anche mantenere lo stesso nome di * self *? – Honey

3

Perché guard let `self` = self è un compiler bug as stated by Chris Lattner cercherei di evitarlo. Nel tuo esempio è possibile utilizzare solo semplice concatenamento opzionale:

return { [weak self] in 
    self?.doSomethingNonOptionalSelf()   
} 

A volte potrebbe essere necessario utilizzare auto come parametro. In tal caso è possibile utilizzare flatMap (su un tipo opzionale):

{ [weak self] in 
    self.flatMap { $0.delegate?.tableView($0, didSelectRowAt: indexPath) } 
} 

Nel caso in cui è necessario fare qualcosa di più complicato è possibile utilizzare if let costrutto:

{ [weak self] in 
    if let strongSelf = self { 
     // Do something more complicated using strongSelf 
    } 
} 

o guard let costrutto:

{ [weak self] in 
    guard let strongSelf = self else { return } 

    // Do something more complicated using strongSelf 
} 

oppure è possibile creare un metodo privato:

{ [weak self] in 
    self?.doSomethingMoreComplicated() 
} 

... 

private func doSomethingMoreComplicated() { 
    // Do something more complicated 
} 
+0

Grazie per le diverse alternative. Potremmo aggiungere 'guardia lasciare strongSelf = self else {return}'. È un peccato che non ci sia un modo più breve per esprimere questo idioma comune. Ad esempio qualcosa come '[if self] in self.method()' dove viene eseguita la chiusura se self non è nullo. –

+0

Grazie a @FerranMaylinch, ho modificato la risposta per includere anche 'guard let'. –

Problemi correlati