问题
So recently I switch from Xcode 9 to Xcode 10 for my iOS app development. the first thing I noticed that when I tried to print out a variable, the value is wrapped with optional, while in Xcode 9 it never happened. for example here is the code that I test.
let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
let build = Bundle.main.object(forInfoDictionaryKey: kCFBundleVersionKey as String) as! String
let parameters = ["branch_id": loginData.profile.branchId,
"version": "\(version).\(build)",
"os_name" : "ios",
"user_id" : loginData.uid]
print(parameters)
and the output was like :
["os_name": "ios", "branch_id": Optional("2"), "version": "1.5.8.3", "user_id": Optional("1141")]
I've tried to force unwrap the code with exclamation mark
"branch_id": loginData.profile.branchId!
,
or even better with coalescing operator
"branch_id": loginData.profile.branchId ?? "0"
It works, but I have like, 30+ lines of code with the same problem, do I need to do it one by one? Or is there a way to change this behaviour?
FYI I'm using Swift 4 for my project. Edit : FYI this was tested on iOS 12, while before in Xcode 9 was tested in iOS 11
Edit:
To answer matt comment asking info about where loginData.profile.branchId
come from, here it is.
So, the data is fetched from data model, and I use this code to fetch it:
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "User")
let fetchResults = try context.fetch(request) as? [NSManagedObject]
let loginData = fetchResults![0]
let profile = loginData.value(forKey: "profile") as! NSManagedObject
self.profile = Profile()
self.profile.branchId = profile.value(forKey: "branchId") as? String
回答1:
Use Optional Unwrapping with if-let statement
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "User")
if let fetchResults = try context.fetch(request) as? [NSManagedObject]{
let loginData = fetchResults[0]
let profile = loginData.value(forKey: "profile") as! NSManagedObject
self.profile = Profile()
if let branchId = profile.value(forKey: "branchId") as? String{
self.profile.branchId = branchId
}
}
if let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String, let build = Bundle.main.object(forInfoDictionaryKey: kCFBundleVersionKey as String) as? String{
let branchId = loginData.profile.branchId ?? ""
let branchId = loginData.uid ?? ""
let parameters = ["branch_id": branchId,
"version": "\(version).\(build)",
"os_name" : "ios",
"user_id" : login_tty.uid]
print(parameters)
}
Never use force unwrapping, i mean ! directly, it may result in crash, instead safely unwrap using
if let
andguard let
回答2:
if you are printing an optional value Xcode prints the value warapped with the word optional("value").
if you want to avoid this you must upwarapped the value. you have 3 ways to do that:
the careful way, use guard let or if let:
if let branchId = profile.value(forKey: "branchId") as? String { //here branchId != nil } guard let branchId = profile.value(forKey: "branchId") as? String else { return }
the force unwarapped way:
let branchId = profile.value(forKey: "branchId") as! String
on that way, if the value is nil the app will crash so be careful
use default value:
let branchId = profile.value(forKey: "branchId") as? String ?? "default value"
回答3:
I ended up using coalescing operator which is ?? ""
and implemented it my code like:
var parameters = [String: Any]()
if loginData.profile != nil {
if loginData.profile.branchId != "" {
let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
let build = Bundle.main.object(forInfoDictionaryKey: kCFBundleVersionKey as String) as! String
parameters = ["branch_id": loginData.profile.branchId ?? "",
"version" : "\(version).\(build)",
"os_name" : "ios",
"user_id" : loginData.uid ?? ""
]
}
}
来源:https://stackoverflow.com/questions/53606860/updating-to-xcode-10-made-value-wrapped-with-optional