Air*_*ity 43 optional ios swift swift2
通常,您需要编写如下代码:
if someOptional != nil {
    // do something with the unwrapped someOptional e.g.       
    someFunction(someOptional!)
}
这似乎有点冗长,而且我听说使用!强制解包操作符可能是不安全的,最好避免使用.有没有更好的方法来处理这个?
Air*_*ity 110
几乎总是不必检查是否有可选项nil.几乎是你唯一需要做的事情就是它nil的唯一性是你想知道的 - 你不关心它的价值,只是它不是nil.
在大多数其他情况下,有一些Swift简写,可以更安全,更简洁地if为您完成任务.
如果不是,则使用该值 nil
代替:
let s = "1"
let i = Int(s)
if i != nil {
    print(i! + 1)
}
你可以使用if let:
if let i = Int(s) {
    print(i + 1)
}
您还可以使用var:
if var i = Int(s) {
    print(++i)  // prints 2
}
但请注意,这i将是一个本地副本 - 任何更改i都不会影响原始可选内的值.
您可以在一个中打开多个选项if let,以后可以依赖于之前的选项:
if let url = NSURL(string: urlString),
       data = NSData(contentsOfURL: url),
       image = UIImage(data: data)
{
    let view = UIImageView(image: image)
    // etc.
}
您还可以where向已解包的值添加子句:
if let url = NSURL(string: urlString) where url.pathExtension == "png",
   let data = NSData(contentsOfURL: url), image = UIImage(data: data)
{ etc. }
替换nil为默认值
代替:
let j: Int
if i != nil {
    j = i
}
else {
    j = 0
}
要么:
let j = i != nil ? i! : 0
你可以使用nil-coalescing运算符,??:
// j will be the unwrapped value of i,
// or 0 if i is nil
let j = i ?? 0
将可选项与非可选项等同
代替:
if i != nil && i! == 2 {
    print("i is two and not nil")
}
您可以检查选项是否等于非可选值:
if i == 2 {
    print("i is two and not nil")
}
这也适用于比较:
if i < 5 { }
nil总是等于其他nils,并且小于任何非nil值.
小心!这里可能有问题:
let a: Any = "hello"
let b: Any = "goodbye"
if (a as? Double) == (b as? Double) {
    print("these will be equal because both nil...")
}
在可选项上调用方法(或读取属性)
代替:
let j: Int
if i != nil {
    j = i.successor()
}
else {
   // no reasonable action to take at this point
   fatalError("no idea what to do now...")
}
你可以使用可选的链接,?.:
let j = i?.successor()
注意,j现在也将是可选的,以考虑该fatalError方案.之后,您可以使用此答案中的其他技巧之一来处理其j可选性,但您通常可以推迟实际解开您的选项,直到很久以后,或者有时根本不打开.
顾名思义,你可以链接它们,所以你可以写:
let j = s.toInt()?.successor()?.successor()
可选链接也适用于下标:
let dictOfArrays: ["nine": [0,1,2,3,4,5,6,7]]
let sevenOfNine = dictOfArrays["nine"]?[7]  // returns {Some 7}
和功能:
let dictOfFuncs: [String:(Int,Int)->Int] = [
      "add":(+),
      "subtract":(-)
]
dictOfFuncs["add"]?(1,1)  // returns {Some 2}
分配给可选项上的属性
代替:
if splitViewController != nil {
    splitViewController!.delegate = self 
}
您可以通过可选链分配:
splitViewController?.delegate = self
只有在不splitViewController存在的情况下nil才能进行分配.
使用该值,如果不是nil,或使用bailing(Swift 2.0中的新增功能)
有时候在一个函数中,你需要编写一小段代码来检查一个可选项,如果是nil,则提前退出函数,否则继续.
你可以这样写:
func f(s: String) {
    let i = Int(s)
    if i == nil { fatalError("Input must be a number") }
    print(i! + 1)
}
或者为了避免力量展开,像这样:
func f(s: String) {
    if let i = Int(s) {
        print(i! + 1)
    }
    else { 
        fatalErrr("Input must be a number")
    }
}
但是通过检查将错误处理代码保持在最顶端会更好.这也可能导致令人不快的筑巢("厄运金字塔").
相反,你可以使用guard,这就像一个if not let:
func f(s: String) {
    guard let i = Int(s)
        else { fatalError("Input must be a number") }
    // i will be an non-optional Int
    print(i+1)
}
该else部分必须退出保护值的范围,例如a return或fatalError,以保证保护值对范围的其余部分有效.
guard不限于功能范围.例如以下内容:
var a = ["0","1","foo","2"]
while !a.isEmpty  {
    guard let i = Int(a.removeLast())
        else { continue }
    print(i+1, appendNewline: false)
}
打印321.
循环遍历序列中的非零项(Swift 2.0中的新项)
如果您有一系列可选项,则可以使用for case let _?迭代所有非可选元素:
let a = ["0","1","foo","2"]
for case let i? in a.map({ Int($0)}) {
    print(i+1, appendNewline: false)
}
打印321.这是使用模式匹配语法的可选项,后面是变量名称?.
您还可以在switch语句中使用此模式匹配:
func add(i: Int?, _ j: Int?) -> Int? {
    switch (i,j) {
    case (nil,nil), (_?,nil), (nil,_?):
        return nil
    case let (x?,y?):
        return x + y
    }
}
add(1,2)    // 3
add(nil, 1) // nil
循环直到函数返回 nil
很像if let,你也可以编写while let和循环,直到nil:
while let line = readLine() {
    print(line)
}
你也可以写while var(类似的注意事项if var).
where 子句也在这里工作(并终止循环,而不是跳过):
while let line = readLine() 
where !line.isEmpty {
    print(line)
}
将可选项传递给采用非可选项并返回结果的函数
代替:
let j: Int
if i != nil {
    j = abs(i!)
}
else {
   // no reasonable action to take at this point
   fatalError("no idea what to do now...")
}
你可以使用optional的map运算符:
let j = i.map { abs($0) }
这是非常相似的可选链接,但对于当你需要的非可选值传递到函数作为参数.与可选链接一样,结果将是可选的.
当你想要一个可选的时候这很好.例如,reduce1就像reduce,但是使用第一个值作为种子,如果数组为空则返回一个可选项.您可以这样写(使用guard前面的关键字):
extension Array {
    func reduce1(combine: (T,T)->T)->T? {
        guard let head = self.first
            else { return nil }
        return dropFirst(self).reduce(head, combine: combine)
    }
}
[1,2,3].reduce1(+) // returns 6
而是你可以map在.first性能,并返回:
extension Array {
    func reduce1(combine: (T,T)->T)->T? {
        return self.first.map {
            dropFirst(self).reduce($0, combine: combine)
        }
    }
}
将可选项传递给一个带有可选项并返回结果的函数,避免烦人的双选项
有时候,你想要类似的东西map,但你想要调用的函数本身会返回一个可选的.例如:
// an array of arrays
let arr = [[1,2,3],[4,5,6]]
// .first returns an optional of the first element of the array
// (optional because the array could be empty, in which case it's nil)
let fst = arr.first  // fst is now [Int]?, an optional array of ints
// now, if we want to find the index of the value 2, we could use map and find
let idx = fst.map { find($0, 2) }
但现在idx是类型Int??,双重可选.相反,您可以使用flatMap,将结果"展平"为单个可选项:
let idx = fst.flatMap { find($0, 2) }
// idx will be of type Int? 
// and not Int?? unlike if `map` was used
| 归档时间: | 
 | 
| 查看次数: | 34008 次 | 
| 最近记录: |