1

Hi I am really new to coding in Swift, and am trying to follow the codes in this book: http://www.apress.com/9781484202098. Learn iOS 8 App Development 2nd Edition by James Bucanek

In particular, I am working through Chapter 3 - building a URL shortening app, but despite having copied the code exactly, I am getting an error on the code in Page 76:

if let toShorten = webView.request.URL.absoluteString {

which states 'NSURLRequest?' does not have a member named 'URL'.

I have tried googling an answer, but unfortunately have not come across anything. Any response I can find seems to suggest that my code ought to be working (e.g. How to get url which I hit on UIWebView?). This seems to have the closest answer SWIFT: Why I can't get the current URL loaded in UIWebView? but the solution does not appear to work for me. If I add a ? after the request, it will then at least build it, but I then have a nil variable returned.

I am using Xcode v6.1.1. Here is the piece of code that is coming up with the error in ViewController.swift:

    let GoDaddyAccountKey = "0123456789abcdef0123456789abcdef" //this is replaced by my actual account key in my own code
    var shortenURLConnection: NSURLConnection?
    var shortURLData: NSMutableData?

    @IBAction func shortenURL( AnyObject ) {

        if let toShorten = webView.request?.URL.absoluteString { // ? now added

        let encodedURL = toShorten.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
        let urlString = "http://api.x.co/Squeeze.svc/text/\(GoDaddyAccountKey)?url=\(encodedURL)"
        shortURLData = NSMutableData()
        if let firstrequest = NSURL(string: urlString) //added if here and removed !
        let request = NSURLRequest(URL:firstrequest)
        shortenURLConnection = NSURLConnection(request:request, delegate:self)
        shortenButton.enabled = false
        }
        }
    }

If you have any suggestions on how I can fix this, I would really appreciate it!

Update:

Following suggestions from Ashley below, I have amended my code so that it is no longer bringing up the error (see comments above). However, it is now no longer running. This appears to be because the urlString is being created as http://api.x.co/Squeeze.svc/text/d558979bb9b84eddb76d8c8dd9740ce3?url=Optional("http://www.apple.com/"). The problem is therefore the Optional() that is included and thus makes it an invalid URL. Does anyone have a suggestion on how to remove this please?

Community
  • 1
  • 1
Gemma Down
  • 100
  • 10
  • Can you please remove non-relevant code - too much code turns people off reading your question! – Ashley Mills Feb 13 '15 at 16:45
  • Sorry, I saw too many posts saying that there wasn't enough code, and I wasn't sure what was causing the issue. I will edit to just display the function that brings up the error. – Gemma Down Feb 13 '15 at 16:48
  • Thanks. The key is to provide the relevant code - and determining what that is will often guide you towards an answer. – Ashley Mills Feb 13 '15 at 16:49
  • Thanks Ashley. I have updated the question, and added the updates from your help below. – Gemma Down Feb 13 '15 at 16:56

1 Answers1

1

request is an optional property on UIWebView:

var request: NSURLRequest? { get }

also stringByAddingPercentEscapesUsingEncoding returns an optional:

func stringByAddingPercentEscapesUsingEncoding(_ encoding: UInt) -> String?

What you need is to make user of optional binding in a few places:

if let toShorten = webView.request?.URL.absoluteString {

    if let encodedURL = toShorten.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) {

        let urlString = "http://api.x.co/Squeeze.svc/text/\(GoDaddyAccountKey)?url=\(encodedURL)"
        shortURLData = NSMutableData()

        if let firstrequest = NSURL(string: urlString) {  // If a method can return a nil, don't force unwrap it
            let request = NSURLRequest(URL:first request)
            shortenURLConnection = NSURLConnection(request:request, delegate:self)
            shortenButton.enabled = false
        }

    }
}

See Apple's docs on optional chaining for details

See Apple's docs for NSURL class

Ashley Mills
  • 50,474
  • 16
  • 129
  • 160
  • I think it should be `webView.request?.URL.absoluteString` ;-) – Antonio Feb 13 '15 at 13:00
  • Thank you for this. Unfortunately though when I try it, I then get an error when I try to run the function from the App and it gives me "fatal error: unexpectedly found nil while unwrapping an Optional value" on the "let firstrequest = NSURL(string: urlString)!" line. – Gemma Down Feb 13 '15 at 13:53
  • What that's telling you is a value you've assumed to be non-nil, isn't! You should really try to avoid using force unwrapping in your own code. If you remove the ! from NSURL(string: urlString)! you'll see the problem. I updated my answer. – Ashley Mills Feb 13 '15 at 13:57
  • Thank you for all your help on this Ashley. Unfortunately, whilst that code no longer gives me an error, it doesn't actually do what it is meant to either. I assume this is because there is nothing now for it to unwrap each time, and therefore it is not running the Connection. I can't see though why it would return a nil value. Sorry for all the questions, I really appreciate you taking the time to get back to me on it! – Gemma Down Feb 13 '15 at 15:47
  • 1
    If you look at the docs for `-[NSURL initWithString]` you'll see that the string must conform to a valid URL format and only contain valid characters. I'd suggest printing out `urlString` so you can see what it contains (maybe add to your original question). – Ashley Mills Feb 13 '15 at 16:44
  • Again, you can see in the docs that `stringByAddingPercentEscapesUsingEncoding` returns an optional - updated my answer – Ashley Mills Feb 13 '15 at 17:00