Swift将泛型转换为可选参数,其值为nil会导致fatalError [英] Swift Casting Generic to Optional with a nil value causes fatalError

查看:339
本文介绍了Swift将泛型转换为可选参数,其值为nil会导致fatalError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Swift 2,在我设计的例子中,我将 String 转换为 Int 或者更具体地说是一个 Int 或一个 Int?使用泛型。在 Int <应该为零的情况下,强制转换将会失败并发生fatalError:致命错误:意外地发现nil,同时展开可选值 code>



这些看起来像是相似/重复的问题:



我的问题是:人们应该如何转换为可选项,即nil?



示例:

  class Thing< T> {
var item:T

init(_ item:T){
self.item = item



struct Actions {

static func convertIntForThing< T>(string:String,thing:Thing< T>) - > T {
return convertStringToInt(string,to:T.self)
}

static func convertStringToInt< T>(string:String,to:T.Type) - > T {
debugPrint(Converting to ---> \(to))

if T.self == Int.self {
return Int(string) !如! T
}

//如果是Int?将是零,铸造
//在这里导致它炸毁:
//
//致命错误:意外地发现零,同时展开
//可选值甚至尽管在这种情况下T是可选的< Int>
返回Int(string)as! T




func testExample(){
//此工程:
let thing1 =物件< Int>(0)
thing1.item = Actions.convertIntForThing(1,thing:thing1)

//此失败:
//空字符串,其中value = Int ()
//将返回一个可选的< Int> (0)
thing2.item = Actions.convertIntForThing(,thing:thing2)
}

testExample()


解决方案



我忘记了可选 NilLiteralConvertible 。所以我们可以在转换函数上提供2个变体,它不会失败。基本上,在 T 其中 T:NilLiteralConvertible



< pre $ class Thing< T> {
var item:T

init(_ item:T){
self.item = item



struct动作{

//提供2个变体之一,其中T:NilLiteralConvertible
//变体1 for non-optionals
static func convertIntForThing< T>(string:String,thing:Thing< T>) - > T {
return convertStringToInt(string,to:T.self)
}

//变化2 for optionals
static func convertIntForThing< T where T:NilLiteralConvertible> (string:String,thing:Thing< T>) - > T {
return convertStringToInt(string,to:T.self)
}

static func convertStringToInt< T>(string:String,to:T.Type) - > T {
debugPrint(Converting to ---> \(to))
return Int(string)!如! T
}

static func convertStringToInt< T where T:NilLiteralConvertible>(string:String,to:T.Type) - > T {
debugPrint(Converting to ---> \(to))

let value = Int(string)

if _ =价值{
返回值为! T
}

让其他:T =零
返回其他
}
}

func testExample(){
//此作品:
let thing1 = Thing< Int>(0)
thing1.item = Actions.convertIntForThing(1,thing:thing1)

let thing2 = Thing< Int?>(0)
thing2.item = Actions.convertIntForThing(,thing:thing2)
}

testExample()


Using Swift 2, in my contrived example I am converting a String to an Int or more specifically an Int or an Int? using a generic. In the case where the Int? should be nil the cast will fail with a fatalError: fatal error: unexpectedly found nil while unwrapping an Optional value

These look like they may be similar/duplicate questions:

My question is: how is one supposed to cast to an optional that is nil?

Example:

class Thing<T>{
    var item: T

    init(_ item: T){
        self.item = item
    }
}

struct Actions{

    static func convertIntForThing<T>(string: String, thing:Thing<T>) -> T{
        return convertStringToInt(string, to: T.self)
    }

    static func convertStringToInt<T>(string: String, to: T.Type) -> T{
        debugPrint("Converting to ---> \(to)")

        if T.self == Int.self{
            return Int(string)! as! T
        }

        // in the case of "" Int? will be nil, the cast
        // here causes it to blow up with:
        //
        // fatal error: unexpectedly found nil while unwrapping an
        // Optional value even though T in this case is an Optional<Int>
        return Int(string) as! T

    }
}


func testExample() {
    // this WORKS:
    let thing1 = Thing<Int>(0)
    thing1.item = Actions.convertIntForThing("1", thing: thing1)

    // This FAILS:
    // empty string  where value = Int("")
    // will return an Optional<Int> that will be nil
    let thing2 = Thing<Int?>(0)
    thing2.item = Actions.convertIntForThing("", thing: thing2)
}

testExample()

解决方案

I got something that does work.

I forgot that Optional is a NilLiteralConvertible. So we can provide 2 variations on the conversion function and it will not fail. Basically, provides a constraint on T where T: NilLiteralConvertible

class Thing<T>{
    var item: T

    init(_ item: T){
        self.item = item
    }
}

struct Actions{

    // Provide 2 variations one with T the other where T: NilLiteralConvertible
    // variation 1 for non-optionals
    static func convertIntForThing<T>(string: String, thing:Thing<T>) -> T{
        return convertStringToInt(string, to: T.self)
    }

    // variation 2 for optionals
    static func convertIntForThing<T where T: NilLiteralConvertible>(string: String, thing:Thing<T>) -> T{
        return convertStringToInt(string, to: T.self)
    }

    static func convertStringToInt<T>(string: String, to: T.Type) -> T{
        debugPrint("Converting to ---> \(to)")
        return Int(string)! as! T
    }

    static func convertStringToInt<T where T: NilLiteralConvertible>(string: String, to: T.Type) -> T{
        debugPrint("Converting to ---> \(to)")

        let value = Int(string)

        if let _ = value{
            return value as! T
        }

        let other: T = nil
        return other
    }
}

func testExample() {
    // this WORKS:
    let thing1 = Thing<Int>(0)
    thing1.item = Actions.convertIntForThing("1", thing: thing1)

    let thing2 = Thing<Int?>(0)
    thing2.item = Actions.convertIntForThing("", thing: thing2)
}

testExample()

这篇关于Swift将泛型转换为可选参数,其值为nil会导致fatalError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