なぜプライベート(セット)が迅速で機能していないのですか?
-
26-12-2019 - |
質問
Apple Docsから:
"上記の各アクセスレベルの修飾子は任意選択で単一のものを受け入れます 括弧で囲まれたキーワードセットからなる引数 (たとえば、プライベート(セット))。この形式のアクセスレベルを使用してください のセッターのアクセスレベルを指定したい場合の修飾子 変数または添え字は、そのアクセスレベル以下のもの以下のものです。 ゲッターで説明したように、変数または添え字自体 セッターズ。 "
抜粋:Apple Inc.「Swiftプログラミング言語」 iBooks。 https://itun.es/ru/jeuh0.l
遊び場でテストしようとする例:
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 <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
.
私は何をしていますか?私は何かがありませんか?
ps1
この例はうまく機能します:
struct TrackedString {
private(set) var numberOfEdits = 0
var value: String = "" {
didSet {
numberOfEdits++
}
}
}
var stringToEdit = TrackedString()
stringToEdit.value = "Hello"
stringToEdit
stringToEdit.numberOfEdits += 10
stringToEdit
.
DOCSからの詳細:
"NumberSofEditsプロパティのアクセスレベルには、 プロパティが設定可能なことを示すためのプライベート(設定)修飾子 TrackedString構造体と同じソースファイル内からのみ 定義。 "
抜粋:Apple Inc.「Swiftプログラミング言語」 iBooks。 https://itun.es/ru/jeuh0.l
しかしそれは私が必要なものではありません。 struct / classの外部の変数NubledoFeDitsを設定することはできませんか?
解決
あなたの問題はここにあります:
set { self.name = "Unknown" }
.
自分のセッター内に計算されたプロパティの値を設定します。これにより無限再帰が引き起こされます。これが computed プロパティであることを忘れないでください:それは実際にはストレージを持っていません。何かを置く変数 "self.name"はありません。それを計算するためのいくつかの機能しかありません。このような計算されたプロパティは、ストレージのための他の非計算変数を使用する必要があります。 (それがあなたの構造の例が機能する理由であるのですが、次のようにしてください。)
あなたは遊び場で走っているという事実によってあなたのデバッグに役立っていません。間違っていない:遊び場は素晴らしいです。ただし、この場合、クラッシュするのには何秒かかりますので、編集後に衝突が表示されていない場合はおそらく表示されません。それはまたあなたにフルスタックトレースを表示していません(これはあなたが「実際の」アプリで複製した問題のために巨大です。上記をコンソールアプリとして構築して実行しました。つまり、最終的にスタックトレース104,832呼び出しを深く吹き飛ばします。手がかりのビット:)