Optional unwrapping for class properties Swift - swift

Let's say I have the following class definition:
class Request {
let url: NSURL?
init?(url: String) {
guard let self.url = NSURL(string: url) else {
self.url = nil
return nil
}
}
}
The guard statement doesn't work so I'm having to do the following:
let url: NSURL?
init?(url: String) {
guard let _ = NSURL(string: url) else {
self.url = nil
return nil
}
self.url = NSURL(string: url)!
}
Which feels quite long - is there another, simpler way to achieve what I'm trying to achieve which is to create a failable initialiser whose only property takes a value from NSURL (which returns an optional). The initialiser is to fail and return nil if the NSURL value returns nil.

Your first version could work, you just forgot to give guard a variable name for the unwrapped value (you used self.url instead, that's the mistake):
class Request {
let url: NSURL?
init?(url: String) {
guard let value = NSURL(string: url) else {
self.url = nil
return nil
}
self.url = value
}
}

Related

Return empty URL on failure

In a function like this:
func getMessageDetails()->URL{
if let theLinks = theMessage.links as? [[String:String]]{
let thisLink = theLinks[3]["Href"]
let url = URL(string: thisLink)
return url!
}
return nil// is unacceptable, what should I put here?
}
what should I return outside the closure?
In this case the best solution is to return an optional URL, it can also handle the case if the link is not a valid URL. And you should check if the thisLink array contains more than 3 items to avoid an out-of-range exception:
func getMessageDetails() -> URL? {
if let theLinks = theMessage.links as? [[String:String]],
theLinks.count > 3,
let thisLink = theLinks[3]["Href"] {
return URL(string: thisLink)
}
return nil
}

URL is always nil in Swift 3

I have a struct that I am using to call out to the iTunes API. But when ever I run it myURL variable is never getting set, it's always nil. Not sure what I am doing wrong:
let myDefaultSession = URLSession(configuration: .default)
var myURL: URL?
var myDataTask: URLSessionTask?
struct APIManager {
func getJSON(strURL: String) {
myURL = URL(string: strURL)
var dictReturn: Dictionary<String, Any> = [:]
//cancel data task if it is running
myDataTask?.cancel()
print(myURL!) //<----Always nil
}
}
Here's the string:
"https://itunes.apple.com/search?media=music&entity=song&term=The Chain"
You´re getting nil because the URL contains a space. You need to encode the string first and then convert it to an URL.
func getJSON(strURL: String) {
if let encoded = strURL.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed),
let myURL = URL(string: encoded) {
print(myURL)
}
var dictReturn:Dictionary<String, Any> = [:]
//cancel data task if it is running
myDataTask?.cancel()
}
URL will be:
https://itunes.apple.com/search?media=music&entity=song&term=The%20Chain

String still optional in Swift

I am trying to assign a string to a label like so:
self.MsgBlock4.text = "\(wsQAshowTagArray![0]["MsgBlock4"]!)"
But it display the label like so Optional(James) how do I remove the Optional() ?
The Dictionary inside the array comes from here:
self.wsQAshowTag(Int(barcode)!, completion: { wsQAshowTagArray in
})
Here is the method:
func wsQAshowTag(tag: Int, completion: ([AnyObject]? -> Void)) {
let requestString = NSString(format: "URL?wsQATag=%d", tag) as String
let url: NSURL! = NSURL(string: requestString)
let task = NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: {
data, response, error in
do {
let result = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments) as? [AnyObject]
completion(result)
}
catch {
completion(nil)
}
})
task.resume()
}
Since these are optionals and the type can be AnyObject, optional chaining / downcasting and providing a default value using the nil coalescing operator seem the safest approach. If you're expecting the item to be a String:
self.MsgBlock4.text = (wsQAshowTagArray?[0]["MsgBlock4"] as? String) ?? ""
Or I guess for any type that conforms to CustomStringConvertible you can use its description
self.MsgBlock4.text = (wsQAshowTagArray?[0]["MsgBlock4"] as? CustomStringConvertible)?.description ?? ""

