[英]Updating a UILabel from an escaping closure doesn't take effect immedialtely
Basically :基本上:
In viewDidAppear:在 viewDidAppear 中:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
myFunction(closure)
}
closure
is of type @escaping (_ success: Bool) -> Void
closure
类型为@escaping (_ success: Bool) -> Void
In the closure code:在关闭代码中:
print("Change myLabel.text")
self?.myLabel.text = "New Title"
print("myLabel.text changed")
"Show myLabel.text"
and "myLabel.text changed"
are printed as soon as the VC appears, but the text in myLabel
changes after several seconds (around 10 seconds). "Show myLabel.text"
和"myLabel.text changed"
会在 VC 出现后立即打印,但myLabel
的文本会在几秒钟(大约 10 秒)后发生变化。
myLabel
is created programmatically as seen below: myLabel
以编程方式创建,如下所示:
class MyClass : UIViewController {
...
var myLabel: UILabel!
var contacts = [ContactEntry]()
...
override func viewWillLayoutSubviews() {
myLabel = UILabel()
myLabel.text = "Original title"
myLabel.frame = CGRect(x: 10, y: 10, width: 100, height: 400)
self.view.addSubview(myLabel)
}
}
The actual code is inspired from here :实际代码的灵感来自这里:
viewDidAppear : viewDidAppear :
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
requestAccessToContacts { [weak self] (success) in
if success {
self?.retrieveContacts(completion: { (success, contacts) in
self?.tableView.isHidden = false
self?.myLabel.isHidden = true
if success && (contacts?.count)! > 0 {
self?.contacts = contacts!
self?.myLabel.text = ""
self?.myLabel.isHidden = true
self?.tableView.reloadData()
} else if (contacts?.count)! == 0 {
self?.myLabel.isHidden = false
self?.myLabel.text = "No contacts found"
} else {{
self?.myLabel.isHidden = false
self?.myLabel.text = "Error loading contacts"
}
})
} else {
print("Change label text")
self?.myLabel.attributedText = "Enable access to contacts by going to\nSettings>Privacy>Contacts>MyApp"
self?.myLabel.isHidden = false
print("Label text changed")
}
}
}
requestAccessToContacts : requestAccessToContacts :
func requestAccessToContacts(completion: @escaping (_ success: Bool) -> Void) {
let authorizationStatus = CNContactStore.authorizationStatus(for: CNEntityType.contacts)
switch authorizationStatus {
case .authorized:
// authorized previously
completion(true)
case .denied, .notDetermined:
// needs to ask for authorization
self.contactStore.requestAccess(for: CNEntityType.contacts, completionHandler: { (accessGranted, error) -> Void in
completion(accessGranted)
})
default:
// not authorized.
completion(false)
}
}
retrieveContacts :检索联系人:
func retrieveContacts(completion: (_ success: Bool, _ contacts: [ContactEntry]?) -> Void) {
var contacts = [ContactEntry]()
do {
let contactsFetchRequest = CNContactFetchRequest(keysToFetch: [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactImageDataKey, CNContactImageDataAvailableKey, CNContactPhoneNumbersKey, CNContactEmailAddressesKey].map {$0 as CNKeyDescriptor})
try contactStore.enumerateContacts(with: contactsFetchRequest, usingBlock: { (cnContact, error) in
if let contact = ContactEntry(cnContact: cnContact) { contacts.append(contact) }
})
completion(true, contacts)
} catch {
completion(false, nil)
}
}
What am I missing here?我在这里缺少什么?
You are saying:你是说:
print("Change myLabel.text")
self?.myLabel.text = "New Title"
print("myLabel.text changed")
And you are complaining that the print messages appear in the console but the label doesn't change until much later.而且您抱怨打印消息出现在控制台中,但标签直到很久以后才改变。
This sort of delay is nearly always caused by a threading issue.这种延迟几乎总是由线程问题引起的。 You do not show MyFunction and you do not show the entirety of closure
, so it's impossible to help you in detail, but the likelihood is that you are messing around with background threads without knowing what you are doing, and that you have accidentally set myLabel.text
on a background thread, which is a big no-no.您没有显示 MyFunction 并且没有显示整个closure
,因此无法详细帮助您,但可能是您在不知道自己在做什么的情况下搞乱了后台线程,并且您不小心设置了myLabel.text
在后台线程上,这是一个很大的禁忌。 You must step out to the main thread in order to touch the interface in any way:您必须跳出主线程才能以任何方式触摸界面:
DispatchQueue.main.async {
print("Change myLabel.text")
self?.myLabel.text = "New Title"
print("myLabel.text changed")
// ... and everything else that touches the interface
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.