Why the assigned value is nil? - ios

I use oAuth for the users login.
func getUserInfoResponse(_ response: APIResponse!) {
print("----------------------------------------")
print("用户资料获取成功:")
print(response.jsonResponse)
//print(response.jsonResponse["figureurl_qq_2"])
let accessToken = _tencentOAuth.accessToken
let nickname = response.jsonResponse["nickname"] as! String!
let avatar = response.jsonResponse["figureurl_qq_1"] as! String!
let avatar2 = response.jsonResponse["figureurl_qq_2"] as! String!
let urlString:String = "http://www.xxxxxx.com/cloud/app?openid=\(accessToken!)&nickname=\(nickname!)&avatar=\(avatar!)&avatar2=\(avatar2!)"
self.wk = WKWebView(frame: self.view.frame)
let url = URL(string: urlString)!
self.wk.load(URLRequest(url: url))
self.view.addSubview(self.wk)
}
and print(urlString) is
http://www.example.com/cloud/app?openid=xxxxxxx32D1E05D95E91881A15A8CDC75&nickname=
.&avatar=http://q.qlogo.cn/qqapp/101237639/90012AB5E745A1B10A6F5F4A14F0B48D/40&avatar2=http://q.qlogo.cn/qqapp/101237639/90012AB5E745A1B10A6F5F4A14F0B48D/100
when user login, , all the values have value except the url and get this error:
fatal error: unexpectedly found nil while unwrapping an Optional value
Why the url is nil, it has been assigned with value. Sorry I'm new to ios and swift3.

You should encode the url before use it
if let urlEncoded = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed){
let url = URL(string: urlEncoded)
}

Related

Issue assigning variable value to open Apple Maps when pressing a UILabel

Essentially I am parsing JSON data and assigning it to a variable called addressPressNow I then have the following function that executes when a user taps on a UILabel:
The goal is to have Apple Maps open provided the variable value it contains.
Because I am assigning an address to a variable it will contain spaces
ex: 3981 Test Drive Cupertino CA 95014
NOTE: The value of the variable is being passed correctly because when I do print(addressPressNow) in func tapFunction it prints correctly.
#objc
func tapFunction(sender:UITapGestureRecognizer) {
let targetURL = NSURL(string: "http://maps.apple.com/?q=" + addressPressNow)!
UIApplication.shared.openURL(targetURL as URL)
}
The issue is I am having trouble applying the variable to the string URL with the following error:
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an
Optional value
The following is how I am assigning the value to the variable:
struct FacilityInfo: Decodable {
let address: String
class infoViewController: UIViewController {
var addressPressNow : String = ""
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(infoViewController.tapFunction))
addressInfo.isUserInteractionEnabled = true
addressInfo.addGestureRecognizer(tap)
let url = URL(string: "https://test/test/example”)!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
// ensure there is no error for this HTTP response
guard error == nil else {
print ("error: \(error!)")
return
}
// ensure there is data returned from this HTTP response
guard let data = data else {
print("No data")
return
}
// Parse JSON into array of Car struct using JSONDecoder
guard let cars = try? JSONDecoder().decode([FacilityInfo].self, from: data), let secondCar = cars.first
else {
print("Error: Couldn't decode data into cars array")
return
}
DispatchQueue.main.async {
self.addressPressNow = secondCar.facility_address
}
}
"I am assigning an address to a variable it will contain spaces"
If the address contains spaces then creating NSURL with the string will crash. You can use addingPercentEncoding to solve the problem
if let encodedAddress = addressPressNow.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) {
let targetURL = NSURL(string: "http://maps.apple.com/?q=" + encodedAddress)!
UIApplication.shared.openURL(targetURL as URL)
}
And don't use NSURL and force unwrapping. Update it like this
if let encodedAddress = addressPressNow.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
let targetURL = URL(string: "http://maps.apple.com/?q=" + encodedAddress) {
UIApplication.shared.openURL(targetURL)
}
As suggested by matt use URLComponents
let addressPressNow = "3981 Test Drive Cupertino CA 95014"
var components = URLComponents(string: "http://maps.apple.com")
components?.queryItems = [URLQueryItem(name: "q", value: addressPressNow)]
print(components?.url)//http://maps.apple.com?q=3981%20Test%20Drive%20Cupertino%20CA%2095014
if let targetURL = components?.url {
UIApplication.shared.open(targetURL, options: [:], completionHandler: nil)
}
You are saying
NSURL(string: "http://maps.apple.com/?q=" + addressPressNow)!
Notice the exclamation mark at the end. That means "if there's a problem, crash me". You can hardly complain if you do in fact crash; that is what you asked to do.
Basically, never use NSURL(string:) if you can avoid it. To form a valid URL, build it up using URLComponents. And form it out of valid components. (It is impossible to say whether facility_address is a valid URL query, because you have not shown what it is.)
Example:
var comp = URLComponents()
comp.scheme = "https"
comp.host = "maps.apple.com"
comp.queryItems = [URLQueryItem(name: "q", value: "1 Infinite Loop, Cupertino, CA")]
if let url = comp.url {
print(url) // https://maps.apple.com?q=1%20Infinite%20Loop,%20Cupertino,%20CA
}
That gives us a valid URL that actually works.

