2017-03-15 55 views
1

我想提高我的調試技巧,所以開始閱讀here。我有以下的代碼:Xcode + LLDB:試圖用'表達式'來改變變量值

var label = "tom" 
self.label.text = label 
print(label) 

我在每一行的一個破發點,並在他們每個人的I型

expression label = "jones" 
po label 

所以,當我鍵入po label我得到預期的結果是jones,但標籤和控制檯(print(label))中顯示的文字是tom

我鏈接的教程指出,這些更改應該在程序的整個運行過程中生效。它是假的,還是我做錯了什麼?

我正在使用iPhone 7 Plus模擬器的Xcode版本8.2.1(8C1002)。

謝謝!

+1

我不知道關於swift的crapballs,但如果這是objc,你正在做的事情將無法工作......將標籤分配給文本後,現在有2個指向同一個字符串的指針,並且如果更改了舊標籤,它不會改變self.label.text指向的內容......除非有一些KVO正在進行......「po self.label.text =」jones「'做了什麼? –

+0

當然,字符串是一個結構體,我只是創建了一個由'label'指向的新結構體,而self.label.text仍然指向了舊結構體。輝煌! :) – Yotam

回答

1

我不確定這有幫助,但是發生的情況比您想象的要複雜一點。

斯威夫特琴絃實際上是結構,因此,如果你停止了就行分配給self.text.label之前,並分配一個新的價值,您label變種,你實際上改變的是結構的內容,應該由所有權利意味着當你從該結構中分配到self.text.label時,它確實應該獲得新的值...

不工作的原因是swift編譯器聰明地解開了這些結構,以便它不會做不必要的儘可能提供解除引用。這種情況甚至發生在-Onone

因此,舉例來說,在你的例子中,swift編譯代碼已經將字符串和發出的代碼直接引用了內容。更改實際的字符串內容不會更改對分配代碼中已有的取消裝箱內容的引用,因此您的更改不會執行。

你可以看到這個IRL:如果你讓編譯器無法知道字符串的內容是什麼,它不能做這個拆箱,然後你會看到你的調試器更改生效。

使用此代碼示例:在調試器

class HasLabel 
{ 
    var label : String = "Default Value" 
} 

func 
main() 
{ 
    var myLabel = HasLabel() 
    var string = "set in code" 

    string.removeSubrange(string.startIndex..<string.endIndex) 
    string.append("Different string in code") 
    myLabel.label = string // Set a breakpoint here 
    print ("Did it change? string: \"\(string)\" Label: \"\(myLabel.label)\"") 
} 

main() 

,我看到:

(lldb) br s -p "Set a breakpoint here" 
Breakpoint 1: where = tryme`tryme.main() ->() + 499 at tryme.swift:14, address = 0x0000000100001e93 
(lldb) run 
Process 8323 launched: '/private/tmp/tryme' (x86_64) 
Process 8323 stopped 
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 
    frame #0: 0x0000000100001e93 tryme`tryme.main() ->() at tryme.swift:14 
    11 
    12  string.removeSubrange(string.startIndex..<string.endIndex) 
    13  string.append("Different string in code") 
-> 14  myLabel.label = string // Set a breakpoint here 
     ^
    15  print ("Did it change? string: \"\(string)\" Label: \"\(myLabel.label)\"") 
    16 } 
    17 
(lldb) expr string = "Set in debugger" 
(lldb) c 
Process 8323 resuming 
Did it change? string: "Set in debugger" Label: "Set in debugger" 
Process 8323 exited with status = 0 (0x00000000) 

在那裏你看到調試變化居然拿了。但是,如果您註釋掉string.removeSubrangestring.append,那麼更改將不再需要。

+0

非常有用,非常感謝! – Yotam

+0

@Jim「如果你讓編譯器無法知道字符串的內容是什麼,它不能做這個拆箱,然後你會看到你的調試器更改生效。」我不確定我是否理解正確。你是說只要有一些影響運行時結構屬性的代碼,比如'removeSubrange',那麼調試器中的變化就會生效? 「Int」會發生什麼變化?我嘗試用multiplication之類的東西來修改屬性,但是從'expr'的更改仍然不會發生。 – HuaTham

+0

Ints很簡單,我對如何解決這個問題沒有很好的建議。將它作爲某個函數的inout參數傳遞可能會有所裨益。 –