简体   繁体   English

从转义闭包更新 UILabel 不会立即生效

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM