簡體   English   中英

從轉義閉包更新 UILabel 不會立即生效

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM