2016-06-27 29 views
11

Sto utilizzando la versione DEVELOPMENT-SNAPSHOT-2016-06-06-a di Swift. Non riesco per aggirare questo problema, ho provato ad utilizzare @noescape in vari luoghi, ma ho ancora il seguente errore:Modifica delle variabili di istanza della struct all'interno di una chiusura di Invio in Swift

Closure cannot implicitly capture a mutating self parameter

per spiegare meglio, ecco un semplice esempio:

public struct ExampleStruct { 
    let connectQueue = dispatch_queue_create("connectQueue", nil) 
    var test = 10 

    mutating func example() { 
    if let connectQueue = self.connectQueue { 
     dispatch_sync(connectQueue) { 
     self.test = 20 // error happens here 
     } 
    } 
    } 
} 

Qualcosa deve essere cambiato in questi binari Swift che sta causando la rottura del mio codice precedentemente funzionante. Una soluzione che voglio evitare è rendere la mia struct una classe, che aiuta a risolvere il problema. Fammi sapere se c'è un altro modo.

+0

In Mac OS (la versione Xcode?) O su Linux? –

+0

@ MartinR Sto usando Xcode 7.3.1 su Mac – tfrank377

risposta

11

non posso provarlo, perché non sto usando una build con quell'errore, ma sono abbastanza sicuro catturando auto esplicitamente è possibile risolvere il problema:

dispatch_sync(connectQueue) { [self] in 
    self.test = 20 
} 

EDIT: A quanto pare non funziona, forse si può provare questo (non molto bello TBH):

var copy = self 
dispatch_sync(connectQueue) { 
    copy.test = 20 
} 
self = copy 

Se WA per saperne di più sul perché, here is the responsible Swift proposal.

La nuova API spedizione rende il metodo @noreturnsync quindi non avrebbe bisogno la cattura esplicito:

connectQueue.sync { 
    test = 20 
} 
+0

La cattura di sé continua a darmi un errore: "Previsto 'debole', 'sconosciuto' o nessun identificatore nella lista di cattura. Non vedo l'ora di utilizzare le nuove API, ma suppongo che non vi sia alcuna soluzione con l'implementazione corrente? – tfrank377

+0

@ tfrank377 Ho modificato la mia risposta – Kametrixom

+0

Sì, funziona, ma come hai detto, non molto bello. Penso che userò una classe invece di una struct per avere un codice più pulito. Detto questo, questo risponde alla domanda ed è la soluzione migliore che vedo per l'istantanea Swift del 06/06. – tfrank377

1

Si sta utilizzando Swift3 poiché si è menzionato un recente dev snapshot di Swift. Provate qui sotto e fatemi sapere se funziona:

public struct ExampleStruct { 
    let connectQueue = DispatchQueue(label: "connectQueue", attributes: .concurrent)//This creates a concurrent Queue 

    var test = 10 

    mutating func example() { 
     connectQueue.sync { 
      self.test = 20 
     } 
    } 
} 

Se siete interessati ad altri tipi di code, controllare questi:

let serialQueue = DispatchQueue(label: "YOUR_QUEUE", attributes: .serial) 
serialQueue.sync { 
    // 
} 

Prendi il mainQueue in modo asincrono e in modo sincrono:

DispatchQueue.main.async { 
    //async operations 
} 
DispatchQueue.main.sync { 
    //sync operations 
} 

E se sei interessato in Background:

DispatchQueue.global(attributes: .qosDefault).async { 
    //async operations 
} 

Si potrebbe fare riferimento questo per nuove funzionalità di Swift3 e per le modifiche alla versione attuale: Migrating to Swift 2.3 or Swift 3 from Swift 2.2

+0

Credo in questa particolare istantanea 3 rapida, la classe 'DispatchQueue' non esiste. Ottengo l'errore "identificatore non risolto" quando cerco di usarlo. – tfrank377

+0

possiamo vedere che la tua risposta è stata ispirata da https://stackoverflow.com/a/37806522/1033581 –

Problemi correlati