Cannot convert value of type 'String' to 'NSURL'

I'm working in swift and originally got the warning "'stringByAddingPercentEscapesUsingEncoding' was deprecated..." so I changed my code from
let url = NSURL(string: (urlString as NSString).stringByAddingPercentEscapesUsingEncoding(NSASCIIStringEncoding)!)
to
var url = urlString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())
But now I'm getting the error "Cannot convert value of type 'String' to expected argument type 'NSURL'.
let urlRequest = NSURLRequest(URL: url!)
My current code:
private func handleTextFieldInterfaces(){
autocompleteTextField.onTextChange = {[weak self] text in
if !text.isEmpty{
if self!.connection != nil{
self!.connection!.cancel()
self!.connection = nil
}
let urlString = "\(self!.baseURLString)?key=\(self!.googleMapsApiKey)&input=\(text)"
//let url = NSURL(string: (urlString as NSString).stringByAddingPercentEscapesUsingEncoding(NSASCIIStringEncoding)!)
var url = urlString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())
if url != nil{
let urlRequest = NSURLRequest(URL: url!) //Error on this line
self!.connection = NSURLConnection(request: urlRequest, delegate: self)
}
}
}
}
Try casting it to NSURL see if it works
var url = NSURL(urlString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet()))

NSUrl exc_bad_instruction?

I am trying to follow this tutorial and after some minor trial and error runs I have ran into a problem that I don't quite understand. I am receiving this error(?) exc_bad_instruction. I have read that it happens usually when you try to unwrap a nil or the nil isn't valid?
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {
var cell:iGameTableViewCell? = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? iGameTableViewCell
if(cell == nil) {
cell = NSBundle.mainBundle().loadNibNamed("iGameTableViewCell", owner: self, options: nil)[0] as? iGameTableViewCell
}
if let pfObject = object {
cell?.gameNameLabel?.text = pfObject["name"] as? String
var votes:Int? = pfObject["votes"] as? Int
if votes == nil {
votes = 0
}
cell?.gameVotesLabel?.text = "\(votes!) votes"
var credit:String? = pfObject["author"] as? String
if credit != nil {
cell?.gameCreditLabel?.text = "\(credit!)"
}
cell?.gameImageView?.image = nil
if var urlString:String? = pfObject["url"] as? String {
var url:NSURL? = NSURL(string: urlString!)
if var url:NSURL? = NSURL(string: urlString!) {
var error:NSError?
var request:NSURLRequest = NSURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.ReturnCacheDataElseLoad, timeoutInterval: 5.0)
NSOperationQueue.mainQueue().cancelAllOperations()
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {
(response:NSURLResponse!, imageData:NSData!, error:NSError!) -> Void in
cell?.gameImageView?.image = UIImage(data: imageData)
})
}
}
}
return cell
}
See these two lines:
var url:NSURL? = NSURL(string: urlString!)
if var url:NSURL? = NSURL(string: urlString!) {
First, you can't want them both; they both do the same thing in
different ways.
Second, the way the first line operates is dangerous. Delete it.
Third, delete the exclamation mark from urlString! and the type
declaration NSURL?.
Now you will just have this:
if var url = NSURL(string: urlString) {
And that is safe and is how such unwrapping should look.
EDIT: Just to clarify: This is a terribly self-defeating thing to do:
if var urlString:String? = pfObject["url"] as? String
Here's why. The if var ... = or if let ... = construct unwraps the Optional on the right side of the equal sign. That is its purpose: to unwrap the Optional, safely. But by adding the :String? declaration, you wrap it right back up again in an Optional, thus defeating the entire purpose of this construct! You want to say this:
if var urlString = pfObject["url"] as? String
Now urlString, if it is anything at all, is an unwrapped String, which is what you're after.