如何在不创建无限循环的情况下在闭包中使用闭包?
How can I use Closures in Closures, without creating an infinite loop?
这是我的代码
fetchCurrentUser() 函数首先调用 'observeCurrentUserFromDisk',如果它不在磁盘上则调用 'observeCurrentUserToDisk'(firebase),我如何在调用 [=17= 后再次调用 'observeCurrentUserFromDisk' ] 到 return 从 'observeCurrentUserFromDisk' 到第一个使用闭包调用 'observeCurrentUserFromDisk' 的函数(fetchCurrentUser)的结果,试图维护 D.R.Y 谢谢。
func fetchCurrentUser() {
// I don't want to call these two functions each time
Api.User.observeCurrentUserFromDisk(onSuccess: { (user) in
self.emailLabel.text = user.email
if let profileUrl = URL(string: user.profileImageUrl!) {
self.profileImageView.sd_setImage(with: profileUrl)
}
}) {
Api.User.observeCurrentUserToDisk(onSuccess: {
self.fetchCurrentUser()
}) { (error) in
ProgressHUD.showError(error)
}
}
}
func observeCurrentUserToDisk(onSuccess: @escaping () -> Void, onError: @escaping (_ errorMessage: String) -> Void) {
guard let currentUser = Api.User.CURRENT_USER?.uid else { return }
Config.REF_USERS.child(currentUser).observeSingleEvent(of: .value, with: { (snapshot) in
if let dict = snapshot.value as? [String: Any] {
let user = UserModel.transformUser(dict: dict, key: snapshot.key)
Api.Realm.writeUserToDisk(user)
onSuccess()
}
})
}
func observeCurrentUserFromDisk(onSuccess: @escaping (RealmUser) -> Void, onError: @escaping () -> Void) {
guard let uid = Api.User.CURRENT_USER?.uid else { return }
let predicate = NSPredicate(format: "id = %@", uid)
var users: Results<RealmUser>!
users = usersOnDisk.objects(RealmUser.self).filter(predicate)
if let index = users.index(matching: predicate) {
let user = users[index]
onSuccess(user)
} else {
onError()
}
}
您可以在 vars 中捕获您的闭包,然后在另一个闭包中引用它。例如:
var onFetch = { a in print(a) }
var saveUsers = { b in
if b {
onFetch()
}
}
在其自身内部调用函数没有问题 - 这称为递归,只要您有停止条件,这就不会是无限的。
在您的情况下,您正在确定需要执行的某个地方 observeCurrentUserToDisk
- 据推测,如果您不这样做,那么该功能就会完成。那就是你的停止条件。
此外,由于 fetchCurrentUser
是异步的,您将调用它并需要对其结果进行操作,因此向其添加完成(onSuccess
和 onError
)处理程序作为嗯。
大致思路如下:
func fetchCurrentUser(onSuccess: @escaping (RealmUser) -> Void,
onError: @escaping (String) -> Void) {
observeCurrentUserFromDisk(
onSuccess: onSuccess,
onError: {
observeCurrentUserToDisk(
onSuccess: {
// start recursive call, and in the next iteration this shouldn't
// end in onError of observeCurrentUserFromDisk.
// Though, if it's a possibility, you might want to limit
// the number of tries before failing
fetchCurrentUser(onSuccess: onSuccess)
},
onError: onError)
}
}
您可以使用 fetchCurrentUser
的完成处理程序来执行您需要的操作:
fetchCurrentUser(
onSuccess: { user in
self.emailLabel.text = user.email
if let profileUrl = URL(string: user.profileImageUrl!) {
self.profileImageView.sd_setImage(with: profileUrl)
}
},
onError: {
// handle the error case
})
这是我的代码
fetchCurrentUser() 函数首先调用 'observeCurrentUserFromDisk',如果它不在磁盘上则调用 'observeCurrentUserToDisk'(firebase),我如何在调用 [=17= 后再次调用 'observeCurrentUserFromDisk' ] 到 return 从 'observeCurrentUserFromDisk' 到第一个使用闭包调用 'observeCurrentUserFromDisk' 的函数(fetchCurrentUser)的结果,试图维护 D.R.Y 谢谢。
func fetchCurrentUser() {
// I don't want to call these two functions each time
Api.User.observeCurrentUserFromDisk(onSuccess: { (user) in
self.emailLabel.text = user.email
if let profileUrl = URL(string: user.profileImageUrl!) {
self.profileImageView.sd_setImage(with: profileUrl)
}
}) {
Api.User.observeCurrentUserToDisk(onSuccess: {
self.fetchCurrentUser()
}) { (error) in
ProgressHUD.showError(error)
}
}
}
func observeCurrentUserToDisk(onSuccess: @escaping () -> Void, onError: @escaping (_ errorMessage: String) -> Void) {
guard let currentUser = Api.User.CURRENT_USER?.uid else { return }
Config.REF_USERS.child(currentUser).observeSingleEvent(of: .value, with: { (snapshot) in
if let dict = snapshot.value as? [String: Any] {
let user = UserModel.transformUser(dict: dict, key: snapshot.key)
Api.Realm.writeUserToDisk(user)
onSuccess()
}
})
}
func observeCurrentUserFromDisk(onSuccess: @escaping (RealmUser) -> Void, onError: @escaping () -> Void) {
guard let uid = Api.User.CURRENT_USER?.uid else { return }
let predicate = NSPredicate(format: "id = %@", uid)
var users: Results<RealmUser>!
users = usersOnDisk.objects(RealmUser.self).filter(predicate)
if let index = users.index(matching: predicate) {
let user = users[index]
onSuccess(user)
} else {
onError()
}
}
您可以在 vars 中捕获您的闭包,然后在另一个闭包中引用它。例如:
var onFetch = { a in print(a) }
var saveUsers = { b in
if b {
onFetch()
}
}
在其自身内部调用函数没有问题 - 这称为递归,只要您有停止条件,这就不会是无限的。
在您的情况下,您正在确定需要执行的某个地方 observeCurrentUserToDisk
- 据推测,如果您不这样做,那么该功能就会完成。那就是你的停止条件。
此外,由于 fetchCurrentUser
是异步的,您将调用它并需要对其结果进行操作,因此向其添加完成(onSuccess
和 onError
)处理程序作为嗯。
大致思路如下:
func fetchCurrentUser(onSuccess: @escaping (RealmUser) -> Void,
onError: @escaping (String) -> Void) {
observeCurrentUserFromDisk(
onSuccess: onSuccess,
onError: {
observeCurrentUserToDisk(
onSuccess: {
// start recursive call, and in the next iteration this shouldn't
// end in onError of observeCurrentUserFromDisk.
// Though, if it's a possibility, you might want to limit
// the number of tries before failing
fetchCurrentUser(onSuccess: onSuccess)
},
onError: onError)
}
}
您可以使用 fetchCurrentUser
的完成处理程序来执行您需要的操作:
fetchCurrentUser(
onSuccess: { user in
self.emailLabel.text = user.email
if let profileUrl = URL(string: user.profileImageUrl!) {
self.profileImageView.sd_setImage(with: profileUrl)
}
},
onError: {
// handle the error case
})