Pregunta

De documentos de Apple:

“Cada modificador de nivel de acceso anterior acepta opcionalmente un solo argumento, que consiste en el conjunto de palabras clave encerradas entre paréntesis (por ejemplo, privado (set)).Use esta forma de un modificador de nivel de acceso cuando desee especificar un nivel de acceso para el setter de una variable o subíndice que es menor o igual al nivel de acceso de la variable o subíndice en sí, como se discutió en Getters y Setters ".

Extracto de:Apple Inc."El lenguaje de programación rápida". iBooks. https://itun.es/ru/jEUH0.l

Un ejemplo que intento probar en Playground:

import UIKit


class A {
  private(set) var name: String {
  get { return "Hello, \(self.name)" }
  set { self.name = "Unknown" }
  }

  init(_ name:String) {
    self.name = name
  }
}

let a = A("Andrew")
a.name = "Hello"

Un error que aparece en la salida de la consola:

Playground execution failed: error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=2, address=0x7fff5056eff8).
The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
* thread #1: tid = 0xea721, 0x00000001104f308c libsystem_pthread.dylib`__mtx_droplock + 222, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x7fff5056eff8)
  * frame #0: 0x00000001104f308c libsystem_pthread.dylib`__mtx_droplock + 222
    frame #1: 0x00000001104f2f07 libsystem_pthread.dylib`pthread_mutex_unlock + 68
    frame #2: 0x000000010ffbd2b5 libc++.1.dylib`std::__1::mutex::unlock() + 9
    frame #3: 0x000000010f040b94 libswift_stdlib_core.dylib`swift_getGenericMetadata + 260
    frame #4: 0x000000010ef28a24 libswift_stdlib_core.dylib`Swift.IndexingGenerator.init <A : Swift._Collection>(Swift.IndexingGenerator<A>.Type)(A) -> Swift.IndexingGenerator<A> + 164
    frame #5: 0x000000010ef55f1a libswift_stdlib_core.dylib`protocol witness for Swift._Sequence_.generate <A : Swift._Sequence_>(@inout Swift._Sequence_.Self)() -> Swift._Sequence_.Self.GeneratorType in conformance Swift._ContiguousArrayBuffer : Swift._Sequence_ + 154
    frame #6: 0x000000010ef284d5 libswift_stdlib_core.dylib`Swift._copyCollectionToNativeArrayBuffer <A : protocol<Swift._Collection, Swift._Sequence_>>(A) -> Swift._ContiguousArrayBuffer<A.GeneratorType.Element> + 1061
    frame #7: 0x000000010ef40281 libswift_stdlib_core.dylib`Swift.Array.convertFromArrayLiteral <A>(Swift.Array<A>.Type)(Swift.Array<A>...) -> Swift.Array<A> + 641
    frame #8: 0x000000010f1eaae4 PlaygroundLogger`Swift.UInt64.toBytes (Swift.UInt64)() -> Swift.Array<Swift.UInt8> + 292
    frame #9: 0x000000010f1eb6a4 PlaygroundLogger`protocol witness for PlaygroundLogger.ToBytes.toBytes <A : PlaygroundLogger.ToBytes>(@inout PlaygroundLogger.ToBytes.Self)() -> Swift.Array<Swift.UInt8> in conformance Swift.UInt64 : PlaygroundLogger.ToBytes + 20
    frame #10: 0x000000010f1dbe3d PlaygroundLogger`PlaygroundLogger.BytesStream.write (PlaygroundLogger.BytesStream)(PlaygroundLogger.ToBytes) -> PlaygroundLogger.BytesStream + 77
    frame #11: 0x000000010f1dbd74 PlaygroundLogger`PlaygroundLogger.BytesStream.write (PlaygroundLogger.BytesStream)(Swift.String) -> PlaygroundLogger.BytesStream + 164
    frame #12: 0x000000010f20f04b PlaygroundLogger`PlaygroundLogger.PlaygroundWriter.encode_config_info (PlaygroundLogger.PlaygroundWriter)() -> () + 203
    frame #13: 0x000000010f20f2bf PlaygroundLogger`PlaygroundLogger.PlaygroundWriter.encode_header (PlaygroundLogger.PlaygroundWriter)() -> () + 127
    frame #14: 0x000000010f20ecda PlaygroundLogger`PlaygroundLogger.PlaygroundScopeWriter.encode_scope_event (PlaygroundLogger.PlaygroundScopeWriter)(PlaygroundLogger.ScopeEvent) -> () + 58
    frame #15: 0x000000010f1eb997 PlaygroundLogger`playground_log_scope_entry + 87
    frame #16: 0x000000011ae20771

¿Qué estoy haciendo mal?¿Me estoy perdiendo de algo?

PS1

Este ejemplo funciona bien:

struct TrackedString {
  private(set) var numberOfEdits = 0
  var value: String = "" {
  didSet {
    numberOfEdits++
  }
  }
}

var stringToEdit = TrackedString()
stringToEdit.value = "Hello"
stringToEdit
stringToEdit.numberOfEdits += 10
stringToEdit

Más de documentos:

"El nivel de acceso para la propiedad NumberOfEdits está marcado con un modificador privado (establecido) para indicar que la propiedad debe estar establecida solo desde el mismo archivo fuente que la definición de la estructura de rastreado".

Extracto de:Apple Inc."El lenguaje de programación rápida". iBooks. https://itun.es/ru/jEUH0.l

enter image description here

Pero eso no es lo que necesito.¿Es posible no permitir establecer la variable numberOfEdits fuera de la estructura/clase?

¿Fue útil?

Solución

Tu problema está aquí:

  set { self.name = "Unknown" }

Estás configurando el valor de una propiedad calculada dentro de su propio definidor.Esto provoca una recursividad infinita.No olvides que este es un calculado propiedad:en realidad no tiene almacenamiento.No tienes una variable "self.name" para poner nada;sólo tienes un par de funciones para calcularlo.Las propiedades calculadas como esta deberían utilizar otras variables no calculadas para el almacenamiento.(Por cierto, es por eso que su ejemplo de estructura funciona:está utilizando una propiedad real con almacenamiento).

El hecho de ejecutar en un patio de juegos no le ayudará en la depuración.No me malinterpretes:Los parques infantiles son geniales.Sin embargo, en este caso, el bloqueo tarda muchos segundos, por lo que es probable que el bloqueo no aparezca cuando se espera después de una edición.Tampoco te muestra un seguimiento completo de la pila (lo cual es enorme para el problema que estás teniendo, ya que lo reprodujiste en una aplicación "real" y podría haber hecho más obvio que habías arruinado la pila). construyó y ejecutó lo anterior como una aplicación de consola, finalmente explotó con un seguimiento de pila de 104,832 llamadas de profundidad, todas menos dos de las cuales fueron ...private_cmd.A.name.setter....Una pequeña pista :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top