How to convert userdefault value to URL?

I'm trying to retrieve the URL from a UserDefault I saved previously, but parsing it to URL fails as states: "Cannot convert NSINLINEDATA to NSURL"
I've tried parsing it to String and then to URL but it only gives nil
Set value
let videourl = info["UIImagePickerControllerReferenceURL"] as? URL
if let videoURL = videourl{
defaults.set(videourl,forKey: "LullabyURL")
}
Get value
let videoURL = defaults.value(forKey: "LullabyURL")
let newStr = String(data: videoURL as! Data, encoding: .utf8)
let vu = URL.init(string:newStr ?? "nil")
let player = AVPlayer(url: vu!)
You can use built in method func url(forKey defaultName: String) -> URL? to retrieve URL as below,
if let defaultsUrl = UserDefaults.standard.url(forKey: "urlString") {
let player = AVPlayer(url: defaultsUrl)
}

Kingfisher nil while unwrapping optional value

I have Medicine struct that holds image_origin URL of image I want to download and set to the ImageView.
For downloading/caching purposes I'm using Kingfisher framework.
let m = medicines[indexPath.row]
cell.medicineImage.kf.setImage(with: URL(string: m.value(forKeyPath: "image_origin") as! String)!)
cell.medicineName.text = m.value(forKeyPath: "i_name") as? String
In the code above m is an NSManagedObject of CoreData. I try to get image URI from the CoreData and set it to the ImageView, but every time at the line 2 I get the following error message: Unexpectedly found nil while unwrapping an Optional value
I have tried changing variables and Optinal types, tried to hardcode URI but without success.
What am I doing wrong?
P.S. Im using Swift4
Just unwrap safely to fix the crash and check your database if you are not getting the urlString properly,
if let urlString = m.value(forKeyPath: "image_origin") as? String {
print(urlString)
guard let url = URL(string: urlString) else { return }
cell.medicineImage.kf.setImage(with: url)
}
There might be a problem with image_origin key that I may have value as string or may not have. So, just need to confirm the value and use it
let m = medicines[indexPath.row]
cell.medicineName.text = m.value(forKeyPath: "i_name") as? String
guard let urlPath = m.value(forKeyPath: "image_origin") as? String, let url = URL(string: urlPath) else { return }
cell.medicineImage.kf.setImage(with: url)

Swift 2.0 fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)

