0

My issue: I have reason to believe that initializing a UIImage from Data gums up my main thread a bit. It isn't terrible, takes a fraction of a second to complete, but it is noticeable as it makes my UI seem a bit glitchy.

What I'm doing: I have a UIPageViewController. One of the UIViewControllers presented by said UIPageViewController is making use of this UIImage(data: Data) initializer in its viewDidLoad method:

class PageViewController: UIPageViewController {

    var pages: [UIViewController] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        loadPages()
    }

    ...

    func loadPages() {

        let vc1 = storyboard!.instantiateViewController(withIdentifier: "VC1") as! ViewController1
        let vc2 = storyboard!.instantiateViewController(withIdentifier: "VC2") as! ViewController2
        let vc3 = storyboard!.instantiateViewController(withIdentifier: "VC3") as! ViewController3
        pages.append(userProfilePreviewVC)
        pages.append(meetVC)
        pages.append(chatLogVC)

        setViewControllers([pages[1]], direction: UIPageViewController.NavigationDirection.forward, animated: false, completion: nil)
    }
}

extension PageViewController: UIPageViewControllerDelegate, UIPageViewControllerDataSource {
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {

        switch currentIndex {
        case 1:
            return pages[0]
        case 2:
            return pages[1]
        default:
            return nil
        }
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        switch currentIndex {
        case 0:
            return pages[1]
        case 1:
            return pages[2]
        default:
            return nil
        }
    }
}

Here is where the issue lies:

class ViewController1: UIViewController {

    @IBOutlet var profilePicButton: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
        let userPhotos = UserDefaults.standard.array(forKey: "UserPhotos") as? [Data] ?? []
        if userPhotos.count != 0 {
            self.profilePicButton.setImage(UIImage(data: userPhotos.first ?? Data()) ?? UIImage(named: "profile")!, for: .normal)
        } else {
            self.profilePicButton.setImage(UIImage(named: "profile"), for: .normal)
        }
    }
}

My question: When swiping on my PageViewController to the page that is displaying ViewController1, the main thread seems to gum up as it takes a fraction of a second to actually load this ViewController1. This is in contrast to other view controllers that are instantly ready to go when swiping to them. Similarly, when the user doesn't have any stored profile picture data, a placeholder image that is from my assets.xcassets folder takes its place. There is no lag when presenting this image. My question is: should I use UIImage(data: Data) on a background thread and update the button image when the UIImage has initialized?

David Chopin
  • 2,780
  • 2
  • 19
  • 40
  • 1
    You should not use UserDefaults to store image data – Leo Dabus Oct 28 '19 at 08:41
  • create a folder and save your images straight to disk. You can save their names and location in user defaults if needed – Leo Dabus Oct 28 '19 at 11:42
  • I apologize, earlier I read your comment as "You should use UserDefaults to store image data". Is there a reason as to why its a bad idea to store image data in `UserDefaults`? – David Chopin Oct 28 '19 at 19:41
  • Could you tell what's the lenght/size of `userPhotos`? I wouldn't use UserDefaults for that. Maybe a "path", but definitely not in UserDefaults, which might be cause for the issue. – Larme Oct 29 '19 at 11:56
  • It stores an array or up to 6, non-compressed user images. This can be from their camera roll or camera, so there’s no limit to how large the images could be. When pushed to the backend, the images get compressed, but I’m not compressing images when storing them on the device. – David Chopin Oct 29 '19 at 15:15
  • I ended up going with Leo's suggestion and did this little tutorial https://iswiftdeveloper.wordpress.com/2018/01/30/save-and-get-image-from-document-directory-in-swift/ to convert data stored on the users' `UserDefaults` to storing the data as files in the document directory. This seems to have had a positive impact on performance. – David Chopin Nov 01 '19 at 17:35

0 Answers0