简体   繁体   English

如何将解析后的数据存储在数组中?

[英]How to store the parsed data in the array?

I have a database on Firebase.我有一个关于 Firebase 的数据库。 I parse some data that I want to store in the array of structures:我解析了一些我想存储在结构数组中的数据:
postData.swift postData.swift

struct postData {
  let Title: String
  let Subtitle: String
  let imgURL: String
  let Date: String

  init(Title: String, Subtitle: String, imgURL: String, Date: String) {
    self.Title = Title
    self.Subtitle = Subtitle
    self.imgURL = imgURL
    self.Date = Date
  }
}

This array will be used for creating a collectionViewCells inside a tableViewCells .该数组将用于在tableViewCells中创建collectionViewCells Inside my ViewController I created a global array var dataPosts:[postData] = [] where I will store parsed data.在我的 ViewController 中,我创建了一个全局数组var dataPosts:[postData] = []我将在其中存储解析的数据。 Here is a function I made:这是我制作的 function:

var dataPosts:[postData] = []
...
override func viewDidLoad() {
       super.viewDidLoad()
       tableView = UITableView(frame: self.view.bounds, style: .grouped)
       tableView.delegate = self
       tableView.dataSource = self
       ...
       tableView.register(PostCell.self, forCellReuseIdentifier: PostTableID)
       parsePosts()
       print(dataPosts.count) // prints 0
   }
   
   func parsePosts() {
       let databaseRef = Database.database().reference(withPath: "Посты")
       var data:[postData]
       databaseRef.observeSingleEvent(of: .value) { (snapshot) in
           for child in snapshot.children {
               let snap = child as! DataSnapshot
               let res = snap.value as! [String: Any]
               
               let title = res["Заголовок"] as! String
               let subtitle = res["Подзаголовок"] as! String
               let img = res["URL"] as! String
               let date = res["Дата"] as! String
               
               self.dataPosts.append(postData(Title: title, Subtitle: subtitle, imgURL: img, Date: date))
               print(self.dataPosts.count, " - inside cycle") // prints 1
           }
       }
       data = dataPosts
       print(data.count, " - inside function") // prints 0
   }

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

Is there any way to store it in the array?有没有办法将它存储在数组中? Or I should use something from OOP (I'm a beginner)?或者我应该使用 OOP 的东西(我是初学者)? Thanks谢谢

First of all please name structs with starting uppercase letter and variables with starting lowercase letter.首先,请以大写字母开头的结构和以小写字母开头的变量命名。 The init method is not needed不需要init方法

struct PostData {
    let title: String
    let subtitle: String
    let imgURL: String
    let date: String
}

and

var dataPosts : [PostData] = []

Actually you have only to reload the table view after the loop inside the closure which receives the data asynchronously.实际上,您只需在异步接收数据的闭包循环之后重新加载表视图。 The temporary array data is not needed.不需要临时数组data

func parsePosts() {
   let databaseRef = Database.database().reference(withPath: "Посты")
   
   databaseRef.observeSingleEvent(of: .value) { (snapshot) in
       for child in snapshot.children {
           let snap = child as! DataSnapshot
           let res = snap.value as! [String: Any]
           
           let title = res["Заголовок"] as! String
           let subtitle = res["Подзаголовок"] as! String
           let img = res["URL"] as! String
           let date = res["Дата"] as! String
           
           self.dataPosts.append(PostData(title: title, subtitle: subtitle, imgURL: img, date: date))
           print(self.dataPosts.count, " - inside cycle") // prints 1
       }
       
       self.tableView.reloadData()
   }
}

And delete并删除

print(dataPosts.count) // prints 0

in viewDidLoad , it's useless.viewDidLoad中,它没用。

This is only a suggestion, instead of creating a struct create a NSObject class instead:这只是一个建议,而不是创建一个struct ,而是创建一个NSObject class :

import UIKit

class PostData: NSObject {
    
    @objc var title: String?
    @objc var subtitle: String?
    @objc var imgUrl: String?
    @objc var date: String?
    
    init(dictionary: [String: AnyObject]) {
        
        self.title = dictionary["title"] as? String
        self.subtitle = dictionary["subtitle"] as? String
        self.imgUrl = dictionary["imgUrl"] as? String
        self.date = dictionary["date"] as? String
        
    }
}

Make sure that the dictionary values such as the title, subtitle, etc. match with your firebase database values names.确保标题、副标题等字典值与您的 firebase 数据库值名称匹配。 I think that yours may be:我认为你的可能是:

init(dictionary: [String: AnyObject]) {
    self.title = dictionary["Заголовок"] as? String
    self.subtitle = dictionary["Подзаголовок"] as? String
    self.imgUrl = dictionary["URL"] as? String
    self.date = dictionary["Дата"] as? String
}

This way now when reading data you can initialize a PostData object with the dictionary from snapshot and append it to your array (If using it).现在,当读取数据时,您可以使用快照中的字典初始化 PostData object 并将 append 初始化到您的数组(如果使用它)。

EXAMPLE:例子:

// Here you had already observed a single event

if let postDict = snapshot.value as? [String: AnyObject] {
    let postData = PostData(dictionary: postDict)

    // append to array if needed
    self.postsData.append(newElement: postData)

}

REMEMBER that with your object we are working with optionals values, that means that you may need to use guard let or if let statements to make sure this properties are not nil (this may not be the case if this are correctly parsed with your firebase database).请记住,对于您的 object,我们正在使用可选值,这意味着您可能需要使用guard letif let语句来确保此属性不为零(如果使用 firebase 数据库正确解析,则可能不是这种情况)。

EXAMPLE:例子:

// Let's suppose that you need to access to the "title" property

// This dictionary is a hardcoded dictionary, yours may be downloaded from your database
let dictionary: [String: AnyObject] = [
    "title": "a title" as AnyObject,
    "subtitle": "a subtitle" as AnyObject,
    "imgUrl": "an imgUrl" as AnyObject,
    "date": "a date" as AnyObject
]

let postData = PostData(dictionary: dictionary)

// THIS IS THE INCORRECT WAY
let postTitle = postData.title
print(postTitle!) /* The print statement does not require a non-optional value, but may print something like: Optional("a title"), in your case you may want a non-optional value */

// THIS IS THE CORRECT WAY
if let postTitle = postData.title {
    print(postTitle) // Prints: "a title"
}

// ALTERNATIVE TO CORRECT WAY
guard let postTitle = postData.title else { return }
print(postTitle) // Prints: "a title"

This may helps you to write less lines of code and make it simple to understand.这可以帮助您编写更少的代码行并使其易于理解。

COMPLETE EXAMPLE:完整示例:

var postsDataArray = [PostData]()

func parsePosts() {
   let databaseRef = Database.database().reference(withPath: "Посты")
   
   databaseRef.observeSingleEvent(of: .value) { (snapshot) in
       
       if let postDict = snapshot.value as? [String: AnyObject] {

           let postData = PostData(dictionary: postDict)

           self.postsDataArray.append(newElement: postData)

       }
       
       self.tableView.reloadData()
   }
}

This last example is using PostData as a NSObject class as I showed you on the example above.最后一个示例使用 PostData 作为NSObject class,正如我在上面的示例中向您展示的那样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM