[英]nil Delegate between two ViewController with two different Bundle (swift)
[英]Two different types of nil in Swift?
我在使用REPL(= Read-Eval-Print-Loop)時在Swift語言中遇到了一些奇怪的行為,其中似乎有兩種不同類型的nil
值在運行時具有不同的行為:
為此,我定義了一個函數g
:
func g(x:String!) {
println("start!");
println((x == "foo") ? "foo" : "not");
}
然后我定義了兩個變量:
var x:String
var y:String!
當我調用g(x)
,它就像Objective-C一樣:
start!
not
當我打電話給g(y)
,我收到一個錯誤:
start!
fatal error: Can't unwrap Optional.None
Execution interrupted. Enter Swift code to recover and continue.
Enter LLDB commands to investigate (type :help for assistance.)
請注意,此錯誤在運行時被捕獲! 該功能已經開始。 你可以看到這個因為“開始!” 輸出中的字符串。
看來,在第一種情況下,函數的值為nil,並附有“這不是零值”的注釋。 在第二種情況下,似乎得到一個零,附加說明“這個值是零,請尖叫,不要只使用它。”
為什么我在第一種情況下沒有出錯,在第二種情況下出錯? 不應該是g(x)和g(y)的行為相同嗎?
這是預期的行為嗎? 我錯過了什么嗎? 這是Swift中的錯誤嗎? 規范中的錯誤? 或者實施中的錯誤? 或者只是REPL中的一個錯誤? 是不是不可能訪問未初始化的變量?
整個會議記錄,供參考......
$ /Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift
Welcome to Swift! Type :help for assistance.
1> func g(x:String!) {println("start!"); println((x=="foo") ? "foo" : "not");}
2> var x:String
x: String = {
core = {
_baseAddress = Builtin.RawPointer = 0x0000000000000000
_countAndFlags = 0
_owner = None
}
}
3> var y:String!
y: String! = nil
4> g(x)
start!
not
5> g(y)
start!
fatal error: Can't unwrap Optional.None
Execution interrupted. Enter Swift code to recover and continue.
Enter LLDB commands to investigate (type :help for assistance.)
6>
要重現整個會話,只需在終端中鍵入以下代碼:
/Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift
func g(x:String!) {println("start!"); println((x=="foo") ? "foo" : "not");}
var x:String
var y:String!
g(x)
g(y)
(該函數寫在一行,因為復制和粘貼功能在REPL中被破壞,至少在我的機器上。但是在一行中編寫它是有效的。這是另一個故事...)
2015年3月更新: Apple似乎解決了這個問題。 如果沒有初始值,則無法再聲明正常變量:
2> var x:String
repl.swift:2:1: error: variables currently must have an initial value when entered at the top level of the REPL
var x:String
^
REPL會自動為您做一些初始化,即使您不想要它
我將您的代碼復制並粘貼到操場上,它會向我拋出此錯誤:
error: variable 'x' used before being initialized
g(x)
^
<REPL>:22:5: note: variable defined here
var x:String
我認為這是正確的結果。 代碼不應該編譯。
當我輸入REPL時
var a:String
它打印
a: String = {
core = {
_baseAddress = Builtin.RawPointer = 0x0000000000000000
_countAndFlags = 0
_owner = None
}
}
所以REPL以某種方式將a
初始化為一個nil
String(我不確定它是否合法存在)並且在其他答案中解釋了故事的其余部分
看起來REPL正在為每個變量進行一些默認初始化,因此您不能使用未初始化的變量
Welcome to Swift! Type :help for assistance.
1> var a:String
a: String = {
core = {
_baseAddress = Builtin.RawPointer = 0x0000000000000000
_countAndFlags = 0
_owner = None
}
}
2> var b:Int
b: Int = 0
3> var c:Int[]
c: Int[] = size=0
4> var d:Dictionary<Int,Int>
d: Dictionary<Int, Int> = {}
更有趣的是它仍然可以使用nil
初始化非可選類型
5> import Foundation
6> var f:NSObject
f: NSObject = {}
7> var g:NSNumber
g: NSNumber = {
Foundation.NSValue = <parent is NULL>
}
8> print(g)
fatal error: Can't unwrap Optional.None
Execution interrupted. Enter Swift code to recover and continue.
因此,REPL將對未初始化的變量(應該是編譯時錯誤)的訪問轉變為運行時錯誤
Welcome to Swift! Type :help for assistance.
1> class Test{ var val:Int; init(v:Int) {val=v} }
2> var t:Test
t: Test = {
val = <parent is NULL>
}
3> t.val
Execution interrupted. Enter Swift code to recover and continue.
Enter LLDB commands to investigate (type :help for assistance.)
4> t = Test(v:1)
5> t.val
$R2: Int = 1
6>
這是預期的行為。
var y:String!
(帶有感嘆號)是一個“隱式解包的可選項”,這意味着它是可選的,但是當你想要訪問它時,你不需要打開它(添加!)。 但是,像可選項一樣,當您嘗試訪問它時,如果它沒有值,您將觸發運行時異常:
從“The Swift Programming Language” - 第78頁
“如果在不包含值時嘗試訪問隱式展開的可選項,則會觸發運行時錯誤。 結果與在不包含值的普通可選項之后放置感嘆號完全相同。“
因此,g(y)崩潰的事實是正確的。 看起來很奇怪的是g(x)不會崩潰,但它似乎是REPL的一種行為,它會為你初始化x。
對於非可選值,nil的概念不存在。 所以,x不是零,它就像“未初始化”。 如果您嘗試將此代碼放在實際項目中
func g(testValue:String!) {
println("start!");
println((testValue == "foo") ? "foo" : "not");
}
var x:String
var y:String!
g(x)
g(y)
它不會編譯,你會收到:
在初始化之前使用變量'x'
這是預期的行為嗎? 我錯過了什么嗎? 這是Swift中的錯誤嗎?
看起來這是由於您之前在REPL中的活動。 這是我將代碼粘貼到游樂場時得到的結果:
Playground execution failed: error: code after 'return' will never be executedcode after 'return' will never be executed<REPL>:8:3: error: variable 'x' used before being initialized
g(x)
^
<REPL>:6:5: note: variable defined here
var x:String
基本上,它抱怨你使用x
而沒有先給它一個值。 在你的發言全文回首,但是, 你給x
線2的值:
2> var x:String
x: String = {
core = {
_baseAddress = Builtin.RawPointer = 0x0000000000000000
_countAndFlags = 0
_owner = None
}
}
因此編譯器對x
沒問題也就不足為奇了。 您獲得的錯誤是由於y
被聲明為隱式展開的變量。 您將其設置為nil
,嘗試訪問它,並獲得一個運行時錯誤,指出該值無法解開。 這里的錯誤並不令人驚訝 - 當你試圖強行打開一個nil變量時,應該會發生這種情況。
var x:String
必須有一個價值。 可能不會是零。
那就是問題所在。 您不應該使用未初始化的變量(它不是可選的)。
var y:String!
可以使用未初始化,值可以為零。 是喜歡寫作
var y:String? //但是每次我使用它都請在y之后為我添加感嘆號
所以而不是y!
你可以寫y。 但價值可能是nil
。 當值為nil
時使用y
- >崩潰。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.