![](/img/trans.png)
[英]URL(string:) gives nil error even if the String is not nil in Swift
[英]Encoding generic String object gives nil Swift
我有一个UserDefaults
类,用于处理存储,删除和获取存储对象为默认值的类。 我相信,这是完整的课程,简洁明了:
现在的问题在于存储功能。 我似乎不能编码Encodable
String
对象。 我知道我可以将对象存储为默认值,但这会MVDefaults
处理通用对象的目的。
我在这里想念什么吗?
import Foundation
enum MVDefaultsKey: String {
case requestToken = "defaultsRequestToken"
}
/// The class that has multiple class functions for handling defaults.
/// Also has the helper class functions for handling auth tokens.
class MVDefaults {
// MARK: - Functions
/// Stores token.
class func store<T: Encodable>(_ object: T, key: MVDefaultsKey) {
let encoder = JSONEncoder()
let encoded = try? encoder.encode(object)
UserDefaults.standard.set(encoded, forKey: key.rawValue)
}
/// Removes the stored token
class func removeDefaultsWithKey(_ key: MVDefaultsKey) {
UserDefaults.standard.removeObject(forKey: key.rawValue)
}
/// Returns stored token (optional) if any.
class func getObjectWithKey<T: Decodable>(_ key: MVDefaultsKey, type: T.Type) -> T? {
guard let savedData = UserDefaults.standard.data(forKey: key.rawValue) else {
return nil
}
let object = try? JSONDecoder().decode(type, from: savedData)
return object
}
}
考虑一下将字符串"hello"
编码为JSON的样子。 它看起来像:
"hello"
不是吗
那不是有效的JSON(根据here )! 您不能直接将字符串编码为JSON,也不能直接解码字符串。
例如,此代码
let string = try! JSONDecoder().decode(String.self, from: "\"hello\"".data(using: .utf8)!)
会产生错误
JSON文本不是以数组或对象开头,并且没有允许片段设置的选项。
和
let data = try! JSONEncoder().encode("Hello")
会产生错误:
顶级字符串编码为字符串JSON片段。
此处的解决方法只是使用UserDefaults
提供的专用set
方法存储字符串。 不过,您仍然可以使用通用方法,只需检查类型并进行强制转换:
if let str = object as? String {
UserDefaults.standard.set(str, forKey: key)
} else if let int = object as? Int {
...
尽管Sweeper的评论很有帮助,应该是答案(因为没有他,我将无法提出自己的答案),但我仍然会继续分享我对Defaults类所做的事情,以使其能够处理非JSON编码对象(例如String,Int,Array和whatnot)。
这里是:
MVDefaults.swift
import Foundation
enum MVDefaultsKey: String {
case requestToken = "defaultsRequestToken"
case someOtherKey = "defaultsKeyForTests"
}
/// The class that has multiple class functions for handling defaults.
/// Also has the helper class functions for handling auth tokens.
class MVDefaults {
// MARK: - Functions
/// Stores object.
class func store<T: Encodable>(_ object: T, key: MVDefaultsKey) {
let encoder = JSONEncoder()
let encoded = try? encoder.encode(object)
if encoded == nil {
UserDefaults.standard.set(object, forKey: key.rawValue)
return
}
UserDefaults.standard.set(encoded, forKey: key.rawValue)
}
/// Removes the stored object
class func removeDefaultsWithKey(_ key: MVDefaultsKey) {
UserDefaults.standard.removeObject(forKey: key.rawValue)
}
/// Returns stored object (optional) if any.
class func getObjectWithKey<T: Decodable>(_ key: MVDefaultsKey, type: T.Type) -> T? {
if let savedData = UserDefaults.standard.data(forKey: key.rawValue) {
let object = try? JSONDecoder().decode(type, from: savedData)
return object
}
return UserDefaults.standard.object(forKey: key.rawValue) as? T
}
}
这是我为测试Defaults方法编写的测试(规范)。 全部通过! ✅
MVDefaultsSpec.swift
@testable import Movieee
import Foundation
import Quick
import Nimble
class MVDefaultsSpec: QuickSpec {
override func spec() {
describe("Tests for MVDefaults") {
context("Tests the whole MVDefaults.") {
it("tests the store and retrieve function for any Codable object") {
let data = stubbedResponse("MovieResult")
expect(data).notTo(beNil())
let newMovieResult = try? JSONDecoder().decode(MovieResult.self, from: data!)
MVDefaults.store(newMovieResult, key: .someOtherKey)
let retrievedObject = MVDefaults.getObjectWithKey(.someOtherKey, type: MovieResult.self)
// Assert
expect(retrievedObject).notTo(beNil())
// Assert
expect(retrievedObject?.movies?.first?.id).to(equal(newMovieResult?.movies?.first?.id))
}
it("tests the store and retrieve function for String") {
let string = "Ich bin ein Berliner"
MVDefaults.store(string, key: .someOtherKey)
let retrievedObject = MVDefaults.getObjectWithKey(.someOtherKey, type: String.self)
// Assert
expect(retrievedObject).notTo(beNil())
// Assert
expect(retrievedObject).to(equal(string))
}
it("tests the removal function") {
MVDefaults.removeDefaultsWithKey(.someOtherKey)
let anyRetrievedObject = UserDefaults.standard.object(forKey: MVDefaultsKey.someOtherKey.rawValue)
let stringRetrievedObject = MVDefaults.getObjectWithKey(.someOtherKey, type: String.self)
// Assert
expect(anyRetrievedObject).to(beNil())
// Assert
expect(stringRetrievedObject).to(beNil())
}
it("tests the store and retrieve function for Bool") {
let someBool: Bool = true
MVDefaults.store(someBool, key: .someOtherKey)
let retrievedObject = MVDefaults.getObjectWithKey(.someOtherKey, type: Bool.self)
// Assert
expect(retrievedObject).to(equal(someBool))
// Assert
expect(retrievedObject).notTo(beNil())
}
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.