观察调用不更新字典值。异步的问题
Posted
技术标签:
【中文标题】观察调用不更新字典值。异步的问题【英文标题】:Observe call not updating dictionary value. Problem with async 【发布时间】:2019-12-14 18:04:20 【问题描述】:我正在尝试从我的 firebase 数据库中获取图像列表。在观察方法中,如果我打印帖子的数量,它可以正常工作。如果我在观察函数之外打印帖子数,但仍在 fetchPosts() 函数内,我得到 0。如果我在 fetchPosts() 调用(使用观察的函数)之后打印帖子数,我得到 0。
如何在此异步调用中将值保存到我的字典帖子中?我已经尝试过完成和调度组。我可能没有正确实现它们,所以如果你看到一个简单的方法,那么请帮助我。代码如下:
import UIKit
import SwiftUI
import Firebase
import FirebaseUI
import SwiftKeychainWrapper
class FeedViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource
@IBOutlet weak var collectionview: UICollectionView!
//var posts = [Post]()
var posts1 = [String]()
didSet
collectionview.reloadData()
var following = [String]()
//var posts1 = [String]()
var userStorage: StorageReference!
var ref : DatabaseReference!
override func viewDidLoad()
super.viewDidLoad()
// Do any additional setup after loading the view.
fetchPosts()
// func lengthyTask(completionHandler: (Int) -> Int)
//
// let result = completionHandler(42)
// print(result)
//
//
// lengthyTask(completionHandler: number in
// print(number)
// return 101
// )
//
func fetchPosts()
let uid = Auth.auth().currentUser!.uid
let ref = Database.database().reference().child("posts")
let uids = Database.database().reference().child("users")
uids.observe(DataEventType.value, with: (snapshot) in
let dict = snapshot.value as! [String:NSDictionary]
for (_,value) in dict
if let uid = value["uid"] as? String
self.following.append(uid)
ref.observe(DataEventType.value, with: (snapshot2) in
let dict2 = snapshot2.value as! [String:NSDictionary]
for(key, value) in dict
for uid2 in self.following
if (uid2 == key)
for (key2,value2) in value as! [String:String]
//print(key2 + "this is key2")
if(key2 == "urlToImage")
let urlimage = value2
//print(urlimage)
self.posts1.append(urlimage)
self.collectionview.reloadData()
print(self.posts1.count)
)
self.collectionview.reloadData()
)
//ref.removeAllObservers()
//uids.removeAllObservers()
print("before return")
print(self.posts1.count)
//return self.posts1
func numberOfSections(in collectionView: UICollectionView) ->Int
return 1
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
return posts1.count
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PostCell", for: indexPath) as! PostCell
cell.postImage.sd_setImage(with: URL(string: posts1[indexPath.row]))
//creating the cell
//cell.postImage.downloadImage(from: self.posts[indexPath.row])
// let storageRef = Storage.storage().reference(forURL: self.posts[indexPath.row].pathToImage)
//
//
print("im trying")
//let stickitinme = URL(fileURLWithPath: posts1[0])
//cell.postImage.sd_setImage(with: stickitinme)
//cell.authorLabel.text = self.posts[indexPath.row].author
//cell.likeLabel.text = "\(self.posts[indexPath.row].likes) Likes"
return cell
@IBAction func signOutPressed(_sender: Any)
signOut()
self.performSegue(withIdentifier: "toSignIn", sender: nil)
@objc func signOut()
KeychainWrapper.standard.removeObject(forKey:"uid")
do
try Auth.auth().signOut()
catch let signOutError as NSError
print("Error signing out: %@", signOutError)
dismiss(animated: true, completion: nil)
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
*/
【问题讨论】:
删除闭包外的(无意义的)print
行,并在闭包内做你必须做的事情。
我真的不知道如何使用闭包。我只是用谷歌搜索了它们,然后就出现了。我知道完成处理程序,但实际上没有人告诉你它是如何工作的。我只是想加载一个集合视图,但我仍然不知道一旦我填充了“帖子”字典,这是否会起作用。你能帮我解决一下闭包语法吗?
【参考方案1】:
您只需要稍作改动
简单地声明posts1
var posts1 = [String]()
并删除属性观察者didSet
在self.posts1.append(..
之后删除self.collectionview.reloadData()
这一行
将最后出现的self.collectionview.reloadData()
上移一级,将其包装在DispatchQueue
块中以更新主线程上的集合视图并删除外部闭包后的print
行
DispatchQueue.main.async
self.collectionview.reloadData()
)
)
而且第二个闭包中有一个错字。应该是
let dict2 = snapshot2.value as! [String:NSDictionary]
for(key, value) in dict2
带有尾随索引的变量名很容易出错,最好是 userDict
和 postDict
编辑:
这是执行顺序的代码
override func viewDidLoad()
super.viewDidLoad()
collectionview.dataSource = self
collectionview.delegate = self
// 1
fetchPosts()
// 5
func fetchPosts()
// 2
let uid = Auth.auth().currentUser!.uid
let ref = Database.database().reference().child("posts")
let uids = Database.database().reference().child("users")
// 3
uids.observe(DataEventType.value, with: (snapshot) in
// 6
let dict = snapshot.value as! [String:NSDictionary]
for (_,value) in dict
if let uid = value["uid"] as? String
self.following.append(uid)
// 7
ref.observe(DataEventType.value, with: (snapshot2) in
// 9
let dict2 = snapshot2.value as! [String:NSDictionary]
for(key, value) in dict2 // TYPO!!!!
for uid2 in self.following
if (uid2 == key)
for (key2,value2) in value as! [String:String]
//print(key2 + "this is key2")
if(key2 == "urlToImage")
let urlimage = value2
//print(urlimage)
self.posts1.append(urlimage)
print(self.posts1.count)
DispatchQueue.main.async
// 11
self.collectionview.reloadData()
// 10
)
// 8
)
// 4
【讨论】:
没用。返回后posts1仍然是空的。还有其他想法吗?无论如何感谢您的帮助。 如果闭包中的print(self.posts1.count)
行打印了正确数量的帖子,那么集合视图必须显示数据,至少"im trying"
。不要在同一方法中运行代码 underneath。
闭包是什么意思?您是在谈论“观察”电话吗?包装在调度队列中仍然不起作用。我也无法打印“我正在尝试”。你能解释一下其他集合视图方法是如何工作的吗?苹果开发文档根本没有帮助。
闭包是( ... )
里面的代码。 在下面闭包意味着代码就像原始fetchPosts
末尾的无用打印行一样。
有没有办法让程序在加载字典时停止?我正在关注一个教程,他们让它以这种方式工作,所以我真的很想了解哪里出了问题。我在学校里从来没有学过任何关于异步的知识:(正确的帖子数量只有在它被附加到 fetchPosts() 时才会打印出来。假设集合视图在 fetchPosts() 存在之前不会加载是否正确?以上是关于观察调用不更新字典值。异步的问题的主要内容,如果未能解决你的问题,请参考以下文章