XML 数据保存在 NSUserDefaults 或文档目录中

XML data save in NSUserDefaults or in Documents Directory

我正在制作一个简单的新闻应用程序,并尝试在 NSUserDefaults 中保存(标题、描述、日期、图像及其数据)以供离线阅读。我希望当它在 NSUserDefaults 中保存数据时,它会离线显示,并且当有新数据可用时,它会重写或替换为以前的数据。 我知道如何在 NSUserDefaults 中保存字符串数组,但不知道如何在 NSUserDefaults 中保存图像。我正在尝试制定保存数据的逻辑并检查它是否有新数据可用但没有成功,启动画面也需要更多时间才能消失,这是由于从服务器加载数据还是由于互联网连接速度慢? 任何人都可以检查我的代码以修复它。 谢谢

class ViewController2: UIViewController ,NSXMLParserDelegate {

    let newsDefaults = NSUserDefaults.standardUserDefaults()

    @IBOutlet weak var tableView: UITableView!

    var parser = NSXMLParser()
    var posts = NSMutableArray()
    var elements = NSMutableDictionary()
    var element = NSString()
    var title1 = NSMutableString()
    var date = NSMutableString()
    var link = NSMutableString()
    var des = NSMutableString()
    var img2 = NSMutableString()


    var NSUserDefaultsTitle : [NSString] = []
    var NSUserDefaultsDate : [NSString] = []
    var NSUserDefaultsDes : [NSString] = []

    var NSUserDefaultsImage : [UIImage] = []

    typealias CompletionHandler = (image: UIImage) -> Void

    var attrsUrl : [String : NSString]!
    var urlPic :  NSString?

    var postLink: String = String()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.configure()

        self.beginParsing()
    }

    override func viewWillAppear(animated: Bool) {
//        if let HaveTitle = newsDefaults.objectForKey("t"){
//            NSUserDefaultsTitle = HaveTitle.mutableCopy() as! [NSString]
//        }
//        if let HaveDate = newsDefaults.objectForKey("d"){
//            NSUserDefaultsDate = HaveDate.mutableCopy() as! [NSString]
//        }
//        if let HaveDes = newsDefaults.objectForKey("des"){
//            NSUserDefaultsDes = HaveDes.mutableCopy() as! [NSString]
//        }
//        if let imageData = newsDefaults.objectForKey("imgData"){
//            NSUserDefaultsImage = imageData.mutableCopy() as! [UIImage]
//        }
//
//        print(newsDefaults.objectForKey("d"))
    }

    func beginParsing()
    {
        posts = []
        parser = NSXMLParser(contentsOfURL:(NSURL(string: "http://www.voanews.com/api/zq$omekvi_"))!)!
        parser.delegate = self
        parser.parse()

        tableView!.reloadData()
    }

    //XMLParser Methods

    func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String])
    {
        element = elementName
        if (elementName as NSString).isEqualToString("item")
        {
            elements = NSMutableDictionary()
            elements = [:]
            title1 = NSMutableString()
            title1 = ""
            date = NSMutableString()
            date = ""
            link = NSMutableString()
            link = ""
            des = NSMutableString()
            des = ""
            img2 = NSMutableString()
            img2 = ""
        }
        if elementName == "enclosure" {
            attrsUrl = attributeDict as [String: NSString]
             urlPic = attrsUrl["url"]
            print(urlPic!, terminator: "")

        }
    }

    func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?)
    {
        if (elementName as NSString).isEqualToString("item") {
            if !title1.isEqual(nil) {
                elements.setObject(title1, forKey: "title")
            }
            if !date.isEqual(nil) {
                elements.setObject(date, forKey: "pubDate")
            }
            if !link.isEqual(nil) {
                elements.setObject(link, forKey: "link")
            }
            if !des.isEqual(nil){
                elements.setObject(des, forKey: "description")
            }
            if !img2.isEqual(nil){
                elements.setObject(urlPic!, forKey: "enclosure")
            }

            posts.addObject(elements)
//
//            if let HaveData = newsDefaults.objectForKey("post"){
//
//            }else{
//            
////                newsDefaults.setObject(self.posts.valueForKey("title"), forKey: "t")
////                newsDefaults.setObject(self.posts.valueForKey("pubDate"), forKey: "d")
////                newsDefaults.setObject(self.posts.valueForKey("description"), forKey: "des")
//                
//                newsDefaults.setObject(posts, forKey: "post")
//                
                print("elementName")
//            }
        }
        print("didEndElement")

    }

    func parser(parser: NSXMLParser, foundCharacters string: String)
    {
        if element.isEqualToString("title") {
            title1.appendString(string)
        } else if element.isEqualToString("pubDate") {
            date.appendString(string)
            print(date)
        }
        else if element.isEqualToString("link"){
            link.appendString(string)
        }else if element.isEqualToString("description"){
            des.appendString(string)
        }else if element.isEqualToString("enclosure"){
            img2.appendString(string)
        }
        print("foundCharacter")
    }

    private func configure() {
        self.navigationController?.navigationBar.titleTextAttributes = [NSFontAttributeName: UIFont.boldSystemFontOfSize(20.0), NSForegroundColorAttributeName: UIColor.whiteColor()]

        self.tableView.registerNib(UINib(nibName: "2ImageCell", bundle: nil), forCellReuseIdentifier: "imageCell")
        self.tableView.delegate = self
        self.tableView.dataSource = self

        self.fillNavigationBar(color: UIColor(red: 252.0/255.0, green: 0, blue: 0, alpha: 1.0))

    }

    private func fillNavigationBar(color color: UIColor) {
        if let nav = self.navigationController {
            nav.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: .Default)
            nav.navigationBar.shadowImage = UIImage()
            for view in nav.navigationBar.subviews {
                if view.isKindOfClass(NSClassFromString("_UINavigationBarBackground")!) {
                    if view.isKindOfClass(UIView) {
                        (view as UIView).backgroundColor = color
                    }
                }
            }
        }
    }
}

