I came into something I would assume is an easy enough problem but somehow I can't think of any way to solve it. It's simply converting an NSArray to an Array, and I think I've done a good job here with this code:
func getTrainingSubCategories(completion: #escaping(Result<[TrainingSubCategory], GetError>) -> Void){
let dataTask = URLSession.shared.dataTask(with: resourceURL){data, _, _ in
guard let jsonData = data else {
completion(.failure(.trainingCategoriesNoDataAvailable))
return
}
do{
let parsedData = try JSONSerialization.jsonObject(with: jsonData) as! [String: Any]
for (key, value) in parsedData {
if key == "categories" {
if let categoriesDictionary: [[String: Any]] = value as? [[String: Any]]{
for categoryDictionary in categoriesDictionary{
for (key, value) in categoryDictionary{
if key == "sub_categories" {
print("1st Type => \(type(of: value)) Value => \(value)")
print("2nd Type => \(type(of: value as? Array<TrainingSubCategory>)) Value => \(value as? Array<TrainingSubCategory>)")
// guard let subCategoryValue = value as? Array<TrainingSubCategory> else{
// fatalError("Error in casting value to array of trainingsubcategory")
// }
}
}
}
}
}
}
}catch {
completion(.failure(.trainingSubCategoriesCannotProcessData))
}
}
dataTask.resume()
}
but the console would log otherwise:
1st Value => (
{
"category_id" = 1;
"company_id" = 50;
"created_at" = "2019-11-07 00:58:37";
"deleted_at" = "<null>";
id = 1;
name = Advertisement;
"updated_at" = "2019-11-07 00:58:37";
},
{
"category_id" = 1;
"company_id" = 50;
"created_at" = "<null>";
"deleted_at" = "<null>";
id = 3;
name = Sales;
"updated_at" = "2019-11-10 23:28:30";
}
)
2nd Value => nil
1st Value => (
{
"category_id" = 2;
"company_id" = 50;
"created_at" = "2019-11-07 19:58:07";
"deleted_at" = "<null>";
id = 6;
name = Inventory;
"updated_at" = "2019-11-07 19:58:07";
}
)
2nd Value => nil
1st Value => (
{
"category_id" = 3;
"company_id" = 50;
"created_at" = "2019-11-10 21:24:22";
"deleted_at" = "<null>";
id = 9;
name = "Human Resource";
"updated_at" = "2019-11-10 21:24:22";
}
)
2nd Value => nil
Am I missing something here? I'm quite new to Swift so I don't actually have much of a guess myself.
So I made the return type simply an array of NSDictionary.
func getTrainingSubCategories(completion: #escaping(Result<[NSDictionary], GetError>) -> Void){
let dataTask = URLSession.shared.dataTask(with: resourceURL){data, _, _ in
guard let jsonData = data else {
completion(.failure(.trainingCategoriesNoDataAvailable))
return
}
var trainingSubCategories = [NSDictionary]()
do{
let parsedData = try JSONSerialization.jsonObject(with: jsonData) as! [String: Any]
for (key, value) in parsedData {
if key == "categories" {
if let categoriesDictionary: [[String: Any]] = value as? [[String: Any]]{
for categoryDictionary in categoriesDictionary{
for (key, value) in categoryDictionary{
if key == "sub_categories" {
if let subCategoriesArray: [Any] = value as? [Any] {
for subCategory in subCategoriesArray{
trainingSubCategories.append(subCategory as! NSDictionary)
}
}
}
}
}
}
}
completion(.success(trainingSubCategories))
}
}catch {
completion(.failure(.trainingSubCategoriesCannotProcessData))
}
}
dataTask.resume()
}
and my function call with the return looks like this:
private func downloadSubCategories(withCompanyID: Int) {
let trainingCategoriesRequest = GetRequests(endpoint: "getTrainingCategories", id: String(withCompanyID))
trainingCategoriesRequest.getTrainingSubCategories{result in
switch result{
case .success(let trainingSubCategories):
for counter in 0 ..< trainingSubCategories.count {
for (key, value) in trainingSubCategories[counter]{
print("\(key) => \(value)")
}
}
case .failure(let error):
print(error)
}
}
}
I was able to map them without casting NSDictionary to TrainingSubCategory. Which, I'm sorry for ya'll looking into the post, is not an answer to the initial question but a workaround. :)
Related
I am not sure where am I doing wrong.
let recievedJson = json
let results = recievedJson["results"] as! NSArray
let resultsDic = results[0] as! NSDictionary
let address = resultsDic["address_components"] as? NSArray
let zipcodeDic = address?[0] as! NSDictionary
let cityNameDic = address?[1] as! NSDictionary
let countyDic = address?[2] as! NSDictionary
let stateDic = address?[3] as! NSDictionary
let countryDic = address?[4] as! NSDictionary
let zipcode = zipcodeDic["long_name"] as! String
let cityName = cityNameDic["long_name"] as! String
let countyName = countyDic["long_name"] as! String
let stateName = stateDic["long_name"] as! String
let stateShortName = stateDic["short_name"] as! String
let countryName = countryDic["long_name"] as! String
let countryShortName = countryDic["short_name"] as! String
Trying to retrieve data from this json response
http://maps.googleapis.com/maps/api/geocode/json?address=23508&sensor=true
This worked for me, small change to #Danh Answer.
let recievedJson: [String: Any] = json as! [String : Any]
if let results = recievedJson["results"] as? [[String: Any]] {
if results.count > 0 {
let resultsDic = results[0]
if let address = resultsDic["address_components"] as? [[String: Any]] {
for dict in address {
if let longName = dict["long_name"] as? String,
let shortName = dict["short_name"] as? String,
let types = dict["types"] as? [String] {
if types.contains("postal_code") {
print("postal_code: \(longName)")
} else if types.contains("locality") {
print("city: \(longName)")
} else if types.contains("administrative_area_level_2") {
print("county: \(longName)")
} else if types.contains("administrative_area_level_1") {
print("state: \(longName)")
} else if types.contains("country") {
print("country: \(longName)")
}
}
}
}
}
}
The address array has 4 items (has indexes from 0 to 3) but you accessed to item has index is 4, so you got this error. You should use Optional Binding - if let to unwrap values and check count of an array before subscript. And let use Swift types. The code must be:
let recievedJson: [String: Any] = json
if let results = recievedJson["results"] as? [[String: Any]] {
if results.count > 0 {
let resultsDic = results[0]
if let address = resultsDic["address_components"] as? [[String: Any]] {
// zipcode
if address.count > 0 {
let zipcodeDic = address[0]
if let zipcode = zipcodeDic["long_name"] as? String {
print("zipcode: \(zipcode)")
}
}
// cityName
if address.count > 1 {
let cityNameDic = address[1]
if let cityName = cityNameDic["long_name"] as? String {
print("cityName: \(cityName)")
}
}
// stateName
if address.count > 2 {
let stateDic = address[2]
if let stateName = stateDic["long_name"] as? String {
print("stateName: \(stateName)")
}
if let stateShortName = stateDic["short_name"] as? String {
print("stateShortName: \(stateShortName)")
}
}
// countryDic
if address.count > 3 {
let countryDic = address[3]
if let countryName = countryDic["long_name"] as? String {
print("countryName: \(countryName)")
}
if let countryShortName = countryDic["short_name"] as? String {
print("countryShortName: \(countryShortName)")
}
}
}
}
}
Update: extract address components from Google Maps API
let recievedJson: [String: Any] = json
if let results = recievedJson["results"] as? [[String: Any]] {
if results.count > 0 {
let resultsDic = results[0]
if let address = resultsDic["address_components"] as? [[String: Any]] {
for dict in address {
if let longName = dict["long_name"] as? String,
let shortName = dict["short_name"] as? String,
let types = dict["types"] as? [String] {
if types.contains("postal_code") {
print("postal_code: \(longName)")
} else if types.contains("locality") {
print("city: \(longName)")
} else if types.contains("administrative_area_level_2") {
print("county: \(longName)")
} else if types.contains("administrative_area_level_1") {
print("state: \(longName)")
} else if types.contains("country") {
print("country: \(longName)")
}
}
}
}
}
}
I am upgrading my app from swift 2 to swift 3 and have a significant performance loss when building an array of custom objects. In swift 2 this took a few seconds while in swift 3 it takes around 30 seconds. I am using alamofire to return swiftyJSON, returning about 3000 rows of data. the alamofire return is quick, its looping through this json to build array of custom objects thats slow. These objects greatly simplify the code written when building table cells and passing data to new views.
Code:
class Customer {
var ID: String!
var sysName: String!
var address: String!
var contactID: String!
required init(_name:String?, _id: String?, _address:String?, _contactID:String?) {
//print(json)
if _id != nil {
self.ID = _id
}else{
self.ID = ""
}
if _name != nil {
self.sysName = _name
}else{
self.sysName = ""
}
if _address != nil {
self.address = _address
}else{
self.address = "No Address on File"
}
if _contactID != nil {
self.contactID = _contactID
}else{
self.contactID = ""
}
}
}
Alamofire.request(API.Router.customerList()).responseJSON() {
response in
print(response.request ?? "") // original URL request
print(response.response ?? "") // URL response
print(response.data ?? "") // server data
print(response.result) // result of response serialization
if let json = response.result.value {
print("JSON: \(json)")
self.customers = JSON(json)
self.parseJSON()
}
}
func parseJSON(){
let jsonCount = self.customers["customers"].count
self.totalCustomers = jsonCount
for i in 0 ..< jsonCount {
self.loadedCustomers = i
print("customer = \(self.customers["customers"][i] ["sysName"].string!)")
//VERY SLOW
//create a customer object
let customer = Customer( _name: self.customers["customers"][i]["sysName"].string!, _id: self.customers["customers"][i]["ID"].string!, _address: self.customers["customers"][i]["mainAddr"].string!, _contactID: self.customers["customers"][i]["contactID"].string!)
//add customer to customer array
self.customersArray.append(customer)
}
self.layoutViews() //build view, call all table methods
}
Thanks
Improved code:
import Foundation
import UIKit
import Alamofire
import SwiftyJSON
enum SearchMode{
case name
case address
}
class CustomerListViewController: ViewControllerWithMenu, UITableViewDelegate, UITableViewDataSource, UISearchControllerDelegate, UISearchBarDelegate, UISearchDisplayDelegate, UISearchResultsUpdating{
var indicator: SDevIndicator!
var totalCustomers:Int!
//data arrays
var ids = [String]()
var names = [String]()
var addresses = [String]()
var searchController:UISearchController!
var currentSearchMode = SearchMode.name
var customerTableView:TableView = TableView()
var layoutVars:LayoutVars = LayoutVars()
var sections : [(index: Int, length :Int, title: String)] = Array()
var customersSearchResults:[String] = []
var shouldShowSearchResults:Bool = false
let viewsConstraint_V:NSArray = []
let viewsConstraint_V2:NSArray = []
override func viewDidLoad() {
super.viewDidLoad()
title = "Customer List"
view.backgroundColor = layoutVars.backgroundColor
getCustomerList()
}
func getCustomerList() {
//remove any added views (needed for table refresh
for view in self.view.subviews{
view.removeFromSuperview()
}
// Show Indicator
indicator = SDevIndicator.generate(self.view)!
Alamofire.request(API.Router.customerList()).responseJSON() {
response in
//print(response.request ?? "") // original URL request
//print(response.response ?? "") // URL response
//print(response.data ?? "") // server data
//print(response.result) // result of response serialization
do {
if let data = response.data,
let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
let customers = json["customers"] as? [[String: Any]] {
for customer in customers {
if let id = customer["ID"] as? String {
self.ids.append(id)
}
if let name = customer["sysName"] as? String {
self.names.append(name)
}
if let address = customer["mainAddr"] as? String {
self.addresses.append(address)
}
}
}
} catch {
print("Error deserializing JSON: \(error)")
}
// build sections based on first letter(json is already sorted alphabetically)
var index = 0;
var firstCharacterArray:[String] = [" "]
for i in 0 ..< self.names.count {
let stringToTest = self.names[i].uppercased()
let firstCharacter = String(stringToTest[stringToTest.startIndex])
if(i == 0){
firstCharacterArray.append(firstCharacter)
}
if !firstCharacterArray.contains(firstCharacter) {
let title = firstCharacterArray[firstCharacterArray.count - 1]
firstCharacterArray.append(firstCharacter)
let newSection = (index: index, length: i - index, title: title)
self.sections.append(newSection)
index = i;
}
if(i == self.names.count - 1){
let title = firstCharacterArray[firstCharacterArray.count - 1]
let newSection = (index: index, length: i - index, title: title)
self.sections.append(newSection)
}
}
self.layoutViews()
}
}
func layoutViews(){
indicator.dismissIndicator()
searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.placeholder = "Search Customers"
searchController.searchResultsUpdater = self
searchController.delegate = self
searchController.searchBar.delegate = self
searchController.dimsBackgroundDuringPresentation = false
searchController.hidesNavigationBarDuringPresentation = false
navigationItem.titleView = searchController.searchBar
let items = ["Name","Address"]
let customSC = SegmentedControl(items: items)
customSC.selectedSegmentIndex = 0
customSC.addTarget(self, action: #selector(self.changeSearchOptions(sender:)), for: .valueChanged)
self.view.addSubview(customSC)
self.customerTableView.delegate = self
self.customerTableView.dataSource = self
self.customerTableView.register(CustomerTableViewCell.self, forCellReuseIdentifier: "cell")
self.view.addSubview(self.customerTableView)
//auto layout group
let viewsDictionary = [
"view2":customSC,
"view3":self.customerTableView
]as [String:AnyObject]
let sizeVals = ["fullWidth": layoutVars.fullWidth,"width": layoutVars.fullWidth - 30,"navBottom":layoutVars.navAndStatusBarHeight,"height": self.view.frame.size.height - 100] as [String:Any]
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[view2(fullWidth)]", options: [], metrics: sizeVals, views: viewsDictionary))
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[view3(fullWidth)]", options: [], metrics: sizeVals, views: viewsDictionary))
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-navBottom-[view2(40)][view3(height)]", options: [], metrics: sizeVals, views: viewsDictionary))
}
/////////////// Search Methods ///////////////////////
func changeSearchOptions(sender: UISegmentedControl) {
switch sender.selectedSegmentIndex {
case 0:
currentSearchMode = .name
break
case 1:
currentSearchMode = .address
break
default:
currentSearchMode = .name
break
}
filterSearchResults()
}
func updateSearchResults(for searchController: UISearchController) {
filterSearchResults()
}
func filterSearchResults(){
customersSearchResults = []
switch currentSearchMode {
case .name:
self.customersSearchResults = self.names.filter({( aCustomer: String ) -> Bool in
return (aCustomer.lowercased().range(of: self.searchController.searchBar.text!.lowercased()) != nil) })
break
case .address:
self.customersSearchResults = self.addresses.filter({( aCustomer: String) -> Bool in
return (aCustomer.lowercased().range(of: self.searchController.searchBar.text!.lowercased()) != nil)
})
break
}
self.customerTableView.reloadData()
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
//print("searchBarTextDidBeginEditing")
shouldShowSearchResults = true
self.customerTableView.reloadData()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
shouldShowSearchResults = false
self.customerTableView.reloadData()
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
if !shouldShowSearchResults {
shouldShowSearchResults = true
self.customerTableView.reloadData()
}
searchController.searchBar.resignFirstResponder()
}
/////////////// TableView Delegate Methods ///////////////////////
func numberOfSections(in tableView: UITableView) -> Int {
if shouldShowSearchResults{
return 1
}else{
return sections.count
}
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
//print("titleForHeaderInSection")
if shouldShowSearchResults{
return nil
}else{
if(sections[section].title == "#"){
return " # \(self.totalCustomers) Customers Found"
}else{
return " " + sections[section].title //hack way of indenting section text
}
}
}
func sectionIndexTitles(for tableView: UITableView) -> [String]?{
print("sectionIndexTitlesForTableView 1")
if shouldShowSearchResults{
return nil
}else{
//print("sectionIndexTitlesForTableView \(sections.map { $0.title })")
return sections.map { $0.title }
}
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
//print("heightForHeaderInSection")
if shouldShowSearchResults{
return 0
}else{
return 50
}
}
func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
return index
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//print("numberOfRowsInSection")
if shouldShowSearchResults{
return self.customersSearchResults.count
} else {
return sections[section].length
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = customerTableView.dequeueReusableCell(withIdentifier: "cell") as! CustomerTableViewCell
customerTableView.rowHeight = 50.0
if shouldShowSearchResults{
let searchString = self.searchController.searchBar.text!.lowercased()
if(currentSearchMode == .name){
cell.nameLbl.text = self.customersSearchResults[indexPath.row]
cell.name = self.customersSearchResults[indexPath.row]
if let i = self.names.index(of: cell.nameLbl.text!) {
//print("\(cell.nameLbl.text!) is at index \(i)")
cell.addressLbl.text = self.addresses[i]
cell.address = self.addresses[i]
cell.id = self.ids[i]
} else {
cell.addressLbl.text = ""
cell.address = ""
cell.id = ""
}
//text highlighting
let baseString:NSString = cell.name as NSString
let highlightedText = NSMutableAttributedString(string: cell.name)
var error: NSError?
let regex: NSRegularExpression?
do {
regex = try NSRegularExpression(pattern: searchString, options: .caseInsensitive)
} catch let error1 as NSError {
error = error1
regex = nil
}
if let regexError = error {
print("Oh no! \(regexError)")
} else {
for match in (regex?.matches(in: baseString as String, options: NSRegularExpression.MatchingOptions(), range: NSRange(location: 0, length: baseString.length)))! as [NSTextCheckingResult] {
highlightedText.addAttribute(NSBackgroundColorAttributeName, value: UIColor.yellow, range: match.range)
}
}
cell.nameLbl.attributedText = highlightedText
}else{//address search mode
cell.addressLbl.text = self.customersSearchResults[indexPath.row]
cell.address = self.customersSearchResults[indexPath.row]
if let i = self.addresses.index(of: cell.addressLbl.text!) {
cell.nameLbl.text = self.names[i]
cell.name = self.names[i]
cell.id = self.ids[i]
} else {
cell.nameLbl.text = ""
cell.name = ""
cell.id = ""
}
//text highlighting
let baseString:NSString = cell.address as NSString
let highlightedText = NSMutableAttributedString(string: cell.address)
var error: NSError?
let regex: NSRegularExpression?
do {
regex = try NSRegularExpression(pattern: searchString, options: .caseInsensitive)
} catch let error1 as NSError {
error = error1
regex = nil
}
if let regexError = error {
print("Oh no! \(regexError)")
} else {
for match in (regex?.matches(in: baseString as String, options: NSRegularExpression.MatchingOptions(), range: NSRange(location: 0, length: baseString.length)))! as [NSTextCheckingResult] {
highlightedText.addAttribute(NSBackgroundColorAttributeName, value: UIColor.yellow, range: match.range)
}
}
cell.addressLbl.attributedText = highlightedText
}
} else {
//print("make cell")
cell.id = self.ids[sections[indexPath.section].index + indexPath.row]
cell.name = self.names[sections[indexPath.section].index + indexPath.row]
cell.address = self.addresses[sections[indexPath.section].index + indexPath.row]
cell.nameLbl.text = self.names[sections[indexPath.section].index + indexPath.row]
cell.addressLbl.text = self.addresses[sections[indexPath.section].index + indexPath.row]
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let indexPath = tableView.indexPathForSelectedRow;
let currentCell = tableView.cellForRow(at: indexPath!) as! CustomerTableViewCell
let customerViewController = CustomerViewController(_customerID: currentCell.id)
navigationController?.pushViewController(customerViewController, animated: false )
tableView.deselectRow(at: indexPath!, animated: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I have a object like below which is an array of objects.
In swift language, How can i check whether object is an array of objects ?
DefinitionList = (
{
accountNum = {
isEditable = 1;
isRequired = 1;
};
bAccountType = {
isEditable = 1;
isRequired = 0;
},
},
{
accountNum = {
isEditable = 1;
isRequired = 1;
};
bAccountType = {
isEditable = 1;
isRequired = 0;
};
},
..
..)
Usually i use this in Swift 2 :
var DefinitionList = NSObject?()
DefinitionList = ["ciao" : "ciao"]
// DefinitionList = ["ciao"]
guard DefinitionList != nil else {
print("DefinitionList empty")
return
}
guard ((DefinitionList as? Array<NSObject>) != nil) else {
print("I'm a Dictionary")
return
}
print("I'm a Array")
Swift 3
var DefinitionList : NSObject?
// DefinitionList = ["ciao" : "ciao"] as NSObject
DefinitionList = ["ciao"] as NSObject
guard DefinitionList != nil else {
print("DefinitionList empty")
return
}
guard ((DefinitionList as? Array<NSObject>) != nil) else {
print("I'm a Dictionary")
return
}
print("I'm a Array")
You can use "is" operator in Swift language.
if objects is [AnyObject] {
print("right, its array of objects!")
} else {
print("no, its not an array of objects!")
}
Hope this will help you
The following are my codes:
var food = [chicken, fish, duck, pork]
var recipeNames = [String]()
var recipePictures = [UIImage]()
func getRecipes() {
let getRecipesQuery = PFQuery(className: "recipes")
getRecipesQuery.whereKey("food", containedIn: food)
getRecipesQuery.findObjectsInBackgroundWithBlock { (recipes, error) -> Void in
if let recipes = recipes {
self.recipeNames.removeAll(keepCapacity: true)
self.recipePictures.removeAll(keepCapacity: true)
for recipe in recipes {
self.recipeNames.append(recipe["name"] as! String)
if let recipePictureFile = recipe["pictureFile"] as? PFFile {
recipePictureFile.getDataInBackgroundWithBlock({ (imageData, error) -> Void in
if error == nil {
if let picture = UIImage(data: imageData!) {
self.recipePictures.append(picture)
}
}
})
}
}
}
print(self.recipeNames.count)
print(self.recipePictures.count)
}
}
I printed the two arrays counts at the end to check if anything is fetched, the counts are both 0. Any idea why this is happening? There are definitely objects in the class which keys "food" equal to one of the objects in the "food" array, thanks!
EDIT
func getRecipes() {
let getRecipesQuery = PFQuery(className: "recipes")
getRecipesQuery.whereKey("food", containedIn: food)
getRecipesQuery.findObjectsInBackgroundWithBlock { (recipes, error) -> Void in
if let recipes = recipes {
self.recipeNames.removeAll(keepCapacity: true)
self.recipePictures.removeAll(keepCapacity: true)
for recipe in recipes {
self.recipeNames.append(recipe["name"] as! String)
if let recipePictureFile = recipe["pictureFile"] as? PFFile {
recipePictureFile.getDataInBackgroundWithBlock({ (imageData, error) -> Void in
if error == nil {
if let picture = UIImage(data: imageData!) {
self.recipePictures.append(picture)
}
}
})
}
}
dispatch_async(dispatch_get_main_queue()) {
self.recipesTableView.reloadData()
}
}
}
}
I am trying to append data to an Array and save using TMCache, but it's like I'm doing it wrong. Cause, the data isn't being appended. I keep getting empty array
private var teams: Array<Teams> = Array<Teams>()
private var teamResults: [TeamResult]! {
didSet {
if teamResults.count <= 0 {
return
} else {
self.teams = []
for var index = 0; index < teamResults.count; index++ {
//print(index)
let categoryResult = teamResults[index]
if let categoryBackgroundImage = categoryResult["image"] as? PFFile {
categoryBackgroundImage.getDataInBackgroundWithBlock({ (data, error) -> Void in
if let dataGot = data {
let image = UIImage(data: dataGot)
let appendData = Teams(playing: categoryResult["playing"] as! Bool,
name: categoryResult["name"] as! String,
position: categoryResult["position"] as! Int,
image: image!)
//print(appendData.position)
self.teams.append(appendData)
}
print(self.teams.count) <-- I get 0
})
print(self.teams.count) <-- I get 0
}
}
TMCache.sharedCache().setObject(self.teams, forKey: "Teams")
self.mainTableView.reloadData()
for categ in teams {
print(categ.position)
}
}
}
}
getDataInBackgroundWithBlock works asynchronously. The data is returned later in the block.
You have to put the code to reload the table view into the block and check if the loop is finished.
For example (untested)
private var teams: Array<Teams> = Array<Teams>()
private var teamResults: [TeamResult]! {
didSet {
if teamResults.count <= 0 {
return
} else {
self.teams = []
var index : Int
for index = 0; index < teamResults.count; index++ {
//print(index)
let categoryResult = teamResults[index]
if let categoryBackgroundImage = categoryResult["image"] as? PFFile {
categoryBackgroundImage.getDataInBackgroundWithBlock({ (data, error) -> Void in
if let dataGot = data {
let image = UIImage(data: dataGot)
let appendData = Teams(playing: categoryResult["playing"] as! Bool,
name: categoryResult["name"] as! String,
position: categoryResult["position"] as! Int,
image: image!)
//print(appendData.position)
self.teams.append(appendData)
TMCache.sharedCache().setObject(self.category, forKey: "Teams")
if index == teamResults.count {
self.mainTableView.reloadData()
for categ in teams {
print(categ.position)
}
}
}
})
}
}
}
}
}