Reputation: 3060
I have a UIViewController class where I'm trying to populate the data into my UICollectionView
// HomeController.swift
import UIKit
import SwiftyJSON
class HomeController: UICollectionViewController,
UICollectionViewDelegateFlowLayout, TaskServiceManagerDelegate {
func didUpdate(sender: TaskServiceManager) {
self.collectionView?.reloadData()
}
var taskList:JSON? = nil
override func viewDidLoad() {
super.viewDidLoad()
// getting the task list to populate the UICollectionView
let taskServiceManager:TaskServiceManager = TaskServiceManager()
taskList = taskServiceManager.getAllTasks()
collectionView?.dataSource = self;
collectionView?.delegate = self;
navigationItem.title = "Test"
collectionView?.backgroundColor = UIColor.lightGray
collectionView?.register(QuestionCell.self, forCellWithReuseIdentifier: "cellId")
}
override func viewDidAppear(_ animated: Bool) {
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// getting the task list to populate the UICollectionView
let taskServiceManager:TaskServiceManager = TaskServiceManager()
taskList = taskServiceManager.getAllTasks()
collectionView?.dataSource = self;
collectionView?.delegate = self;
}
override func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return (taskList?.count)!
}
}
I have another class TaskServiceManager where I'm making a REST api call and getting the data.
// TaskServiceManager.swift
import UIKit
import Alamofire
import SwiftyJSON
class TaskServiceManager : NSObject{
var delegate: TaskServiceManagerDelegate?
func getAllTasks() -> JSON {
var swiftyJsonVar: JSON = []
Alamofire.request(url, headers: getHeaders()).responseJSON { (responseData) -> Void in
print("Status Code: \(responseData.response?.statusCode)")
if((responseData.result.value) != nil) {
swiftyJsonVar = JSON(responseData.result.value!)
print(swiftyJsonVar)
print("Task List Count: \(swiftyJsonVar.array?.count)")
}
}
return swiftyJsonVar
}
}
protocol TaskServiceManagerDelegate {
func didUpdate(sender: TaskServiceManager)
}
The taskList?.count in the numberOfItemsInSection returns 0 even though I get a success from the api response with count as 6. Why is it so?
How do I refer the HomeController from the TaskServiceManager class?
Also, why does my TaskServiceManagerDelegate doesn't reflect the UICollectionView?
Upvotes: 1
Views: 859
Reputation: 4891
No need of delegate
to fetch data from API, completion handlers
are better choice for this kind of task.
Make this change in your function :
func getAllTasks(completion:@escaping(JSON)->()) {
var swiftyJsonVar: JSON = []
Alamofire.request(url, headers: getHeaders()).responseJSON { (responseData) -> Void in
print("Status Code: \(responseData.response?.statusCode)")
if((responseData.result.value) != nil) {
swiftyJsonVar = JSON(responseData.result.value!)
print(swiftyJsonVar)
print("Task List Count: \(swiftyJsonVar.array?.count)")
completion(swiftyJsonVar)
}
}
}
To call it from your another class:
TaskServiceManager().getAllTasks { (tasks) in
print("tasks : \(tasks)")
//here reload your collection view
}
You are doing everything right except return
statement. API calls are asynchronous
and so your return statement is getting called before your network request is over. You need a completion callback
to return the data when you get response.
And your delegation is incomplete. If you want to the delegation method then you need add these lines.
In viewDidLoad() after :
let taskServiceManager:TaskServiceManager = TaskServiceManager()
you need to assign your HomeController's instance to delegate variable of TaskServiceManager class
taskServiceManager.delegate = self
And in TaskServiceManager class when you get data from server you need to pass it using your delegate method, I don't know why you are trying to pass instance of TaskServiceManager in delegate method ?
protocol TaskServiceManagerDelegate {
func didUpdate(sender: TaskServiceManager) // Why ?
// func didUpdate(serverData: JSON) // Maybe this is what you need
}
To call delegate method one last step without any return statement :
func getAllTasks() {
var swiftyJsonVar: JSON = []
Alamofire.request(url, headers: getHeaders()).responseJSON { (responseData) -> Void in
print("Status Code: \(responseData.response?.statusCode)")
if((responseData.result.value) != nil) {
swiftyJsonVar = JSON(responseData.result.value!)
print(swiftyJsonVar)
print("Task List Count: \(swiftyJsonVar.array?.count)")
delegate.didUpdate(serverData: swiftyJsonVar) // this is to pass data
}
}
}
Now this function in your HomeController will be called (I changed the data to serverData instead of TaskServiceManager) :
func didUpdate(serverData: dataFormServer) {
print("dataFormServer : \(dataFormServer)")
self.collectionView?.reloadData()
}
Upvotes: 4
Reputation: 605
you forgot to call the didUpdate function after successful API call. You need to reload the collectionView after the successful API call. The reason is API calls are asynchronous in nature
Upvotes: 0