Make a dictionary value non-optional as extension

喜欢而已 提交于 2019-12-07 21:50:47

问题


The below playground outlines my issue. The extension will remove nil values from my dictionary, but leave the other values as Optional(Value). What I need is a dictionary that has no nil values and make the optional value type non-optional.

Ex: I have a dictionary of [String:Int?]. I want the jsonSantize() of that called on that dictionary to return a [String:Int].

//: Playground - noun: a place where people can play

import UIKit
import Foundation


protocol OptionalType {
    associatedtype Wrapped
    var asOptional : Wrapped? { get }
}

extension Optional : OptionalType {
    var asOptional : Wrapped? {
        return self
    }
}

extension Dictionary where Value : OptionalType{

    //Sanitizes the current dictionary for json serialization
    //Removes nil values entirely. Makes optionals non-optional
    func jsonSanitize() -> Dictionary<Key,Value> {
        var newDict:[Key:Value] = [:]
        for (key, value) in self {
            if value.asOptional != nil {
                newDict.updateValue(self[key]!, forKey: key)
            }
        }
        return newDict
    }

}

var youGood = false

var stringMan:String? = youGood ?
    "WOHOO!" :
    nil

var dict:[String:Any?] = [
    "stuff":"THINGIES",
    "things": stringMan

]
var dict2 = dict.jsonSanitize()
print(dict2)

var test = (stringMan != nil)

UPDATE: Suggestion made to use Value.Wrapped as new dictionary type

//: Playground - noun: a place where people can play

import UIKit
import Foundation


protocol OptionalType {
    associatedtype Wrapped
    var asOptional : Wrapped? { get }
}

extension Optional : OptionalType {
    var asOptional : Wrapped? {
        return self
    }
}

extension Dictionary where Value : OptionalType{

    //Sanitizes the current dictionary for json serialization
    //Removes nil values entirely. Makes optionals non-optional
    func jsonSanitize() -> Dictionary<Key,Value.Wrapped> {
        var newDict:[Key:Value.Wrapped] = [:]
        for (key, value) in self {
            if let v = value.asOptional {
                newDict.updateValue(v, forKey: key)
            }
        }
        return newDict
    }

}

var youGood = false

var stringMan:String? = youGood ?
    "WOHOO!" :
    nil

var dict:[String:Any?] = [
    "stuff":"THINGIES",
    "things": stringMan

]
var dict2:[String:Any] = dict.jsonSanitize()
print(dict2)

var test = (stringMan != nil)

回答1:


Your method produces a dictionary of the same type [Key: Value] with Value being some optional type. What you probably want is to produce a dictionary of type [Key: Value.Wrapped]:

extension Dictionary where Value: OptionalType {

    func jsonSanitize() -> [Key: Value.Wrapped] {
        var newDict: [Key: Value.Wrapped] = [:]
        for (key, value) in self {
            if let v = value.asOptional {
                newDict.updateValue(v, forKey: key)
            }
        }
        return newDict
    }
}

Example:

let dict: [String: Int?] = [
    "foo": 1234,
    "bar": nil
]
var dict2 = dict.jsonSanitize()
print(dict2) // ["foo": 1234]

Note also that of Swift 3.0.1/Xcode 8.1 beta, optionals are bridged to NSNull instances automatically, see

  • SE-0140 – Warn when Optional converts to Any, and bridge Optional As Its Payload Or NSNull


来源:https://stackoverflow.com/questions/40250573/make-a-dictionary-value-non-optional-as-extension

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!