[英]Updating a UILabel from an escaping closure doesn't take effect immedialtely
基本上:
在 viewDidAppear 中:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
myFunction(closure)
}
closure
類型為@escaping (_ success: Bool) -> Void
在關閉代碼中:
print("Change myLabel.text")
self?.myLabel.text = "New Title"
print("myLabel.text changed")
"Show myLabel.text"
和"myLabel.text changed"
會在 VC 出現后立即打印,但myLabel
的文本會在幾秒鍾(大約 10 秒)后發生變化。
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)
}
}
實際代碼的靈感來自這里:
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 :
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)
}
}
檢索聯系人:
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)
}
}
我在這里缺少什么?
你是說:
print("Change myLabel.text")
self?.myLabel.text = "New Title"
print("myLabel.text changed")
而且您抱怨打印消息出現在控制台中,但標簽直到很久以后才改變。
這種延遲幾乎總是由線程問題引起的。 您沒有顯示 MyFunction 並且沒有顯示整個closure
,因此無法詳細幫助您,但可能是您在不知道自己在做什么的情況下搞亂了后台線程,並且您不小心設置了myLabel.text
在后台線程上,這是一個很大的禁忌。 您必須跳出主線程才能以任何方式觸摸界面:
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.