如何在 Swift 3 中将 NSData 转换为数据?
Posted
技术标签:
【中文标题】如何在 Swift 3 中将 NSData 转换为数据?【英文标题】:How to convert NSData to Data in Swift 3? 【发布时间】:2017-01-16 18:45:53 【问题描述】:我正在尝试创建一个简单的天气应用程序,该应用程序可以获取用户的位置并使用 Google Maps api 显示简单的天气数据。一切正常,除了我获取 JSON 并获取地址的部分。
func getAddressForLatLng(latitude: String, longitude: String)
let url = NSURL(string: "\(baseUrl)latlng=\(latitude),\(longitude)&key=\(apikey)")
let data = NSData(contentsOf: url! as URL)
let json = try! JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments) as! Dictionary
if let result = json["results"] as? Dictionary
if let address = result[0]["address_components"] as? Array
let number = address[0]["short_name"] as! String
let street = address[1]["short_name"] as! String
let city = address[2]["short_name"] as! String
let state = address[4]["short_name"] as! String
let zip = address[6]["short_name"] as! String
weatherDisplay.text = "\(city),\(state)"
上线:
let json = try! JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments) as! Dictionary
我收到此错误:
Cannot invoke 'jsonObject' with an argument list of type '(with: NSData?, options: JSONSerialization.ReadingOptions)'
我做错了什么?
【问题讨论】:
这里根本不需要使用 NSData(或 NSURL)。let url = URL(string: ...)
, let data = Data(contentsOf: ...)
问题是你将一个可选项传递给JSONSerialization
。您可以强制解包数据,例如JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments) as! Dictionary
请注意,使用 NSData(contentsOf: url! as URL)
(或 Swift 3 中的 Data(contentsOf:)
)是个坏主意。这是一个同步调用,将冻结 UI 直到它完成。你真的应该重写它来使用 NSURLSession。
我很难理解为什么这被否决了。在集合和相关标签的范围内似乎是一个合法的问题。
@LukeVanIn 你为什么要使用allowFragments?你知道如果下载失败,强制解包会崩溃吗?
【参考方案1】:
let nsdata = NSData()
let data = Data(referencing: nsdata)
https://developer.apple.com/documentation/foundation/data/3126627-init
【讨论】:
【参考方案2】:您需要更改一些内容。首先,您使用的是NSData
。您应该使用 Swift 类型 Data
。要将NSData?
转换为Data?
,只需将as Data?
添加到变量声明的末尾即可。
另外,你的类型是可选的,但你不能传入可选类型,所以你需要解开它(在这个例子中使用if let data = data /* stuff here */
):
func getAddressForLatLng(latitude: String, longitude: String)
let url = NSURL(string: "\(baseUrl)latlng=\(latitude),\(longitude)&key=\(apikey)")
let data = NSData(contentsOf: url! as URL) as Data? // <==== Added 'as Data?'
if let data = data // <====== Added 'if let'
let json = try! JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments) as! Dictionary
if let result = json["results"] as? Dictionary
if let address = result[0]["address_components"] as? Array
let number = address[0]["short_name"] as! String
let street = address[1]["short_name"] as! String
let city = address[2]["short_name"] as! String
let state = address[4]["short_name"] as! String
let zip = address[6]["short_name"] as! String
weatherDisplay.text = "\(city),\(state)"
更新:
你需要改变的另一件事是:
let json = try! JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments) as! Dictionary
当您转换为Dictionary
类型时,编译器不知道您在说什么,因为Dictionary
是generic type。所以你需要转换为Dictionary<String, AnyObject>
或[String: AnyObject]
(它们是相同的)。
【讨论】:
感谢您的快速回复!现在它说(在 let = json 行上)“通用参数 'key' 无法推断为 'Dictionary<_>” @EricPhillips 更新了我的答案! 现在,在if let address = result[0]["address_components"] as? Array
行上,它显示“对成员'下标'的模糊引用”。还有什么我应该添加/更改的吗?
@EricPhillips 不确定。我知道Array
类型就像Dictionary
类型。您需要添加数组的类型,即Array<String>
。如果您还有更多问题,我建议您使用 Google 搜索,然后在 SO (Stack Overflow) 上提出一个新问题。【参考方案3】:
刚投:let newData = nsData as Data
【讨论】:
这不是let data = NSData(contentsOf: url! as URL) as Data? // <==== Added 'as Data?'
在the accepted answer 中所做的吗?以上是关于如何在 Swift 3 中将 NSData 转换为数据?的主要内容,如果未能解决你的问题,请参考以下文章
将 UIImage 转换为 NSData 并在 Swift 中转换回 UIImage?
在 Swift 中将 UIView 保存和检索为 NSData