Search code examples
objective-cxcodeswiftxcode6ios9

How to populate array and view it's data at the same time - Swift - IOS9


I am trying to retrieve data from an online database, and I do that successfully; However, after retrieving the data from the database I would like to store it in an array and then populate a listview and a mapview with it's data, but there is a problem, I am able to load the data and store it and view it, however the problem is that everytime the app loads no information appears until I go to another scene and go back, because I am populating the array though the AppDelegate. However, if I populate it through the viewdidload I get duplicate items in my table view.

Here is my code:

Approach number 1, which leads to duplicates

StoreViewController.swift

class StoreViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate, UITextFieldDelegate, UITableViewDataSource, UITableViewDelegate, StoresModelProtocoal {
    override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    drawForm()
    setUpMap()
    self.hideKeyboardWhenTappedAround()
    getCurrentLocation()

    let hideStoreDetail: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.hideStoreDetails))
    Map.addGestureRecognizer(hideStoreDetail)

    //Create a nib for the custom cell and use it in the table
    let nib = UINib(nibName: "CustomStoreCell", bundle: nil)
    StoresListTable.registerNib(nib, forCellReuseIdentifier: "customStoreCell")

    let storesModel = StoresModel()
    storesModel.delegate = self
    storesModel.downloadItems()

}

    func itemsDownloaded(items: NSArray) {
    print("Items downloaded")
    for item in items
    {
        if let s = item as? Store
        {
            print(s.Address)
            Globals.unsortedStoresList += [s]
            Map.addAnnotation(s.Annotation)
            do_table_refresh()
        }
    }
}

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return Globals.unsortedStoresList.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell:CustomStoreCell = self.StoresListTable.dequeueReusableCellWithIdentifier("customStoreCell") as! CustomStoreCell

    let s = Globals.unsortedStoresList[indexPath.row]

    cell.loadItem(s.Name, StoreAddress: s.Address, StoreHoursOfOperation: s.HoursOfOperation, StoreDistanceFromCurrentLocation: String(s.DistanceFromCurrentLocation))

    return cell

}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    //tableView.deselectRowAtIndexPath(indexPath, animated: true)
    let s = Globals.unsortedStoresList[indexPath.row]

    print(s.Name)
    print(s.Address)
    print(s.HoursOfOperation)
    print(s.DistanceFromCurrentLocation)

    //print("You selected cell #\(indexPath.row)!")
}

func do_table_refresh()
{
    dispatch_async(dispatch_get_main_queue(), {
        self.StoresListTable.reloadData()
        return
    })
}

I know this one duplicates the items because everytime the view is loaded it re-downloads all the data again; therefore, I tried looking for a better way and then I thought about doing the downloading process in my AppDelegate and then just write couple functions that take data from the array and display it, but the problem here is that the data would be displayed on the TableView right away without duplicates but it won't be displayed on the mapview at first run, instead I have to go to another scene and go back in order for the data to be displayed on the map.

Approach number 2

StoreViewController.swift

class StoreViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate, UITextFieldDelegate, UITableViewDataSource, UITableViewDelegate {
    override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    drawForm()
    setUpMap()
    self.hideKeyboardWhenTappedAround()
    getCurrentLocation()

    let hideStoreDetail: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.hideStoreDetails))
    Map.addGestureRecognizer(hideStoreDetail)

    //Create a nib for the custom cell and use it in the table
    let nib = UINib(nibName: "CustomStoreCell", bundle: nil)
    StoresListTable.registerNib(nib, forCellReuseIdentifier: "customStoreCell")

     loadMapAnnotations()

}

    func loadMapAnnotations(){
    for item in Globals.unsortedStoresList
    {
        Map.addAnnotation(item.Annotation)
        do_table_refresh()

    }
}

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return Globals.unsortedStoresList.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell:CustomStoreCell = self.StoresListTable.dequeueReusableCellWithIdentifier("customStoreCell") as! CustomStoreCell

    let s = Globals.unsortedStoresList[indexPath.row]

    cell.loadItem(s.Name, StoreAddress: s.Address, StoreHoursOfOperation: s.HoursOfOperation, StoreDistanceFromCurrentLocation: String(s.DistanceFromCurrentLocation))

    return cell

}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    //tableView.deselectRowAtIndexPath(indexPath, animated: true)
    let s = Globals.unsortedStoresList[indexPath.row]

    print(s.Name)
    print(s.Address)
    print(s.HoursOfOperation)
    print(s.DistanceFromCurrentLocation)

    //print("You selected cell #\(indexPath.row)!")
}

func do_table_refresh()
{
    dispatch_async(dispatch_get_main_queue(), {
        self.StoresListTable.reloadData()
        return
    })
}

AppDelegate.swift

class AppDelegate: UIResponder, UIApplicationDelegate, StoresModelProtocoal {

var window: UIWindow?

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.

    let storesModel = StoresModel()
    storesModel.delegate = self
    storesModel.downloadItems()

    return true
}

//////////////////////////////////////
//Delegates
//////////////////////////////////////
func itemsDownloaded(items: NSArray) {
    print("Items downloaded")
    for item in items
    {
        if let s = item as? Store
        {
            print(s.Address)
            Globals.unsortedStoresList += [s]
            //Map.addAnnotation(s.Annotation)
        }
    }
}

Any help would be appreciated, Thanks in advance.


Solution

  • I was able to find a temporarily solution to the problem I modified StoreViewController.swift to this, if anyone is having a similar problem.

    class StoreViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate, UITextFieldDelegate, UITableViewDataSource, UITableViewDelegate, StoresModelProtocoal {
    override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    drawForm()
    setUpMap()
    self.hideKeyboardWhenTappedAround()
    getCurrentLocation()
    
    let hideStoreDetail: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.hideStoreDetails))
    Map.addGestureRecognizer(hideStoreDetail)
    
    //Create a nib for the custom cell and use it in the table
    let nib = UINib(nibName: "CustomStoreCell", bundle: nil)
    StoresListTable.registerNib(nib, forCellReuseIdentifier: "customStoreCell")
    
    Globals.unsortedStoresList.removeAll()  //I added this line of code to remove the old list
    let storesModel = StoresModel()
    storesModel.delegate = self
    storesModel.downloadItems()
    
    }
    
    func itemsDownloaded(items: NSArray) {
       print("Items downloaded")
       for item in items
       {
           if let s = item as? Store
           {
               print(s.Address)
               Globals.unsortedStoresList += [s]
               Map.addAnnotation(s.Annotation)
    
           }
        }
        do_table_refresh()
    }
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return Globals.unsortedStoresList.count
    }
    
     func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell:CustomStoreCell = self.StoresListTable.dequeueReusableCellWithIdentifier("customStoreCell") as! CustomStoreCell
    
    let s = Globals.unsortedStoresList[indexPath.row]
    
    cell.loadItem(s.Name, StoreAddress: s.Address, StoreHoursOfOperation: s.HoursOfOperation, StoreDistanceFromCurrentLocation: String(s.DistanceFromCurrentLocation))
    
    return cell
    
    }
    
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    //tableView.deselectRowAtIndexPath(indexPath, animated: true)
    let s = Globals.unsortedStoresList[indexPath.row]
    
    print(s.Name)
    print(s.Address)
    print(s.HoursOfOperation)
    print(s.DistanceFromCurrentLocation)
    
    //print("You selected cell #\(indexPath.row)!")
    }
    
    func do_table_refresh()
    {
        dispatch_async(dispatch_get_main_queue(), {
           self.StoresListTable.reloadData()
           return
        })
     }