Search code examples
iosswiftdispatch-queue

How to load contact image in background?


I'm developing an app using Contact Book. I am displaying the call history from API and when I display the history-data, I check if the contact is available in the contact book or not. If it is available then I display the contacts name and image. I am doing this process in the background but sometimes, the tableview stuck and not giving any kind of response. I'm using the following code for doing the process above:

for i in (0..<arrdata.count-1)
{
    self.count = self.count + 1
    let dict_data = arrdata.value(forKey: String(format: "%d", arguments: [i])) as! NSDictionary

    let dict = NSMutableDictionary()
    dict.setValue(dict_data["callstart"], forKey: "callstart")
    dict.setValue(dict_data["notes"], forKey: "notes")
    dict.setValue(dict_data["debit"], forKey: "debit")
    dict.setValue(dict_data["pattern"], forKey: "pattern")
    dict.setValue(dict_data["calltype"], forKey: "calltype")
    dict.setValue(dict_data["billseconds"], forKey: "billseconds")
    dict.setValue(dict_data["disposition"], forKey: "disposition")
    dict.setValue(dict_data["callednum"], forKey: "callnumber")

    DispatchQueue.global(qos: .background).async(execute:
    { () -> Void in
        let searchContact = Constants.appDelegate.searchForContactUsingPhoneNumber(phoneNumber: dict_data["callednum"] as? String) as [ContactEntry]
        if searchContact.count == 1
        {
            for contact in searchContact
            {
                dict.setValue(contact.name, forKey: "callednum")
                dict.setValue(contact, forKey: "historycontact")
                if contact.image == nil
                {
                    dict.setValue(nil, forKey: "contactimage")
                }
                else
                {
                    let new_image = contact.image?.scaleUIImageToSize( image: contact.image!, size: CGSize(width:250,height:250))
                    let imgdata = new_image?.jpeg(.lowest)
                    dict.setValue(imgdata, forKey: "contactimage")


                }
            }
        }
        else
        {
            dict.setValue(nil, forKey: "historycontact")
            dict.setValue(dict_data["callednum"], forKey: "callednum")
            dict.setValue(nil, forKey: "contactimage")

        }
    })
    dict.setValue(nil, forKey: "historycontact")
    dict.setValue(dict_data["callednum"], forKey: "callednum")
    dict.setValue(nil, forKey: "contactimage")
    dict.setValue(dict_data["callerid"], forKey: "callerid")
    self.arrHistory.append(dict)
}

DispatchQueue.main.async
{
    self.tblview.reloadData()
}

In background queue I checked contact available or not.

I required contact search in background and also set data in back ground and API call on main thread.

If any one have solution for above issue then please help me.

Thank you.


Solution

  • I can see a few potential issues here. Your grabbing a background thread in a for loop which (depending on the data) could take up a lot of threads! This could be what is causing your app to become unresponsive. I'm not entirely sure what your trying to achieve either as when your background thread completes you're not then reloading the tableview.

    From what I can tell you want to dispatch into a background queue right at the beginning, perform all the processing then dispatch back onto the main thread at the end to update the tableview. Something like:

    DispatchQueue.global(qos: .background).async(execute: { () -> Void in
        for i in (0..<arrdata.count-1)
        {
            self.count = self.count + 1
            let dict_data = arrdata.value(forKey: String(format: "%d", arguments: [i])) as! NSDictionary
    
            let dict = NSMutableDictionary()
            dict.setValue(dict_data["callstart"], forKey: "callstart")
            dict.setValue(dict_data["notes"], forKey: "notes")
            dict.setValue(dict_data["debit"], forKey: "debit")
            dict.setValue(dict_data["pattern"], forKey: "pattern")
            dict.setValue(dict_data["calltype"], forKey: "calltype")
            dict.setValue(dict_data["billseconds"], forKey: "billseconds")
            dict.setValue(dict_data["disposition"], forKey: "disposition")
            dict.setValue(dict_data["callednum"], forKey: "callnumber")
    
    
            let searchContact = Constants.appDelegate.searchForContactUsingPhoneNumber(phoneNumber: dict_data["callednum"] as? String) as [ContactEntry]
            if searchContact.count == 1
            {
                for contact in searchContact
                {
                    dict.setValue(contact.name, forKey: "callednum")
                    dict.setValue(contact, forKey: "historycontact")
                    if contact.image == nil
                    {
                        dict.setValue(nil, forKey: "contactimage")
                    }
                    else
                    {
                        let new_image = contact.image?.scaleUIImageToSize( image: contact.image!, size: CGSize(width:250,height:250))
                        let imgdata = new_image?.jpeg(.lowest)
                        dict.setValue(imgdata, forKey: "contactimage")
    
    
                    }
                }
            }
            else
            {
                dict.setValue(nil, forKey: "historycontact")
                dict.setValue(dict_data["callednum"], forKey: "callednum")
                dict.setValue(nil, forKey: "contactimage")
    
            }
            dict.setValue(nil, forKey: "historycontact")
            dict.setValue(dict_data["callednum"], forKey: "callednum")
            dict.setValue(nil, forKey: "contactimage")
            dict.setValue(dict_data["callerid"], forKey: "callerid")
            self.arrHistory.append(dict)
        }
    
        DispatchQueue.main.async {
            self.tblview.reloadData()
        }
    })