0

I'm trying to develop an IOS application using Swift. The application is a simple app which retrieves data from database and display.

The problem is I cannot manage to display data which is retrieved from database via REST server... I've asked similar question here.

As I stated there, I tried DispatchQueue.main.async to execute fetching and reloadData(). but it failed.

When I replace async to sync, it works partially (first screen loading time, it doesn't display but after then it display items).

Can you guys help me get through this?

The followings are my class code

import UIKit

class OrderViewController:UIViewController {

    let cartView:UIView = {
        let tableView = UIView()
        tableView.backgroundColor = UIColor.gray
        tableView.translatesAutoresizingMaskIntoConstraints = false
        return tableView
    }()

    var itemView:UIView = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()
        edgesForExtendedLayout = []
        view.backgroundColor = UIColor.white
        itemView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(itemView)
        view.addSubview(cartView)
        setupItemView()
        setupCartView()
        let layout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsets(top: 20, left: 20, bottom: 10, right: 20)
        //let viewFrame = CGRect(x: view.bounds.minX, y: view.bounds.minY, width: view.bounds.width*2/3, height: view.bounds.height)
        let collectionViewController = ItemcollectionViewController(collectionViewLayout: layout)

        // get rid of black bar underneath navBar
        self.navigationController?.navigationBar.shadowImage = UIImage()
        self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)

        itemView.addSubview(collectionViewController.view)
    }

    private func setupItemView(){
        itemView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        itemView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        itemView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 2/3).isActive = true
        itemView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true
    }

    private func setupCartView() {
        cartView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        cartView.leftAnchor.constraint(equalTo: itemView.rightAnchor).isActive = true
        cartView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1/3).isActive = true
        cartView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true
    }
}

Class where is fetching data:

    import UIKit
import Alamofire
import SwiftyJSON

class ItemcollectionViewController:UICollectionViewController, UICollectionViewDelegateFlowLayout {

    let dateFormat = "yyyy-MM-dd"
    let cellId = "CellId"
    //var categories: [Category]?
    var categories = [Category]()
    let viewOptionVar:ViewOptionBar = {
        let vOV = ViewOptionBar()
        vOV.translatesAutoresizingMaskIntoConstraints = false
        return vOV
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView?.backgroundColor = UIColor.white
        collectionView?.register(ItemCell.self, forCellWithReuseIdentifier: cellId)
        collectionView?.contentInset = UIEdgeInsetsMake(50, 0, self.view.frame.height, self.view.frame.width)
        collectionView?.scrollIndicatorInsets = UIEdgeInsetsMake(50, 0, 0, self.view.frame.width)
        collectionView?.dataSource = self
        collectionView?.delegate = self
        DispatchQueue.global().async {
            Alamofire.request("http://localhost:8080/category/all").responseJSON { (responseData) -> Void in
                switch responseData.result{
                case .success:
                    if let returnedCategories = responseData.result.value as! NSArray? {
                        for element in returnedCategories {
                            let categoryDictionary = element as! NSDictionary
                            let category = Category()
                            category.categoryId = categoryDictionary["categoryId"] as? String
                            category.categoryName = categoryDictionary["categoryName"] as? String
                            category.categoryDescription = categoryDictionary["categoryDescription"] as? String
                            let categoryRegisteredDateString = categoryDictionary["categoryRegisteredDate"] as? String
                            let df = DateFormatter()
                            df.dateFormat = self.dateFormat
                            let categoryRegisteredDate = df.date(from: categoryRegisteredDateString!)!
                            category.categoryRegisteredDate = categoryRegisteredDate
                            self.categories.append(category)
                        }
                        print("After parsing \(self.categories)")
                    }
                case .failure(let error):
                    print("Error while fetching Categories: \(error)")
                }
            }
            DispatchQueue.main.async {
                self.collectionView?.reloadData()
            }
        }
        print(self.categories)
    }

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return self.categories.count 
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! ItemCell
        cell.category = categories[indexPath.item]
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: 111, height: 111)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }

    private func setupViweOptionBar() {
        view.addSubview(viewOptionVar)
        view.addConstraintsWithFormat(format: "H:|[v0]|", views: viewOptionVar)
        view.addConstraintsWithFormat(format: "V:|[v0(50)]", views: viewOptionVar)
    }
}
Community
  • 1
  • 1
J.GS.Han
  • 117
  • 1
  • 9

2 Answers2

0

Try this.

var categories = [Category](){
    didSet {
        self.collectionView?.reloadData()
    }
}

Get rid of the

DispatchQueue.main.async {
            self.collectionView?.reloadData()
}
0

Your:

DispatchQueue.main.async {
                self.collectionView?.reloadData()
            }

Seems to be outside of the Alamofire request. Move it inside case .success:

  • @J.GS.Han I jujst looked at your code again, I dont code in swift but you are adding a UICollectionViewController inside a UIViewController. Not sure why you do this, You don't even seem to be adding it correctly, you need to add it as a childViewController http://stackoverflow.com/questions/26599858/how-to-properly-add-child-view-controller-in-ios-8-with-swift However, before trying out the collectionView with response from Alamofire. try it out with some mockup cells and see if that shows at all. If what I wrote didnt fix the problem, it's hard to see where the problem lies without debugging –  Mar 05 '17 at 09:42