Search code examples
iosobjective-cswiftuicollectionviewviewwillappear

Loading data from API pattern issue


I am building an app that populates data in a collectionView. The data come from API calls. When the screen first loads I get the products and store them locally in my ViewController.

My question is when should I get the products again and how to handle screen changing. My data will change when the app is running (sensitive attributes like prices) , but I don't find ideal solution to make the API call each time viewWillAppear is being called.

Can anybody please tell me what is the best pattern to handle this situation. My first though was to check if [CustomObject].isEmpty on viewWillAppear and then make the call. Including a timer that check again every 10-15 minutes for example.

Thank you for your input.


Solution

  • There is no set pattern but it is advisable not to send repeated network requests to increase energy efficiency (link). You can check the time interval in ViewWillApear and send the network requests after certain gap or can use timer to send requests at time intervals. First method would be better as it sends request only when user is on that screen. You can try following code snippet to get the idea

    class ViewController: UIViewController {
    
        let time = "startTime"
        let collectionView: UICollectionView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
        }
    
        override func viewWillAppear(animated: Bool) {
            super.viewWillAppear(animated)
            update()
        }
    
        private func update() {
            if let startDateTime = NSUserDefaults.standardUserDefaults().objectForKey(time) as? NSDate {
                let interval = NSDate().timeIntervalSinceDate(startDateTime)
                let elapsedTime = Int(interval)
                if elapsedTime >= 3600 {
                    makeNetworkRequest()
                    NSUserDefaults.standardUserDefaults().setObject(startDateTime, forKey: time)
                }
            } else {
                makeNetworkRequest()
                NSUserDefaults.standardUserDefaults().setObject(NSDate(), forKey: time)
            }
        }
    
        func makeNetworkRequest() {
    
            //Network Request to fetch data and update collectionView
            let urlPath = "http://MyServer.com/api/data.json"
            guard let endpoint = NSURL(string: urlPath) else {
                print("Error creating endpoint")
                return
            }
            let request = NSMutableURLRequest(URL:endpoint)
            NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) in
                do {
                    guard let data = data else {
                        return
                    }
                    guard let json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? [String: AnyObject] else {
                       print("Error in json parsing")
                       return
                    }
                    self.collectionView.reloadData()
                } catch let error as NSError {
                    print(error.debugDescription)
                }
            }.resume()
        }