luke luke - 5 months ago 11
JSON Question

populating JSON in tableview

So I'm trying to populate multiple tableviews with the json code below:

{ "company":[
{ "company_id":"0",
"name": "Company Name",
"phone_number":"0123978978",
"website":"http:\/\/www.Company.co.uk\/",
"email":"Company@hotmail.co.uk",
"address":"123 Alm Street...",
"employees":[
{
"company_id": "0",
"name":"Steve",
"age":"25",
"description":"desc"},
{
"company_id": "0",
"name":"Paul",
"age":"35",
"description":"desc"}]

}
]
}


below is the model of fetching the json and formatting it into something I can use

class Company: NSObject {
var name: String
var phoneNumber: String
var website: String
var email: String
var address: String
var employees: [Employee]

override init() {

}

init(name: String, phoneNumber: String, website: String, email: String, address: String, employees: [Employee]) {
self.name = name
self.phoneNumber = phoneNumber
self.website = website
self.email = email
self.address = address
self.employees = employees
}
}

class Employee : NSObject {
var name:String
var age:Int
var information:String

override init() {

}

init(name: String, age: Int, information: String) {
self.name = name
self.age = age
self.information = information
}
}

func getJSON(completion: (array: [Company])->()) {

var companyArray = [Company]()

let requestURL: NSURL = NSURL(string: urlString)!
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(URL: requestURL)
let session = NSURLSession.sharedSession()

let task = session.dataTaskWithRequest(urlRequest) {
data, response, error -> Void in

let httpResponse = response as! NSHTTPURLResponse
let statusCode = httpResponse.statusCode
if (statusCode == 200) {
print("Everything is fine, file downloaded successfully.")

do{

let json = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments)

if let companies = json["companies"] as? NSArray {

for companyDict in companies {

let company = Company()
let employee = Employee()
var employeeArray = [Employee]()

if let name = companyDict["name"] as? String,
let phoneNumber = companyDict["phone_number"] as? String,
let website = companyDict["website"] as? String,
let email = companyDict["email"] as? String,
let address = companyDict["address"] as? String {

company.name = name
company.phoneNumber = phoneNumber
company.website = website
company.email = email
company.address = address
}
if let employees = companyDict["employees"] as? NSArray {
for employeesDict in employees {
if let name = employeesDict["name"] as? String,
let age = employeesDict["age"] as? Int,
let information = employeesDict["information"] as? String {
var employeeArray = [Employee]()
let employee = Employee()

employee.name = name
employee.information = information
employee.age = age
employeeArray.append(employee)
company.employees = employeeArray
}
}
}
companyArray.append(company)

}
dispatch_async(dispatch_get_main_queue()) {
completion(array: companyArray)
}

}

} catch {
print("Error with Json: \(error)")
}

}

}

task.resume()
}


This is where the problem arrises, I can populate my first tableview fine. Each cell displays the data fine. The problem occurs when I try to populate my second tableview based on selection of a cell in my first tableview.

let selectedCompany:Company?

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.selectedCompany!.employees!.count //ignore force unwrap
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let employee = self.selectedCompany!.employees![indexPath.row] //ignore force unwrap

cell.employeeName.text = employee.name


return cell
}


The line
let employee = self.selectedCompany!.employees![indexPath.row]
displays a compiler error of
type has no subscript members
. I think I know why - I need to populate the second table view as an array. At the moment, Employee is not an array. I've tried several different methods to make it an array but I can't seem to do it. What I've tried usually returns nil and the app crashes or i get compiler errors

Answer

You have to declare employees in Company as array

var employees = [Employee]() 

and also in the initializer

init(name ... , employees: [Employee]) {

and – very very important – you have to create the Employee instance in the repeat loop, otherwise you have employees.count times the same object (due to reference semantics of classes)

   ...
   for employeesDict in employees {
       if let name = employeesDict["name"] as? String,
          let age = employeesDict["age"] as? Int,
          let information = employeesDict["information"] as? String {
             let employee = Employee(name:name, age:age, information:information)
             employeeArray.append(employee)
          }
       }
   } 
   company.employees = employeeArray
   ...

You have to use the initializer anyway. And you have to assign the array after the repeat loop.

Comments