let imgURL:NSURL = NSURL(string: "\(ImageName)")!
at the above line,i'm getting fatal error
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)
Code :
let ImageName = obj["image"] as! String
let imgURL:NSURL = NSURL(string: "\(ImageName)")!
let request: NSURLRequest = NSURLRequest(URL: imgURL)
let session = NSURLSession.sharedSession()
let Imgtask = session.dataTaskWithRequest(request){
(data, response, error) -> Void in
if (error == nil && data != nil)
{
func display_image()
{
pointAnnoation.DisplayImage = UIImage(data: data!)
}
dispatch_async(dispatch_get_main_queue(), display_image)
}
}
Imgtask.resume()
From the above code im trying to store my image from database in annotation
if i printed the 'ImageName' it returns the name from the database correctly, but unable to retain the image
it resulting in the error while running.
You say that
if i printed the 'ImageName' it returns the name from the database correctly
Then that must mean that the ImageName is not valid for a URL
If you look at the description of NSURL(string:) it says:
The URL string with which to initialize the NSURL object. This URL string must conform to URL format as described in RFC 2396, and must not be nil. This method parses URLString according to RFCs 1738 and 1808.
So the question is...how does ImageName look? And can you create a URL from it?
Apart from that, it is always a good idea to use ? instead of ! as #PhillipMills says
Update: I can see that you have posted an example of your URL now. If I do this in a playground:
let url = NSURL(string: " goo.gl/pBmA0d")
I get nil in return, so it would seem that short URLs and NSURLaren't the best of friends.
Update 2: hmm, guess I spoke to quickly, if you look at the above you can see that I have a space before the goo.gl part, if I change that to:
let url = NSURL(string: "goo.gl/pBmA0d")
it actually works, I get a NSURL object.
But another thing I stumbled upon in your code. You declare ImageName as a String here:
let ImageName = obj["image"] as! String
So you don't have to wrap it in \() later on
let imgURL:NSURL = NSURL(string: "\(ImageName)")!
You could simply say:
let imageURL = NSURL(string: ImageName)
And then...as others has said, it is always a good idea to use ? instead of !
So you could write:
if let imageName = obj["image"] as? String,
let imageURL = NSURL(string: imageName) {
//we're in business :-)
}
and be safe and sound
Try to use guard or if let for helping yourself.
let ImageName = obj["image"] as! String
if let imgURL = NSURL(string: ImageName) {
let request: NSURLRequest = NSURLRequest(URL: imgURL)
let session = NSURLSession.sharedSession()
let Imgtask = session.dataTaskWithRequest(request){ (data, response, error) -> Void in
if (error == nil && data != nil)
{
// What's that func??
func display_image()
{
pointAnnoation.DisplayImage = UIImage(data: data!)
}
dispatch_async(dispatch_get_main_queue(), display_image)
}
}
}
Imgtask.resume()
Don't make force unwrap...use if let to avoid crash ...
if let img = obj["image"] as? String,
imgURL = NSURL(string: img) {
// ... continue with your code ...
}
Please try the following code:
//ImageName is a String type.
guard let ImageName = obj["image"] as? String , let imgURL = NSURL(string: ImageName) else{
return
}
let request: NSURLRequest = NSURLRequest(URL:imgURL)
let session = NSURLSession.sharedSession()
let Imgtask = session.dataTaskWithRequest(request){
(data, response, error) -> Void in
if (error == nil && data != nil)
{
func display_image()
{
pointAnnoation.DisplayImage = UIImage(data: data!)
}
dispatch_async(dispatch_get_main_queue(), display_image)
}
Imgtask.resume()

NSURL for telephone always nil

This is my NSURL
let url = NSURL(string: "tel://\(phoneCall)")
It is always nil, although the phoneCall is a valid mobile number string, and I am testing on a real iPhone.
I tried
let url = NSURL(string: "tel:\(phoneCall)")
but it's still nil.
let phoneCall = "tel://9000002143";
let url:NSURL = NSURL(string:phoneCall);
//OR
var url:NSURL = NSURL(string: "tel://9000002143")
if phoneCall == nil || phoneCall.isEmpty
{
print("phoneCall is empty or nil.")
}
else
{
UIApplication.sharedApplication().openURL(url);
}
Where this phoneCall is set?
I had a similar issue with a optional type. This code illustrate the problem:
let user = row.value
let phone = user?.phone
let url = NSURL(string: "tel://\(phone)")
UIApplication.sharedApplication().openURL(url!)
In this case, the value of urlString variable is "tel://Optional(\"11XXXXXXXXX\")", because the user variable can be nil.
You have to ensure that the user is not nil first, something like:
guard let user = row.value else {
return
}
let phone = user.phone
let urlString = "tel://\(phone)"
let url = NSURL(string: urlString)
UIApplication.sharedApplication().openURL(url!)

Resources