2016-11-28 5 views
1

スウィフト配列はクラスが参照型である間は値型であるため、[SomeClass]のようなものはSomeClassインスタンスへの参照を含む配列を作成すると考えました。 弱い変数のリリースでのスウィフト配列の混乱

1> class SomeClass {} 
    2> var obj: SomeClass? = SomeClass() 
obj: SomeClass? = 0x0000000101100050 
    3> weak var weakObj = obj 
weakObj: SomeClass? = 0x0000000101100050 
    4> var array = [SomeClass?]() 
array: [SomeClass?] = 0 values 
    5> array.append(obj) 
    6> print(obj, weakObj) 
Optional(SomeClass) Optional(SomeClass) 
    7> array.removeFirst() 
$R0: SomeClass? = 0x0000000101100050 
    8> obj = nil 
    9> print(obj, weakObj) 
nil Optional(SomeClass) 
10> print(array) 
[] 
11> print(Unmanaged.passUnretained(weakObj!).toOpaque()) 
0x0000000101100050 

は私が 0x0000000101100050でのインスタンスの参照カウントが arrayobjを付加した後2でなければならないと思った、と obj = nilarray.removeFirst()たら、両方の参照と呼ばれていました:

しかし、スウィフトREPLでは、次の処理が行われインスタンスが解放される必要があります。

しかし、これはそうではないようです。配列部分がなければ、objがリリースされているように解放されます。私はここで何が欠けていますか?

removeFirst()で起こって何か、popLast()と同様の機能があるように思え を追加しました。 (おそらくバグ?)

うまくnil作品への直接配列インデックスでオブジェクトを設定します。 array自体が解放されたときしかし

102> obj = SomeClass() 
103> (weakObj, array) = (obj, [obj]) 
104> print(obj, weakObj, array) 
Optional(SomeClass) Optional(SomeClass) Optional([Optional(SomeClass)]) 
105> obj = nil 
106> array?[0] = nil 
$R14:()? = nil 
107> print(obj, weakObj, array) 
nil nil Optional([nil]) 

removeLast()またはpopLast()を使用して、weakObjにのみリリースされます。

+0

私はあなたが配列から削除すると、 '$ R0'が強い参照 – Alexander

+0

を保持しているかもしれないと思う、' removeFirst'機能削除されたオブジェクトが返されます。これは '$ R0'によって強く参照され、オブジェクトを生かしたままにします。私の答えを見てください。 – Alexander

答えて

1

array.removeFirst()オンラインで7は、削除されたオブジェクトを返しています。 replはこれを$R0に割り当てます。これはあなたのオブジェクトを存続させる強力な参照です。

あなたのコードは、明示的に_ =で結果を破棄する場合は、期待通りに動作します。

Welcome to Apple Swift version 3.0.1 (swiftlang-800.0.58.6 clang-800.0.42.1). Type :help for assistance. 
    1> class SomeClass {} 
    2> var obj: SomeClass? = SomeClass() 
obj: SomeClass? = 0x00000001006005b0 
    3> weak var weakObj = obj 
weakObj: SomeClass? = 0x00000001006005b0 
    4> var array = [SomeClass?]() 
array: [SomeClass?] = 0 values 
    5> array.append(obj) 
    6> print(obj, weakObj) 
Optional(SomeClass) Optional(SomeClass) 
    7> _ = array.removeFirst() 
    8> obj = nil 
    9> print(obj, weakObj) 
nil nil 
10> print(array) 
[] 
11> print(Unmanaged.passUnretained(weakObj!).toOpaque()) 
fatal error: unexpectedly found nil while unwrapping an Optional value 
2016-11-27 20:58:42.066831 repl_swift[62143:10516084] fatal error: unexpectedly found nil while unwrapping an Optional value 
Current stack trace: 
0 libswiftCore.dylib     0x00000001002bccc0 swift_reportError + 132 
1 libswiftCore.dylib     0x00000001002da070 _swift_stdlib_reportFatalError + 61 
2 libswiftCore.dylib     0x00000001000d00a0 specialized specialized StaticString.withUTF8Buffer<A> ((UnsafeBufferPointer<UInt8>) -> A) -> A + 355 
3 libswiftCore.dylib     0x000000010024c210 partial apply for (_fatalErrorMessage(StaticString, StaticString, StaticString, UInt, flags : UInt32) -> Never).(closure #2) + 109 
4 libswiftCore.dylib     0x00000001000d00a0 specialized specialized StaticString.withUTF8Buffer<A> ((UnsafeBufferPointer<UInt8>) -> A) -> A + 355 
5 libswiftCore.dylib     0x00000001002043d0 specialized _fatalErrorMessage(StaticString, StaticString, StaticString, UInt, flags : UInt32) -> Never + 96 
7 repl_swift       0x0000000100001420 main + 0 
8 libdyld.dylib      0x00007fffaaec7254 start + 1 
Execution interrupted. Enter code to recover and continue. 
Enter LLDB commands to investigate (type :help for assistance.) 
12> 
+0

私はREPLがどのように動作するかを読んでおくべきだと思います。 '$ R0'があなたがREPLで参照できるものであることを知らなかった。 – BridgeTheGap

+1

ええ、それは本当に便利です。式の結果を変数に代入しなかった場合(または '_'でそれを破棄した場合)、REPLは新しい' $ R'変数を作成します。あなたが使いたいと思っていなかった過去の価値を使うことはとても便利です。 – Alexander

+0

@BridgeTheGap質問に答えましたか? – Alexander

2

は、一般的に言って、REPL(あるいは遊び場)が働いているかスウィフトARC試すには良い場所ではありません。

import Foundation 

class SomeClass {} 
var obj: SomeClass? = SomeClass() 
weak var weakObj = obj 
var array = [SomeClass?]() 
array.append(obj) 
print(obj, weakObj) //->Optional(SwiftArrayARC.SomeClass) Optional(SwiftArrayARC.SomeClass) 
array.removeFirst() 
obj = nil 
print(obj, weakObj) //->nil nil 
print(array) //->[] 
print(Unmanaged.passUnretained(weakObj!).toOpaque()) //=>fatal error: unexpectedly found nil while unwrapping an Optional value 

はこれが何を期待されていません。

はMacOSののコマンドラインプロジェクトとしてあなたのコードを試してみましたか?

REPLを使用すると、後でそれらを使用できるように、各ラインの結果のための強い参照を保持することができるので、実際のアプリのように、REPL環境で、あなたはまったく同じ動作を取得することはできません。

はそれでプレーンなコマンドラインプロジェクトと実験を作成します。 (注意:LLDBはまた、強い参照を保持することがあります。)それに頼らないでください。

+0

お役立ち情報私は遊び場が物体を抱えていることを知っていたので、私はREPLを試していました。 REPLが同じことをしたことを知らなかった – BridgeTheGap