arrays - Xcode 说我的数组超出范围,但我可以确认我的数组没有超出范围
问题描述
我有一个用于我的 TableView 单元的数组,类似于 Facebook 提要。我已经成功地让我的应用程序版本的 Feed 成功显示用户发帖的日期、显示创建帖子的用户电子邮件、显示随帖子上传的照片,但我似乎无法弄清楚如何为他们的用户个人资料制作一个数组。所有信息都是从 Firebase 中提取的。
下面你可以看到我的数据库结构的屏幕截图。
在这里,您可以看到我存储帖子信息的帖子结构。
Posts > DocumentID > PostInformation(日期、上传的图片 url 为字符串、海报电子邮件,如计数为 Int)
表视图
我正在尝试从另一个名为 Public 的集合中提取用户的个人资料。
公共 > 用户电子邮件 (test@gmail.com) > 用户信息(姓名、日期、个人资料照片网址)
我从获取 Firestore 数据库的信息中获得了帖子信息,并将所有内容都放入了一个数组中。
然后我将所有内容加载到 tableview 单元格中。
//发布变量 var userCommentArray = String
var likeArray = [Int]()
var userPostImageArray = [String]()
var userProfilePhotoArray = [String]()
var userPostDescription = [String]()
var PosterEmail = [String]()
var postDate = [String]()
var documentIDArray = [String]()
以上是我的帖子变量
下面是我的单元格和用于加载其信息的数组。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let Cell = tableView.dequeueReusableCell(withIdentifier: "VidaFeed", for: indexPath) as! FeedCell
print("Posteremail count = \(PosterEmail.count)")
>> //Cell.userProfilePhotoFeedCellLabel.sd_setImage(with: URL(string: self.userProfilePhotoArray[indexPath.row]))
Cell.FeedCellUserNameLabel.text = PosterEmail[indexPath.row]
Cell.dateFeedCellLabel.text = "test"
Cell.likeCountFeedCellLabel.text = String(likeArray[indexPath.row])
Cell.postImageFeedCellLabel.sd_setImage(with: URL(string: self.userPostImageArray[indexPath.row]))
Cell.postDescriptionLabel.text = userPostDescription[indexPath.row]
if userPostImageArray[indexPath.row] == ""{
Cell.postImageFeedCellLabel.isHidden = true
}
if userPostImageArray[indexPath.row] != "" {
Cell.postImageFeedCellLabel.isHidden = false
}
return Cell
//Cell.userProfilePhotoFeedCellLabel.sd_setImage(with: URL(string: self.userProfilePhotoArray[indexPath.row]))
如果我只注释掉配置文件单元格,那么我的应用程序会成功运行,但每当我添加它时它就会崩溃。
下面你可以看到我在哪里尝试确保我的 var userProfilePhotoArray 不会超出我的索引范围,因为我将它设置为等于一个变量以限制超出数组范围。
if self.profilecount <= self.PosterEmail.count{
self.profilecount = self.profilecount + 1
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return PosterEmail.count
}
func getDatFromFirestore() {
let firestoreDatabase = Firestore.firestore()
firestoreDatabase.collection("Posts").order(by: "Date" , descending : true).addSnapshotListener { (snapshot, error) in
if error != nil {
print(error?.localizedDescription ?? "Connection Error")
} else {
self.userPostImageArray.removeAll(keepingCapacity: false)
self.userCommentArray.removeAll(keepingCapacity: false)
self.userCommentArray.removeAll(keepingCapacity: false)
self.likeArray.removeAll(keepingCapacity: false)
self.PosterEmail.removeAll(keepingCapacity: false)
self.userProfilePhotoArray.removeAll(keepingCapacity: false)
for document in snapshot!.documents {
self.dbread = self.dbread + 1
print(self.dbread)
let documentID = document.documentID
self.documentIDArray.append(documentID)
self.getUserProfilePhoto()
if let postedBy = document.get("postedBy") as? String {
self.PosterEmail.append(postedBy)
let db = Firestore.firestore()
let docRef = db.collection("Public").document(postedBy)
docRef.getDocument { (document, error) in
if self.profilecount <= self.PosterEmail.count{
self.profilecount = self.profilecount + 1
print("Profile count is \(self.profilecount)")
if let document = document, document.exists {
print(document)
if let userProfile = document.get("imageUrl") as? String {
self.userProfilePhotoArray.append(userProfile)
print("time = \(Date.self), \(self.userProfilePhotoArray).")
}
}
}
}
if let postDescription = document.get("PostDescription") as? String {
self.userPostDescription.append(postDescription)
}
if let imageUrl = document.get("imageUrl") as? String {
self.userPostImageArray.append(imageUrl)
}
if let PostLikes = document.get("Likes") as? Int {
self.likeArray.append(PostLikes)
}
if let timeStamp = document.get("Date") as? Date {
let formatter = DateFormatter()
formatter.dateFormat = "MM/dd/yyyy"
let dateString = formatter.string(from: timeStamp)
let timeStampAsString = dateString
self.postDate.append(timeStampAsString)
}
}
self.VidaFeed.reloadData()
}
}
}
下面是输出,我可以清楚地看到该数组等于我的 PosterEmail 数组计数,并且它不会结束,但是每当为用户的个人资料图像重新添加单元格时,应用程序就会崩溃。
Posteremail count = 1
Profile count is 1
<FIRDocumentSnapshot: 0x6000001a2850>
time = 2020-06-01 03:00:28 +0000, "https://firebasestorage.googleapis.com/v0/b/vida-clock-11690.appspot.com/o/UserProfilePhotos%2F8C2ADEC6-C108-4C70-8CDA-ADBFCC56B4E2?alt=media&token=1c2178b8-b35b-4e2a-bbc0-c7747843b673"].
我只是被困住了,到目前为止,我已经厌倦了。有什么建议么?
解决方案
将Firebase
通过网络连接或本地磁盘缓存获取文档,这意味着无法保证每个 API 调用需要多长时间。因此,Firebase API
调用始终是异步的。您的第一个 API 调用将获取Posts
按日期排序的集合,遍历所有文档并将数据附加到PosterEmail
数组中。它还将数据附加到userProfilePhotoArray
数组中,但请注意,这是通过不同的 API 调用完成的,这意味着它是异步完成的。但是,您在第二个异步调用完成之前调用reloadData()
方法VidaFeed
- 填充的那个userProfilePhotoArray
- 这意味着计数PosterEmail
并不userProfilePhotoArray
相同。
解决此问题的一种方法是在其中self.VidaFeed.reloadData()
添加docRef.getDocument { (document, error) in ... }
:
docRef.getDocument { (document, error) in
if self.profilecount <= self.PosterEmail.count{
self.profilecount = self.profilecount + 1
print("Profile count is \(self.profilecount)")
if let document = document, document.exists {
print(document)
if let userProfile = document.get("imageUrl") as? String {
self.userProfilePhotoArray.append(userProfile)
print("time = \(Date.self), \(self.userProfilePhotoArray).")
// Add this line.
self.VidaFeed.reloadData()
}
}
}
}
这样可以确保VidaFeed
每次将新项目添加到 时都会收到通知userProfilePhotoArray
。
现在,在cellForRowAt
方法中,替换
Cell.userProfilePhotoFeedCellLabel.sd_setImage(with: URL(string: self.userProfilePhotoArray[indexPath.row]))
和
if indexPath.row < self.userProfilePhotoArray.count {
Cell.userProfilePhotoFeedCellLabel.sd_setImage(with: URL(string: self.userProfilePhotoArray[indexPath.row]))
}
推荐阅读
- json - 使用 JSON SERDE 读取 json 文件时,我只得到一行
- css - 如何使@page size 适用于小尺寸
- r - R为什么带有重复/重复行名的矩阵会出现点和数字?
- html - Bootstrap 4.5 卡中的完整按钮
- mule - 在 mule 3 中进行映射时从数组对象中删除空 json 数组
- javascript - 带有电话面具的验证表
- python - 如何在没有循环的情况下打印列表值
- python - ValueError:尝试使用 mingw-w64 进行编译时,未知 MS 编译器版本 1916
- reactjs - 如何根据返回对象的唯一标识轻松设置下拉列表中的选定值?
- amazon-web-services - AWS sns 订阅过滤策略限制