Saving URL data to a variable

2019-06-09 04:01发布

问题:

So I am trying to get a simple string of data back from a RESTful API. Here is what a response looks like:

Hello

It is not formatted in XML or JSON or anything just a simple string because only one word is being passed back at a time. So here is what my swift looks like:

let task = session.dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in

    if error != nil {
        println("error: \(error.localizedDescription): \(error.userInfo)")
    }

    var withNewLine:NSString = NSString(data: data, encoding: NSUTF8StringEncoding)!
    let str:NSString = withNewLine.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())

    dispatch_async(dispatch_get_main_queue(), {
        self.spellCorrection = str
    })
})

task.resume()

I get the correct data back in the "str" variable before I go into the dispatch_async() method. But when I do go into the dispatch_async() method the "str" variable becomes nil and I am not sure why. I am just trying to save the single word in a variable within my class, so if I am going about this completely wrong let me know. I would really appreciate any help I can get. Thanks!

Edit

Okay so I should have included this the first time I posted. I have also tried this:

let task = session.dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in

    if error != nil {
        println("error: \(error.localizedDescription): \(error.userInfo)")
    }

    var withNewLine:NSString = NSString(data: data, encoding: NSUTF8StringEncoding)!
    self.spellCorrection = withNewLine.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
})

task.resume()

But when I do this the string does not stay in the self.spellCorrection variable after the completionHandler has finished. So my question is, what should I do to keep the string in the self.spellCorrection variable after the completionHandler has finished? Thanks!

More details

In viewDidLoad:

var spellCorrection: NSString = ""
//First print
println(self.spellCorrection)

In the method I call later I have:

func spellCheck() {
    var check: String = "http://theURL.com/?text=" + condenseWhitespace(self.lastTypedWord)
    let url = NSURL(string: check)
    let task = session.dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in

        if error != nil {
            println("error: \(error.localizedDescription): \(error.userInfo)")
        }

        var withNewLine:NSString = NSString(data: data, encoding: NSUTF8StringEncoding)!
        self.spellCorrection = withNewLine.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
    }).resume()
    //Print after the completionHandler
    println(self.spellCorrection)
}

回答1:

As is clear in the code you've added under the "More Details" section of your answer, i.e.

let task: Void = session.dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in

   // ...

   self.spellCorrection =    withNewLine.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNew lineCharacterSet())
   println(spellCorrection)
}).resume()

println(self.spellCorrection)

by printing self.spellCorrection directly outside of the block, you're attempting to print it before it's been set in the async dataTaskWithURL block.

An async block performs in the background, so as the code written immediately after your block executes on the main thread, the code within the async block will not yet be complete. That's why self.spellCorrection prints correctly inside the async block -- because at that point, the code has definitely executed; but you cannot print the updated value directly outside of the async block as you've done, because the async code hasn't finished executing yet.

So, yes, your self.spellCorrection has in fact been set correctly, but you have to wait until after the async code executes before checking for the new value. And the surefire way to check for that updated value is in fact by printing it within the async block.



回答2:

I don't think that you need to call dispatch_async in the first place. You're not doing any work that requires to be done on the main thread.