3
@IBAction func mainButtonnBeTapped(sender: AnyObject) {
        let session = NSURLSession.sharedSession()
        let request = NSURLRequest(URL: NSURL(string: "http://hq.sinajs.cn/list=sz000609")!)
        let task = session.dataTaskWithRequest(request, completionHandler: {
            (data, response, error) -> Void in            
            let myString = NSString(data: data, encoding: NSUTF8StringEncoding)
            println("this is my string: \(myString)")
        })
        task.resume()
    }

I am using above url to try to get some data, but the return is nil, but i enter the url in chrome/safari, i can get some data. I really don't why, can anyone help to explain?

nhgrif
  • 61,578
  • 25
  • 134
  • 173

2 Answers2

12

This HTTP server sends a

Content-Type = application/x-javascript; charset=GBK

header field in the response, therefore you get the correct encoding from the textEncodingName property of the NSURLResponse. This can be converted to a NSStringEncoding.

This is just a translation of the solution presented in https://stackoverflow.com/a/19885463/1187415 to Swift, plus some simple error checking:

let session = NSURLSession.sharedSession()
let request = NSURLRequest(URL: NSURL(string: "http://hq.sinajs.cn/list=sz000609")!)
let task = session.dataTaskWithRequest(request, completionHandler: {
    (data, response, error) -> Void in   

    var usedEncoding = NSUTF8StringEncoding // Some fallback value
    if let encodingName = response.textEncodingName {
        let encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding(encodingName))
        if encoding != UInt(kCFStringEncodingInvalidId) {
            usedEncoding = encoding
        }
    }
    if let myString = NSString(data: data, encoding: usedEncoding) {
        println("this is my string: \(myString)")
    } else {
        println("failed to decode data")
    }
})
task.resume()

Output:

this is my string: var hq_str_sz000609="绵世股份, ....

Minor changes are necessary for Swift 2:

let session = NSURLSession.sharedSession()
let request = NSURLRequest(URL: NSURL(string: "http://hq.sinajs.cn/list=sz000609")!)
let task = session.dataTaskWithRequest(request, completionHandler: {
    (data, response, error) -> Void in   

    var usedEncoding = NSUTF8StringEncoding // Some fallback value
    if let encodingName = response?.textEncodingName {
        let encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding(encodingName))
        if encoding != UInt(kCFStringEncodingInvalidId) {
            usedEncoding = encoding
        }
    }
    if let myString = String(data: data!, encoding: usedEncoding) {
        print("this is my string: \(myString)")
    } else {
        print("failed to decode data")
    }
})
task.resume()

Update for Swift 3:

let session = URLSession.shared
let request = URLRequest(url: URL(string: "http://hq.sinajs.cn/list=sz000609")!)
let task = session.dataTask(with: request, completionHandler: {
    (data, response, error) -> Void in

    guard let data = data else { return }

    var usedEncoding = String.Encoding.utf8 // Some fallback value
    if let encodingName = response?.textEncodingName {
        let encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding(encodingName as CFString))
        if encoding != UInt(kCFStringEncodingInvalidId) {
            usedEncoding = String.Encoding(rawValue: encoding)
        }
    }
    if let myString = String(data: data, encoding: usedEncoding) {
        print("this is my string: \(myString)")
    } else {
        print("failed to decode data")
    }
})
task.resume()
Community
  • 1
  • 1
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
3

The text you try to get is probably not UTF-8, try with another encoding, like this for example:

let myString = NSString(data: data, encoding: NSASCIIStringEncoding)

Update: read Martin R's answer for how to find the right encoding.

Community
  • 1
  • 1
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
  • While it might be possible that the result was not UTF-8 encoding... I don't think this would actually result in the string being `nil` (versus simply unintelligible). – nhgrif Aug 17 '15 at 13:14
  • It seems like it is GBK and according to the [list of available encodings](http://svn.gna.org/svn/gnustep/libs/corebase/trunk/Source/CFStringEncoding.c) it is probably kCFStringEncodingGB_18030_2000 – Lachezar Aug 17 '15 at 13:16
  • @nhgrif I just tested in a Playground, it is nil with NSUTF8StringEncoding but works with NSASCIIStringEncoding. :) Although I'm not sure this ASCII encoding is the right one for OP, it doesn't return nil anymore with it. – Eric Aya Aug 17 '15 at 13:16
  • 1
    @nhgrif: `NSString(data:encoding:)` does return `nil` if the data is not valid in the specified encoding, and data in GBK encoding is unlikely to be valid UTF-8. – Martin R Aug 17 '15 at 15:23