来自Apple文档:
"上面的每个访问级别修饰符都可以选择接受一个参数,该参数由括在括号中的关键字集合组成(例如,private(set)).如果要为变量或下标的setter指定一个小于或等于变量或下标本身的访问级别的访问级别,请使用此形式的访问级别修饰符,如Getters和Setters中所述."
摘录自:Apple Inc."The Swift Programming Language."iBooks. https://itun.es/ru/jEUH0.l
我尝试在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"
我在控制台输出中得到的错误:
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 (Swift.IndexingGenerator.Type)(A) -> Swift.IndexingGenerator + 164 frame #5: 0x000000010ef55f1a libswift_stdlib_core.dylib`protocol witness for Swift._Sequence_.generate (@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) -> Swift._ContiguousArrayBuffer+ 1061 frame #7: 0x000000010ef40281 libswift_stdlib_core.dylib`Swift.Array.convertFromArrayLiteral (Swift.Array.Type)(Swift.Array...) -> Swift.Array + 641 frame #8: 0x000000010f1eaae4 PlaygroundLogger`Swift.UInt64.toBytes (Swift.UInt64)() -> Swift.Array + 292 frame #9: 0x000000010f1eb6a4 PlaygroundLogger`protocol witness for PlaygroundLogger.ToBytes.toBytes (@inout PlaygroundLogger.ToBytes.Self)() -> Swift.Array 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
我究竟做错了什么?我错过了什么吗?
PS1
这个例子工作正常:
struct TrackedString { private(set) var numberOfEdits = 0 var value: String = "" { didSet { numberOfEdits++ } } } var stringToEdit = TrackedString() stringToEdit.value = "Hello" stringToEdit stringToEdit.numberOfEdits += 10 stringToEdit
更多来自文档:
"numberOfEdits属性的访问级别标有私有(set)修饰符,表示该属性只能在与TrackedString结构定义相同的源文件中设置."
摘录自:Apple Inc."The Swift Programming Language."iBooks. https://itun.es/ru/jEUH0.l
但这不是我需要的.是否可以禁止在struct/class之外设置变量numberOfEdits?
你的问题在于:
set { self.name = "Unknown" }
您正在自己的setter中设置计算属性的值.这会导致无限递归.不要忘记这是一个计算属性:它实际上没有存储空间.你没有变量"self.name"来放置任何内容; 你只有几个函数来计算它.像这样的计算属性应该使用其他非计算变量进行存储.(顺便说一下,这就是你的结构示例有效的原因:你正在使用带存储的不动产.)
通过在Playground中运行的事实,您的调试没有得到帮助.别误会我的意思:游乐场很棒.但是,在这种情况下,它需要花费很多秒才能崩溃,因此在编辑后您可能没有出现崩溃.它也没有向你展示一个完整的堆栈跟踪(这对于你正在获得的问题来说很重要,它已经在一个"真正的"应用程序中重现了它,并且可能使你更加明显的是你已经炸掉了堆栈.)当我构建并运行上面作为控制台应用程序,它最终爆炸了104,832深度的堆栈跟踪,除了其中两个之外...private_cmd.A.name.setter...
.有点头绪:)