extension ViewController2: UITableViewDelegate, UITableViewDataSource {

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        self.tableView.deselectRowAtIndexPath(indexPath, animated: true)

        let view = ImageModalView2.instantiateFromNib()
        view.des.text = posts.objectAtIndex(indexPath.row).valueForKey("description") as? String

        downloadFileFromURL(NSURL(string: self.posts.objectAtIndex(indexPath.row).valueForKey("enclosure") as! String)!, completionHandler:{(img) in
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                view.image = img
            })
        })

        let window = UIApplication.sharedApplication().delegate?.window!
        let modal = PathDynamicModal.show(modalView: view, inView: window!)
        view.closeButtonHandler = {[weak modal] in
            modal?.closeWithLeansRandom()
            return
        }
    }

    @IBAction func printData(sender: AnyObject) {
        print(NSUserDefaultsImage)

    }

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return 80.0
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return posts.count
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = self.tableView.dequeueReusableCellWithIdentifier("imageCell", forIndexPath: indexPath) as! ImageCell2
//        if let picURL = user["picture"].string, url = NSURL(string: picURL) {
//            if let data = NSData(contentsOfURL: url) {
//                cell!.imageView?.image = UIImage(data: data)
//            }
        cell.titleLabel.text = posts.objectAtIndex(indexPath.row).valueForKey("title") as! NSString as String
//        if NSUserDefaultsImage              {
//            cell.sideImageView.image = NSUserDefaultsImage[indexPath.row]
//        }else{
        downloadFileFromURL(NSURL(string: self.posts.objectAtIndex(indexPath.row).valueForKey("enclosure") as! String)!, completionHandler:{(img) in
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                cell.sideImageView.image = img
//                self.NSUserDefaultsImage.append(img)
//                print(img)
//                self.newsDefaults.setObject(self.NSUserDefaultsImage, forKey: "imgData")
            })
        })
//    }
        //cell.date.text = posts.objectAtIndex(indexPath.row).valueForKey("pubDate") as? String
        //cell.sideImageView?.contentMode = UIViewContentMode.ScaleAspectFit
        //cell.sideImageView?.image = image
        cell.titleLabel.userInteractionEnabled = false
        cell.titleLabel.editable = false
        cell.titleLabel.selectable = false
        return cell
    }


    func downloadFileFromURL(url1: NSURL?,completionHandler: CompletionHandler) {
        // download code.
        if let url = url1{
            let priority = DISPATCH_QUEUE_PRIORITY_HIGH
            dispatch_async(dispatch_get_global_queue(priority, 0)) {
                let data = NSData(contentsOfURL: url)
                if data != nil {
                    print("image downloaded")
                    completionHandler(image: UIImage(data: data!)!)
                }
            }
        }
    }


}

Apple 不推荐在 NSUserDefault 中保存大数据,我们不应该保存大数据。 NSUserDefault 或 Keychain 我们用来存储 "Username"、"Password" 之类的信息较少。

您可以使用CoreData or Sqlite对数据进行操作。

为了将图像保存到 NSUserDefaults,您需要将其转换为 NSData,因为那里只允许某些类型。

至于在其中存储信息以供离线查看的想法....这听起来更像是应用程序文档目录的工作。您应该能够在对象中使用 NSCoding 协议,并通过调用将所有信息写入磁盘 NSKeyedArchiver:archiveRootObject:toFile 在主对象上,它将在所有子对象上调用 encodeWithCoder。