如何使用 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的主要内容,如果未能解决你的问题,请参考以下文章

如何动画一个圆圈来填充而不是使用.trim?

如何将嵌套的 Array/JSON 字符串存储在 .plist 文件中?

如何使用 .plist 文件填充表格视图?

猫鼬填充如何在同一对象而不是子文档中填充文档

Plist:它是啥以及如何使用它

如何在 Xcode 中动态填充 Info.plist 值?