如何使用 json 而不是 plist 来填充 TableView
Posted
技术标签:
【中文标题】如何使用 json 而不是 plist 来填充 TableView【英文标题】:How do I use json instead of plist to populate TableView 【发布时间】:2016-08-18 11:12:57 【问题描述】:我有一个工作应用程序,它从远程服务器上的 pList 获取数据。但是,我现在想使用 json 而不是 plist 并且正在努力理解如何做到这一点!任何帮助都非常感谢,任何例子都很棒。
一些选定的代码 - 首先下载 plist,然后使用下载的 plist 填充 TableView。注意:我没有包含所有代码。
@IBAction func startDownload(sender: AnyObject)
progressView.hidden = false
let url = NSURL(string: "http://ftp.iphoneData@dittodata.host-ed.me/Annotations/myAnnotationsKalkan.plist")!
downloadTask = backgroundSession.downloadTaskWithURL(url)
downloadTask.resume()
func showFileWithPath(path: String)
let isFileFound:Bool? = NSFileManager.defaultManager().fileExistsAtPath(path)
if isFileFound == true
let viewer = UIDocumentInteractionController(URL: NSURL(fileURLWithPath: path))
viewer.delegate = self
viewer.presentPreviewAnimated(true)
// print("file is found")
@IBOutlet var progressView: UIProgressView!
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
// 1
func URLSession(session: NSURLSession,
downloadTask: NSURLSessionDownloadTask,
didFinishDownloadingToURL location: NSURL)
let path = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
let documentDirectoryPath:String = path[0]
let fileManager = NSFileManager()
let destinationURLForFile = NSURL(fileURLWithPath: documentDirectoryPath.stringByAppendingString("/myAnnotationsKalkan.plist.plist"))
if fileManager.fileExistsAtPath(destinationURLForFile.path!)
showFileWithPath(destinationURLForFile.path!)
else
do
try fileManager.moveItemAtURL(location, toURL: destinationURLForFile)
// show file
showFileWithPath(destinationURLForFile.path!)
catch
print("An error occurred while moving file to destination url")
// 2
func URLSession(session: NSURLSession,
downloadTask: NSURLSessionDownloadTask,
didWriteData bytesWritten: Int64,
totalBytesWritten: Int64,
totalBytesExpectedToWrite: Int64)
progressView.setProgress(Float(totalBytesWritten)/Float(totalBytesExpectedToWrite), animated: true)
func URLSession(session: NSURLSession,
task: NSURLSessionTask,
didCompleteWithError error: NSError?)
downloadTask = nil
progressView.setProgress(0.0, animated: true)
if (error != nil)
print(error?.description)
else
// print("The task finished transferring data successfully")
progressView.hidden = true
// TableViewController.swift
/ museumTemplate
//
import UIKit
class MyTableViewController: UITableViewController
var titleData = [String]()
var subTitleData = [String]()
var stateData = [String]()
var codeData = [String]()
var infoData = [String]()
var openData = [String]()
var phoneData = [String]()
var emailData = [String]()
var webData = [String]()
var latData = [Double]()
var lonData = [Double]()
var titleToPass = [String]()
var thisState = [String]()
var stateOrAlpha = ""
var titleText = ""
override func viewDidLoad()
super.viewDidLoad()
navigationItem.title = titleText
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
let sourcePath = documentsPath.stringByAppendingPathComponent("myAnnotationsKalkan.plist.plist")
if let content = NSArray(contentsOfFile: sourcePath as String)
let descriptor = NSSortDescriptor(key: stateOrAlpha, ascending: true)
let myMuseum = content.sortedArrayUsingDescriptors([descriptor])
for item in myMuseum
titleData.append(item.objectForKey("title") as! String)
subTitleData.append(item.objectForKey("subtitle") as! String)
infoData.append(item.objectForKey("info") as! String)
phoneData.append(item.objectForKey("phone") as! String)
webData.append(item.objectForKey("web") as! String)
emailData.append(item.objectForKey("email") as! String)
latData.append(item.objectForKey("latitude") as! Double)
lonData.append(item.objectForKey("longitude") as! Double)
override func numberOfSectionsInTableView(tableView: UITableView) -> Int
// Return the number of sections.
return 1
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
// Return the number of rows in the section.
return titleData.count
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCellWithIdentifier("tableCell", forIndexPath: indexPath) as UITableViewCell
// Configure the cell..title and subTitle.
cell.textLabel!.text = titleData[indexPath.row]
return cell
【问题讨论】:
使用 13(!) 个数组作为数据源是非常糟糕的编程习惯。 Swift 是一种面向对象的语言,因此请使用自定义类或结构。与属性列表不同,JSON 文件是纯文本。您可以使用dataTask
而不是downloadTask
,并且必须将文本转换(反序列化)为数组或字典。
感谢您的建议和信息
我应该补充一点,我确实在其他应用程序的类似代码中使用了自定义类。这个我正在试验,又快又脏 :-)
【参考方案1】:
我使用 Alamofire,它更容易和更安全地执行 Web 请求,但这里有一个没有它的代码:
let urlPath = "YourUrlRequest"
let session = NSURLSession.sharedSession()
let url = NSURL(string: urlPath)!
session.dataTaskWithURL(url) ( data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
if let responseData = data
do
let jsonObject = try NSJSONSerialization.JSONObjectWithData(responseData, options: []) as! NSArray
for dataDict : AnyObject in jsonObject
let idj: String = dataDict.objectForKey("id") as!String
let namej: String = dataDict.objectForKey("name") as! String
let indicativej: String = dataDict.objectForKey("indicative") as! String
let flagj: String = dataDict.objectForKey("flag") as! String
saveCountryFromWeb(idj, name: namej, indicative: indicativej, flag: flagj)
catch let error as NSError
print("Failed to load: \(error.localizedDescription)")
.resume()
希望对您有所帮助,如果您想要我推荐的 alamofire 样品,请告诉我 ;)
【讨论】:
Kika_Fortez 没有使用过 Alamofire,所以请回复:样品。虽然我的意图是在整理时使用 Firebase 进行数据访问。感谢您的积极帮助 好的,所以用firebase检索数据你不需要使用它们,因为firebase默认有他的方法,所以我会放一个firebase的例子。请勾选正确答案。 终于有时间玩你的代码了。这行出现错误 let jsonObject = try NSJSONSerialization.JSONObjectWithData(responseData, options: []) as! NSArray SIGABRT - 无法将“__NSCFDictionary”(0x44c5c0)类型的值转换为“NSArray”(0x44c2f0)。 好的!尝试改为此代码: let jsonObject = try NSJSONSerialization.JSONObjectWithData(responseData, options: []) as! NSDictionary 谢谢。但是,我已经尝试过了,并提出了错误“键:AnyObject,值:AnyObject)”不符合协议“AnyObject”,但是,我得到了一些工作代码(欢迎任何 cmets/改进)。接下来,如果时间允许,我将尝试实现您为 Firebase 提供的示例 :-) 祝您好运【参考方案2】:func retrieveBarcodeData()
let databaseref = FIRDatabase.database().reference()
databaseref.child("barcodes").queryOrderedByKey().observeEventType(.ChildAdded, withBlock:
snapshot in
let codig = snapshot.value!["codigo"] as! String
let desc = snapshot.value!["designacao"] as! String
let Url = snapshot.value!["ImageURL"] as! String
barcodes.insert(BarCodeStruct(code: codig, description: desc, ImageURL: Url),atIndex: 0)
self.tableView.reloadData()
)
别忘了在 firebase 中配置你的数据库,并使用 cocoapods 安装 firebase 并将 FIRApp.configure() 放入你的 appDelegate didFinishLaunchingWithOptions
【讨论】:
【参考方案3】:我尝试使用此代码从服务器下载一个简单的 json 文件,它似乎可以工作:
override func viewDidLoad()
super.viewDidLoad()
let requestURL: NSURL = NSURL(string: "http://ftp.iphoneData@dittodata.host-ed.me/Annotations/testData4.json")!
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(URL: requestURL)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(urlRequest)
(data, response, error) -> Void in
let httpResponse = response as! NSHTTPURLResponse
let statusCode = httpResponse.statusCode
if (statusCode == 200)
print("File downloaded.")
// print(testData4.json)
do
let json = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments)
if let users = json["users"] as? [[String: AnyObject]]
for user in users
if let name = user["name"] as? String
if let subtitle = user["subtitle"] as? String
print(name,subtitle)
catch
print("Error with Json: \(error)")
task.resume()
【讨论】:
以上是关于如何使用 json 而不是 plist 来填充 TableView的主要内容,如果未能解决你的问题,请参考以下文章