How to load tableview before view is called? - ios

I want to put the table names of my friends first. But why my view should be loaded first, then starts executing the code here
self.art = [responseObject]
let jsonArrays :[String:AnyObject] = self.art.firstObject as! Dictionary
let name = jsonArrays["response"]
for var value in name as! NSArray
{
value = (name?.valueForKey("first_name"))!
self.friends = [value]
}
Here is the full code
class TableViewController: UITableViewController
{
let manager = AFHTTPRequestOperationManager()
let url = "https://api.vk.com/method/friends.get"
var dict = NSDictionary()
var art = []
var friends = NSArray()
var arrayUser = NSArray()
var ar = []
override func viewDidLoad() {
super.viewDidLoad()
self.getFriends()
self.friends = NSArray()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func getFriends()
{
dict = ["user_id":"107487867",
"name":"order",
"count":5,
"fields":"photo",]
self.manager.GET(url, parameters: dict,
success:{ (operation:AFHTTPRequestOperation,
responseObject: AnyObject!) in
self.art = [responseObject]
let jsonArrays :[String:AnyObject] = self.art.firstObject as! Dictionary
let name = jsonArrays["response"]
for var value in name as! NSArray
{
value = (name?.valueForKey("first_name"))!
self.friends = [value]
}
}){ (operation:AFHTTPRequestOperation!, NSError) -> Void in
}
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return friends.count
}

Related

How to display a multidimensional array under different sections in swift 3

I have been trying to create multidimensional arrays and display each array under each section .. but I keep ending up with a fatal error index out of range . The code that i display below is how I access my firebase data and print each array from the database.. issue is I get the data I assign an array to it create it but can’t seem to display it due to the error . Hope someone helps for reference regarding the error I have attached a screenshot as well.
#IBOutlet weak var tableview: UITableView!
var yourArray = [String]()
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
var sundaycoursenamearray = [String]()
var sundaycoursecodearray = [String]()
var sundaycourselocationarray = [String]()
var sundayfromarray = [String]()
var sundaytoarray = [String]()
var mondaycoursenamearray = [String]()
var mondaycoursecodearray = [String]()
var mondaycourselocationarray = [String]()
var mondayfromarray = [String]()
var mondaytoarray = [String]()
var tuesdaycoursenamearray = [String]()
var tuesdaycoursecodearray = [String]()
var tuesdaycourselocationarray = [String]()
var tuesdayfromarray = [String]()
var tuesdaytoarray = [String]()
var wednesdaycoursenamearray = [String]()
var wednesdaycoursecodearray = [String]()
var wednesdaycourselocationarray = [String]()
var wednesdayfromarray = [String]()
var wednesdaytoarray = [String]()
var thursdaycoursenamearray = [String]()
var thursdaycoursecodearray = [String]()
var thursdaycourselocationarray = [String]()
var thursdayfromarray = [String]()
var thursdaytoarray = [String]()
var fridaycoursenamearray = [String]()
var fridaycoursecodearray = [String]()
var fridaycourselocationarray = [String]()
var fridayfromarray = [String]()
var fridaytoarray = [String]()
var saturdaycoursenamearray = [String]()
var saturdaycoursecodearray = [String]()
var saturdaycourselocationarray = [String]()
var saturdayfromarray = [String]()
var saturdaytoarray = [String]()
var coursecodes = [[String]]()
var coursenames = [[String]]()
var courselocations = [[String]]()
var fromtimes = [[String]]()
var totimes = [[String]]()
var days = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]
override func viewWillAppear(_ animated: Bool) {
let uid = Auth.auth().currentUser?.uid
if(uid == nil){
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let nextviewController = storyboard.instantiateViewController(withIdentifier: "loginscreen")
//self.present(profileViewController, animated: true, completion: nil)
self.present(nextviewController, animated: true, completion: nil)
}
for j in days {
for i in 1 ..< 10 {
let ref1 = Database.database().reference().child("users").child((uid)!).child("courses").child(j).child(String(i))
ref1.observeSingleEvent(of: .value, with: { snapshot in
if let dictionary = snapshot.value as? [String: AnyObject] {
// print(dictionary)
if j == "Sunday" {
if let points = dictionary["coursname"] as? String {
self.sundaycoursecodearray.append(points)
print(self.sundaycoursecodearray)
}
if let points1 = dictionary["coursecode"] as? String {
self.sundaycoursenamearray.append(points1)
print(self.sundaycoursenamearray)
}
if let points1 = dictionary["courseroomlocation"] as? String {
self.sundaycourselocationarray.append(points1)
print(self.sundaycourselocationarray)
}
if let points1 = dictionary["fromtime"] as? String {
self.sundayfromarray.append(points1)
print(self.sundayfromarray)
}
if let points1 = dictionary["totime"] as? String {
self.sundaytoarray.append(points1)
print(self.sundaytoarray)
}
}
if j == "Monday" {
if let points = dictionary["coursname"] as? String {
self.mondaycoursecodearray.append(points)
print(self.mondaycoursecodearray)
}
if let points1 = dictionary["coursecode"] as? String {
self.mondaycoursenamearray.append(points1)
print(self.mondaycoursenamearray)
}
if let points1 = dictionary["courseroomlocation"] as? String {
self.mondaycourselocationarray.append(points1)
print(self.mondaycourselocationarray)
}
if let points1 = dictionary["fromtime"] as? String {
self.mondayfromarray.append(points1)
print(self.mondayfromarray)
}
if let points1 = dictionary["totime"] as? String {
self.mondaytoarray.append(points1)
print(self.mondaytoarray)
}
}
if j == "Tuesday" {
if let points = dictionary["coursname"] as? String {
self.tuesdaycoursecodearray.append(points)
print(self.tuesdaycoursecodearray)
}
if let points1 = dictionary["coursecode"] as? String {
self.tuesdaycoursenamearray.append(points1)
print(self.tuesdaycoursenamearray)
}
if let points1 = dictionary["courseroomlocation"] as? String {
self.tuesdaycourselocationarray.append(points1)
print(self.tuesdaycourselocationarray)
}
if let points1 = dictionary["fromtime"] as? String {
self.tuesdayfromarray.append(points1)
print(self.tuesdayfromarray)
}
if let points1 = dictionary["totime"] as? String {
self.tuesdaytoarray.append(points1)
print(self.tuesdaytoarray)
}
}
if j == "Wednesday" {
if let points = dictionary["coursname"] as? String {
self.wednesdaycoursecodearray.append(points)
print(self.wednesdaycoursecodearray)
}
if let points1 = dictionary["coursecode"] as? String {
self.wednesdaycoursenamearray.append(points1)
print(self.wednesdaycoursenamearray)
}
if let points1 = dictionary["courseroomlocation"] as? String {
self.wednesdaycourselocationarray.append(points1)
print(self.wednesdaycourselocationarray)
}
if let points1 = dictionary["fromtime"] as? String {
self.wednesdayfromarray.append(points1)
print(self.wednesdayfromarray)
}
if let points1 = dictionary["totime"] as? String {
self.wednesdaytoarray.append(points1)
print(self.wednesdaytoarray)
}
}
if j == "Thursday" {
if let points = dictionary["coursname"] as? String {
self.thursdaycoursecodearray.append(points)
print(self.thursdaycoursecodearray)
}
if let points1 = dictionary["coursecode"] as? String {
self.thursdaycoursenamearray.append(points1)
print(self.thursdaycoursenamearray)
}
if let points1 = dictionary["courseroomlocation"] as? String {
self.thursdaycourselocationarray.append(points1)
print(self.thursdaycourselocationarray)
}
if let points1 = dictionary["fromtime"] as? String {
self.thursdayfromarray.append(points1)
print(self.thursdayfromarray)
}
if let points1 = dictionary["totime"] as? String {
self.thursdaytoarray.append(points1)
print(self.thursdaytoarray)
}
}
if j == "Friday" {
if let points = dictionary["coursname"] as? String {
self.fridaycoursecodearray.append(points)
print(self.fridaycoursecodearray)
}
if let points1 = dictionary["coursecode"] as? String {
self.fridaycoursenamearray.append(points1)
print(self.fridaycoursenamearray)
}
if let points1 = dictionary["courseroomlocation"] as? String {
self.fridaycourselocationarray.append(points1)
print(self.fridaycourselocationarray)
}
if let points1 = dictionary["fromtime"] as? String {
self.fridayfromarray.append(points1)
print(self.fridayfromarray)
}
if let points1 = dictionary["totime"] as? String {
self.fridaytoarray.append(points1)
print(self.fridaytoarray)
}
}
if j == "Saturday" {
if let points = dictionary["coursname"] as? String {
self.saturdaycoursecodearray.append(points)
print(self.saturdaycoursecodearray)
}
if let points1 = dictionary["coursecode"] as? String {
self.saturdaycoursenamearray.append(points1)
print(self.saturdaycoursenamearray)
}
if let points1 = dictionary["courseroomlocation"] as? String {
self.saturdaycourselocationarray.append(points1)
print(self.saturdaycourselocationarray)
}
if let points1 = dictionary["fromtime"] as? String {
self.saturdayfromarray.append(points1)
print(self.saturdayfromarray)
}
if let points1 = dictionary["totime"] as? String {
self.saturdaytoarray.append(points1)
print(self.saturdaytoarray)
}
}
self.coursecodes.append(self.sundaycoursenamearray)
self.coursecodes.append(self.mondaycoursenamearray)
self.coursecodes.append(self.tuesdaycoursenamearray)
self.coursecodes.append(self.wednesdaycoursenamearray)
self.coursecodes.append(self.thursdaycoursenamearray)
self.coursecodes.append(self.fridaycoursenamearray)
self.coursecodes.append(self.saturdaycoursenamearray)
self.coursenames.append(self.sundaycoursecodearray)
self.coursenames.append(self.mondaycoursecodearray)
self.coursenames.append(self.tuesdaycoursecodearray)
self.coursenames.append(self.wednesdaycoursecodearray)
self.coursenames.append(self.thursdaycoursecodearray)
self.coursenames.append(self.fridaycoursecodearray)
self.coursenames.append(self.saturdaycoursecodearray)
self.courselocations.append(self.sundaycourselocationarray)
self.courselocations.append(self.mondaycourselocationarray)
self.courselocations.append(self.tuesdaycourselocationarray)
self.courselocations.append(self.wednesdaycourselocationarray)
self.courselocations.append(self.thursdaycourselocationarray)
self.courselocations.append(self.fridaycourselocationarray)
self.courselocations.append(self.saturdaycourselocationarray)
self.fromtimes.append(self.sundayfromarray)
self.fromtimes.append(self.mondayfromarray)
self.fromtimes.append(self.tuesdayfromarray)
self.fromtimes.append(self.wednesdayfromarray)
self.fromtimes.append(self.thursdayfromarray)
self.fromtimes.append(self.fridayfromarray)
self.fromtimes.append(self.saturdayfromarray)
self.totimes.append(self.sundaytoarray)
self.totimes.append(self.mondaytoarray)
self.totimes.append(self.tuesdaytoarray)
self.totimes.append(self.wednesdaytoarray)
self.totimes.append(self.thursdaytoarray)
self.totimes.append(self.fridaytoarray)
self.totimes.append(self.saturdaytoarray)
self.tableview.reloadData()
}
})
} }
super.viewWillAppear(animated)
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return days[section]
}
func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return days.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return coursenames[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! homeTableViewCell
// Configure the cell...
// cell.classcode?.text = sundaycoursenamearray[indexPath.section]
cell.classcode?.text = coursenames[indexPath.section][indexPath.row]
return cell
}
/*
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
You should create a model for your data then create arrays that include the model.
You can create a simple struct like so:
struct Course {
var name : String?
var code: String?
var location: String?
var toTime: String?
var fromTime: String?
}
After you create the model you can create an array that contains this type of struct.
Also for numberOfRowsInSection you don't have to use subscript. Just return:
return coursenames.count
That is why you get the error.

How do I create a drill down UITable in a single view using pre-populated data from API call?

I am trying to create a selection method for users to pick a football team using UITableView.
When the View Controller loads I make an API call and fetch and populated the following arrays in custom structs:
Country [name,id]
Divisions [id, country_id, name]
Teams [id, division_id, name]
The process is:
The user first selects a country > the ID of this country is then used to populate the table with all the divisions from that country > a division is selected which brings up all the teams in that division > a team is selected and the team name and id are passed to a variable to be used elsewhere.
At the moment the table displays all the countries. Once a user selects a country I am using print (self.newCountries[cellCountryId!]) to identifies and print the name of the country and it's id.
How do I now take that data and re-populate the table where Divisions.country_id = (self.newCountries[cellCountryId!])
This is my code:
import UIKit
class PickTeamViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var teamsTableView: UITableView!
var pickedCountryID: Int?
var selectedCellCountryTitle: String?
var cellCountryId: Int?
struct Country {
var name: String?
var countryId: String?
init(_ dictionary: [String : String]) {
self.name = dictionary["name"]
self.countryId = dictionary["id"]
}
}
struct Divisions {
var divisionName: String?
var divisionId: String?
init(_ dictionary: [String : String]) {
self.divisionName = dictionary["name"]
self.divisionId = dictionary["country_id"]
}
}
struct Teams {
var teamName: String?
var newTeamId: String?
init(_ dictionary: [String : String]) {
self.teamName = dictionary["name"]
}
}
struct TeamId {
var newTeamId: String?
init(_ dictionary: [String : String]) {
self.newTeamId = dictionary["id"]
}
}
var newCountries = [Country]()
var newDivisions = [Divisions]()
var newTeams = [Teams]()
var newTeamId = [TeamId]()
override func viewDidAppear(_ animated: Bool) {
let myUrl = URL(string: "http://www.quasisquest.uk/KeepScore/getTeams.php?");
var request = URLRequest(url:myUrl!);
request.httpMethod = "GET";
let task = URLSession.shared.dataTask(with: myUrl!) { (data: Data?, response: URLResponse?, error: Error?) in
DispatchQueue.main.async
{
if error != nil {
print("error=\(error)")
return
}
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:Any]
print (json)
if let arr = json?["countries"] as? [[String:String]] {
self.newCountries = arr.flatMap { Country($0) }
self.teamsTableView.reloadData()
}
if let arr = json?["divisions"] as? [[String:String]] {
self.newDivisions = arr.flatMap { Divisions($0) }
}
if let arr = json?["teams"] as? [[String:String]] {
self.newTeams = arr.flatMap { Teams($0) }
}
self.teamsTableView.reloadData()
} catch{
print(error)
}
}
}
task.resume()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.newCountries.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let country = newCountries[indexPath.row]
let cell = UITableViewCell()
cell.textLabel?.text = country.name
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
cellCountryId = indexPath.row
print (self.newCountries[cellCountryId!])
}
override func viewDidLoad() {
super.viewDidLoad()
self.teamsTableView.delegate = self
self.teamsTableView.dataSource = self
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func backButtonTapped(_ sender: AnyObject) {
self.dismiss(animated: true) {
return
}
}
}

Tableview doesn't display data in swift 2

I'm working on the tableView in swift 2.2 in xcode 7.3.1 and I'm sure from my code because it's not the first time for me to deal with tableView , I'm pulling data correctly from server and stored it in array but I notice the two function that is related to table view is not called so the table view appear empty for me ! I added cell and linked tableview with view also from layout.
I don't know where is the problem!
class studentTeacherList: UIViewController , UITableViewDataSource,UITableViewDelegate {
#IBOutlet weak var studentParentTable: UITableView!
#IBOutlet weak var loadIndicator: UIActivityIndicatorView!
var username:String!
var fromSender: String?
var toRec: String?
var student_id = [Int]()
var parent_id = [String]()
var student_names = [String]()
var parent_name = [String]()
//Sent Data
var s_id:Int = 0
var s_name = ""
var p_id = ""
var p_name = ""
override func viewDidLoad() {
super.viewDidLoad()
studentParentTable.delegate = self
studentParentTable.dataSource = self
let prefs:NSUserDefaults = NSUserDefaults.standardUserDefaults()
username = prefs.objectForKey("user")as! String
fromSender = prefs.objectForKey("Sender")as! String
toRec = prefs.objectForKey("Receiver")as! String
self.loadIndicator.startAnimating()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
self.loadList()
//self.studentParentTable.reloadData()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.loadIndicator.stopAnimating()
})
});
studentParentTable.reloadData()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return student_names.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//This method to define each cell at Table View
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
cell.textLabel?.text = student_names[indexPath.row]
cell.detailTextLabel?.text = parent_name[indexPath.row]
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func backButton(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil )
}
func loadList()
{
var normallink = "mylinkhere"
normallink = normallink + "?teacherid=" + self.username
var studentParentURL:NSURL = NSURL (string: normallink)!
let data = NSData(contentsOfURL: studentParentURL)!
do {
let json = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
if let alldata = json["data"] as? [[String: AnyObject]] {
for onedata in alldata {
if let stu_id = onedata["id"] as? Int {
student_id.append(stu_id)
}
if let stu_name = onedata["studentName"] as? String {
student_names.append(stu_name)
}
if let par_id = onedata["parentId"] as? String {
parent_id.append(par_id)
}
if let par_name = onedata["parentName"] as? String {
parent_name.append(par_name)
}
}
}
} catch {
print("Error Serializing JSON: \(error)")
}
print(student_names.count)
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
s_id = student_id[indexPath.row]
s_name = student_names[indexPath.row]
p_id = parent_id[indexPath.row]
p_name = parent_name[indexPath.row]
}
}
It looks like you aren't reloading after this call:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
self.loadList()
//self.studentParentTable.reloadData()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.loadIndicator.stopAnimating()
})
});
So you should add studentParentTable.reloadData() after self.loadIndicator.stopAnimating().

How to return value from Swift closure?

I'm new at swift closures.
I have this code and i can't extract the values from the forloop into the arrays outside the closure.
Sorry about this question but i have already searched stackflow but without success in this specific case.
Thanks in advance.
var namesArray: [String] = []
var imagesArray: [String] = []
var timesArray: [String] = []
var placesArray: [String] = []
func getData(){
//DATA SOURCE
// Create request for user's Facebook data
let request = FBSDKGraphRequest(graphPath: cmp.pageId, parameters: ["fields": "events"])
// Send request to Facebook
request.startWithCompletionHandler {
(connection, result, error) in
if error != nil {
// Some error checking here
print(error.debugDescription)
} else
if let pageData = result["events"] {
print(result["events"]!!["data"]!![0]["name"])
if let eventDetails = pageData!["data"] {
// EVENT DETAILS FETCH
for var i = 0; i < eventDetails!.count; i++
{
let fetchedEventName = eventDetails![i]["name"] as? String!
let fetchedEventTime = eventDetails![i]["start_time"] as? String!
if eventDetails?[i]["place"]??["name"] != nil {
if let fetchedEventPlace = eventDetails?[i]["place"]??["name"] {
self.placesArray.append(fetchedEventPlace! as! String)
}
} else {
self.placesArray.append("Lisbon")
}
self.namesArray.append(fetchedEventName!)
self.timesArray.append(fetchedEventTime!)
}
print("Name of event: \(self.namesArray)")
}
} else {
print("Error.")
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
getData()
}
EDIT: I want to show the fetched result into a tableview that's already set.
Heres the tableview code.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCellWithIdentifier("previewCell") as? PreviewCell {
var img: UIImage!
let url = NSURL(string: imagesArray[indexPath.row])!
if let data = NSData(contentsOfURL: url){
img = UIImage(data: data)
} else {
img = UIImage(named: "ant")
}
cell.configureCell(img, title: namesArray[indexPath.row], time: timesArray[indexPath.row], place: placesArray[indexPath.row])
return cell
} else {
return PreviewCell()
}
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return namesArray.count
}
func addNewEvent(name: String, image: String, time: String, place: String)
{
namesArray.append(name)
imagesArray.append(image)
timesArray.append(time)
placesArray.append(place)
}
You are already getting the number in to the arrays so what you need to do is just reload the tableview after the for loop.
//end of for-loop
self.tableView.reloadData()
The reason for this is the asynchronous execution of the request.startWithCompletionHandler. The code inside that block will most likely execute after your tableView already loaded and it therefor needs a reload after the data has been fetched
In case if you need to return data from closure you can define completion on your getData() method like this
func getData(completion:([DataType]) -> Void) {
//process data
let dataArray:DataType = []
completion(dataArray)
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
getData { (completionData) -> Void in
// process returned data
}
}
Hope this helps

How to Segue from a table filled with results from search controller

The old UISearchDisplayController class is now deprecated and instead we have to use the new UISearchController. There used to be a property in the old class called "SearchResultsTableView" but it's gone from the new class.
I populate a table with data and all works as intended - including segueing each row's details to another scene. I throw a search bar in there (programmatically - using the new searchController) and it successfully reloads the original table with any found results.
HOWEVER, when touching a selected row after a search, the segue passed along is that of the original table row that happens to be in the same position of the one touched now! (i.e. if I choose the current second row of a search, the next scene will segue the details of the second row of the original table!) That's because despite the data in the rows are being successfuly repopulated with the search data, the index numbers are still those of the old data.
It used to be with the old type that we would check this as such:
if (self.resultSearchController.active) {
let indexPath = self.searchDisplayController!.searchResultsTableView.indexPathForSelectedRow()
} else {
let indexPath = self.tableView.indexPathForSelectedRow()
So I think that with the old UISearchDisplayController class you actually got a new table, whereas with the new SearchController Class you only get new rows inside the old table? This totaly doesn't make sense !
Here is my full code per request:
import UIKit
import Foundation
class secondTableViewController: UITableViewController, UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating {
var filteredTableData = [String]()
var resultSearchController = UISearchController()
//these 2 are standard for the title and subtitle
var TableTitle:Array< String > = Array < String >()
var TableSub:Array< String > = Array < String >()
//the following are for my seque to next scene
var the_fname:Array< String > = Array < String >()
var the_basics:Array< String > = Array < String >()
var the_p_method:Array< String > = Array < String >()
var the_seats:Array< String > = Array < String >()
var the_notes:Array< String > = Array < String >()
var the_tableData:Array< String > = Array < String >()
override func viewDidLoad() {
tableView.delegate = self
tableView.dataSource = self
self.title = currentBus
super.viewDidLoad()
self.resultSearchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
self.tableView.tableHeaderView = controller.searchBar
return controller
})()
// Reload the table
self.tableView.reloadData()
var url = "http://the_path_to_my_json_file"
get_data_from_url(url)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// 2
if (self.resultSearchController.active) {
return self.filteredTableData.count
}
else {
return TableTitle.count
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("secondtableCell", forIndexPath: indexPath) as! UITableViewCell
// Configure the cell...
if (self.resultSearchController.active) {
cell.textLabel?.text = filteredTableData[indexPath.row]
//cell.detailTextLabel?.text = TableSub[indexPath.row]
}else{
cell.textLabel?.text = TableTitle[indexPath.row]
cell.detailTextLabel?.text = TableSub[indexPath.row]
}
return cell
}
func get_data_from_url(url:String)
{
let httpMethod = "GET"
let timeout = 15
let url = NSURL(string: url)
let urlRequest = NSMutableURLRequest(URL: url!,
cachePolicy: .ReloadIgnoringLocalAndRemoteCacheData,
timeoutInterval: 15.0)
let queue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(
urlRequest,
queue: queue,
completionHandler: {(response: NSURLResponse!,
data: NSData!,
error: NSError!) in
if data.length > 0 && error == nil{
let json = NSString(data: data, encoding: NSASCIIStringEncoding)
self.extract_json(json!)
}else if data.length == 0 && error == nil{
println("Nothing was downloaded")
} else if error != nil{
println("Error happened = \(error)")
}
}
)
}
func extract_json(data:NSString)
{
var parseError: NSError?
let jsonData:NSData = data.dataUsingEncoding(NSASCIIStringEncoding)!
let json: AnyObject? = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &parseError)
if (parseError == nil)
{
if let my_pass_list = json as? NSArray
{
for (var i = 0; i < my_pass_list.count ; i++ )
{
if let each_pass = my_pass_list[i] as? NSDictionary
{
if let fname = each_pass["fname"] as? String
{
if let lname = each_pass["lname"] as? String
{
if let numofseats = each_pass["numofseats"] as? String
{
if let showed_up = each_pass["showed_up"] as? String
{
if let res_id = each_pass["resnum"] as? String
{
if let res_notes = each_pass["res_notes"] as? String
{
if let payment_description = each_pass["payment_description"] as? String
{
// the_tableData.append(fname)
the_fname.append(fname)
the_basics.append(fname + " " + lname)
the_p_method.append(payment_description)
the_seats.append(numofseats)
the_notes.append(res_notes)
TableTitle.append(fname + " " + lname)
TableSub.append("Seats Reserved: " + numofseats + ". Showed Up: " + showed_up + ". Notes:" + res_notes)
the_tableData = TableTitle
}
}
}
}
}
}
}
}
}
}
}
do_table_refresh();
}
func do_table_refresh()
{
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
return
})
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using [segue destinationViewController].
var thirdScene = segue.destinationViewController as! customer_details_View_Controller
if let indexPath = self.tableView.indexPathForSelectedRow() {
/*
so what I'm missing is to be able to check
if (self.resultSearchController.active) {
and if yes have indexPath be the self.resultSearchController.resultSearchTableView.indexPathForSelectedRow() {
or something of that nature
*/
thirdScene.dotrav = todayString
thirdScene.from = currentBus
thirdScene.basics = the_basics[indexPath.row]
thirdScene.p_method = the_basics[indexPath.row]
thirdScene.seats = the_tableData[indexPath.row]
thirdScene.notes = the_notes[indexPath.row]
}
// Pass the selected object to the new view controller.
}
func updateSearchResultsForSearchController(searchController: UISearchController)
{
filteredTableData.removeAll(keepCapacity: false)
let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %#", searchController.searchBar.text)
let array = (the_tableData as NSArray).filteredArrayUsingPredicate(searchPredicate)
filteredTableData = array as! [String]
self.tableView.reloadData()
}
}
You need to account for the fact that you are going to have different data in your tableView depending on the search result. You can still use self.tableView.indexPathForSelectedRow.
What I do, is keep a reference to my base data, and then keep a reference to my filtered data, and display my filtered data in the tableView at all times. If my searchBar has no text, then my filtered data is equal to my base data.
Example:
class MyTableViewController: UITableViewController, UISearchResultsUpdating {
var data: [String] = ["One", "Two", "Three", "Four", "Five"]
var filteredData: [String]!
var searchController: UISearchController!
override func viewDidLoad() {
super.viewDidLoad()
setUpSearchController()
setFilteredDataForCurrentSearch()
}
private func setUpSearchController() {
searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
self.tableView.tableHeaderView = searchController.searchBar
}
private func setFilteredDataForCurrentSearch() {
if let searchString = searchController.searchBar.text where !searchString.isEmpty {
filteredData = data.filter({ (string: String) -> Bool in
return searchString.rangeOfString(string, options: NSStringCompareOptions.CaseInsensitiveSearch) != nil
})
} else {
filteredData = data
}
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
setFilteredDataForCurrentSearch()
}
}
Now, you can implement all of your UITableViewDataSource and UITableViewDelegate methods using the filteredData.
In prepareForSegue, you retrieve the correct selected object like:
let indexPath = tableView.indexPathForSelectedRow()
let selectedObject = filteredData[indexPath.row]

Resources