Here i am trying to load the table view with JSON data but data is not showing up. I don't know where the problem is i think i am not getting data into array properly.Tried a lot but not getting what i am doing wrong.New to iOS.
Below is my JSON data:
{"total_images_count":266,"datetime_value":"2016-07-15
19:28:37","total_count_response":"","image_path":"http://www.expert.com/test/images/","task":[{"image_name":"file1","image_path":"1461468362622.jpg"},{"image_name":"file2","image_path":"1461468362622.jpg"},
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
var arrDict :NSMutableArray = NSMutableArray()
override func viewDidLoad() {
super.viewDidLoad()
jsonParsingFromURL()
}
func jsonParsingFromURL () {
let url = NSURL(string: "http://clipbyte.com/ontest/cron/webapi.php?task=webapi.getAllClips")
let request = NSURLRequest(URL: url!)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {(response, data, error) in
self.startParsing(data!)
}
}
func startParsing(data :NSData)
{
let dict: NSDictionary!=(try! NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers)) as! NSDictionary
for var i = 0 ; i < (dict.valueForKey("task") as! NSArray).count ; i++
{
arrDict.addObject((dict.valueForKey("task") as! NSArray) .objectAtIndex(i))
}
NSLog("array is ", arrDict)
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return arrDict.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell : UITableViewCell! = tableView.dequeueReusableCellWithIdentifier("Cell")
let strTitle : NSString=arrDict[indexPath.row] .valueForKey("clip_name") as! NSString
cell.textLabel!.text=strTitle as String
cell.imageView?.image = arrDict[indexPath.row].valueForKey("clip_image_path") as? UIImage
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
if i use the below class for custom cell it gives me error at init function below IBOutlet
TableViewCell class
class TableViewCell: UITableViewCell
{
#IBOutlet weak var lblTitle: UILabel!
#IBOutlet weak var lbDetails: UILabel!
init(style: UITableViewCellStyle, reuseIdentifier: String) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
// Initialization code
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Write a function to run a closure on main thread:
typealias Closure = () -> Void
func runOnMain(closure: Closure) {
dispatch_async(dispatch_get_main_queue(), {
() -> Void in
closure()
})
}
Then in your method startParsing
Finish by reloading tableView:
func startParsing(data :NSData)
{
let dict: NSDictionary!=(try! NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers)) as! NSDictionary
for var i = 0 ; i < (dict.valueForKey("task") as! NSArray).count ; i++
{
arrDict.addObject((dict.valueForKey("task") as! NSArray) .objectAtIndex(i))
}
NSLog("array is ", arrDict)
runOnMain {
self.tableView.reloadData()
}
}
Edit:
A tip is to create a Macros.swift file without any class and put the runOnMain method and typealias in that file. That way that method is accessible from anywhere in your project.
Also you should really create Models from your JSON. I suggest you take a look at my open source project which fetches data using Alamofire and parses the JSON into models.
Related
searching in the textField of the tableView.
I need to search the names from the tableView. So for that i have tableView and textField in the UIViewController.
And i need to search from the Api. For that i have used the Alamofire method to fetch the data.
I need to search. Now i implement to display the names from the api to tableView And i got the output. But i need to implement searching .how to do in the mvvm.
my model:-
class SearchModel: NSObject {
var restaurantname :String!
init?(dictionary :JSONDictionary) {
guard let name = dictionary["name"] as? String else {
return
}
self.restaurantname = name
}
}
My viewmodel:-
class SearchViewModel: NSObject {
var datasourceModel:SearchDataSourceModel
init(withdatasource newDatasourceModel: SearchDataSourceModel) {
datasourceModel = newDatasourceModel
}
func datafordisplay(atindex indexPath: IndexPath) -> SearchModel{
return datasourceModel.dataListArray![indexPath.row]
}
func numberOfRowsInSection(section:Int) -> Int {
return (datasourceModel.dataListArray?.count)!
}
func loadData(completion :#escaping (_ isSucess:Bool) -> ()){
loadFromWebserviceData { (newDataSourceModel) in
if(newDataSourceModel != nil) {
self.datasourceModel = newDataSourceModel!
completion(true)
}
else {
completion(false)
}
}
}
//}
func loadFromWebserviceData(completion :#escaping (SearchDataSourceModel?) -> ()) {
//with using Alamofire ..............
Alamofire.request("http://www.example.com").validate(statusCode: 200..<300).validate(contentType: ["application/json"]).responseJSON{ response in
switch response.result {
case .success(let data):
print("success",data)
let result = response.result
if let wholedata = result.value as? [String:Any]{
if let data = wholedata["data"] as? Array<[String:Any]>{
// print(data["name"] as! String)
print(data)
print(response)
let newDataSource:SearchDataSourceModel = SearchDataSourceModel(array: data)
completion(newDataSource)
// }
}
}
// case .failure(let data):
// print("fail",data)
case .failure(let encodingError ):
print(encodingError)
// if response.response?.statusCode == 404 {
print(encodingError.localizedDescription)
completion(nil)
// }
}
}}
}
my DataSourcemodel:-
class SearchDataSourceModel: NSObject {
var dataListArray:Array<SearchModel>? = []
init(array :Array<[String:Any]>?) {
super.init()
var newArray:Array<[String:Any]> = []
if array == nil {
// newArray = self.getJsonDataStored44()
}
else {
newArray = array!
}
var datalist:Array<SearchModel> = []
for dict in newArray {
let model = SearchModel(dictionary: dict)
datalist.append(model!)
}
self.dataListArray = datalist
}
}
my viewController class:-
class SearchViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet private weak var tableView: UITableView!
private var searchViewModel :SearchViewModel!
init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?, withViewModel viewModel:SearchViewModel) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
searchViewModel = viewModel
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
// tableView.dataSource = self
// filteredData = data
searchViewModel.loadData { (isSuccess) in
if(isSuccess == true) {
self.tableView .reloadData()
}
else {
}
}
// self.tableView .reloadData()
// Do any additional setup after loading the view.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return searchViewModel.numberOfRowsInSection(section: section)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let identifier = "searchcell"
var cell: SearchCell! = tableView.dequeueReusableCell(withIdentifier: identifier) as? SearchCell
if cell == nil {
tableView.register(UINib(nibName: "SearchCell", bundle: nil), forCellReuseIdentifier: identifier)
cell = tableView.dequeueReusableCell(withIdentifier: identifier) as? SearchCell
}
cell.setsearchData(search: searchViewModel.datafordisplay(atindex: indexPath))
// cell.name.text = searchViewModel.datafordisplay(atindex: indexPath)
// cell.name.text = filteredData[indexPath.row]
// cell.setsearchData(search: searchViewModel.datafordisplay(atindex: indexPath))
return cell
}
/*
// 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.
}
*/
}
tableViewCell:-
class SearchCell: UITableViewCell {
#IBOutlet weak var name: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
func setsearchData(search:SearchModel) {
self.name.text = search.restaurantname
}
}
This is my code .Now how to implement the searching here.
There are t way of searching.
when you enter text and press the search button.
When You type then search without using the search button.
A solution for 1:
You need to call a method on the search button
Search button.
func Search() {
predicate = NSPredicate(format: "Self.YourSearchListName beginsWith[c]%#", SearchName)
GetsearchList = YourArrayForSearch.filtered(using: predicate) as NSArray
YourTable.reloadData()
}
2nd Solution
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == self.YourTextFieldName{
Search()
}
}
for 2nd Solution don't forget to set the delegate.
filteredContactListArray is the array holding the filtered data to reload the tableview when user start searching for particular text.
#IBOutlet var searchCityTextField: UITextField!
var filteredSearchArray :SearchViewModel!
within in Viewdidload() function
searchCityTextField.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: UIControlEvents.editingChanged)
UItextfieldDelegate Method
func textFieldDidChange(textField: UITextField) {
if textField.text == "" {
filteredSearchArray = searchViewModel// contactListArray is the actual array with all the list of data.
citiesTableView.reloadData()
}else{
filterContentForSearchText(textField.text!)
}
}
func filterContentForSearchText(searchText: String) {
filteredSearchArray = NSMutableArray(array:searchViewModel. dataListArray.filter({(ele:AnyObject) -> Bool in
return (ele as! searchViewModel).cityName.lowercased().contains(searchText.lowercased())
}))
citiesTableView.reloadData()
}
UItableviewDelegate Method
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredContactListArray.count
}
I am doing in mvvm method.my code as below.
foodModel :-
class foodModel: NSObject {
var name :String!
var city :String!
var imageurl :String!
init?(dictionary :JSONDictionary) {
guard let name = dictionary["name"] as? String,
let imageurl = dictionary["imageurl"] as? String,
let city = dictionary["city"] as? String else {
return
}
self.name = name
self.city = city
self.imageurl = imageurl
}
}
foodDataSourceModel:-
class foodDataSourceModel: NSObject {
var dataListArray:Array<foodModel>? = []
init(array :Array<[String:Any]>?) {
super.init()
var newArray:Array<[String:Any]> = []
if array == nil{
newArray = self.getJsonDataStored1()
}
else{
newArray = array!
}
var datalist:Array<foodModel> = []
for dict in newArray{
let model = foodModel(dictionary: dict)
datalist.append(model!)
}
self.dataListArray = datalist
}
}
typealias dummyDataSource1 = foodDataSourceModel
extension dummyDataSource1{
func getJsonDataStored1() ->Array<Dictionary<String,String>>{
let jsonArray = [["name":"Anjapar","imageurl":"","city":"india"],["name":"Anjapar","imageurl":"","city":"india"]] as Array<Dictionary<String,String>>
return jsonArray
}
}
foodViewModel:-
class foodViewModel: NSObject {
var datasourceModel:foodDataSourceModel
init(withdatasource newDatasourceModel:foodDataSourceModel) {
datasourceModel = newDatasourceModel
}
func datafordisplay(atindex index: Int) -> foodModel {
return datasourceModel.dataListArray![index]
}
func numberOfItemsInSection(section:Int) -> Int {
return (datasourceModel.dataListArray?.count)!
}
func loadData(){
loadFromWebserviceData { (newDataSourceModel) in
self.datasourceModel = newDataSourceModel!
}
}
func loadFromWebserviceData(completion :#escaping (foodDataSourceModel?) -> ()){
let url = URL(string :"http://example.com")!
URLSession.shared.dataTask(with: url) { data, _, _ in
if let data = data {
let json = try! JSONSerialization.jsonObject(with: data, options: [])
//let dictionaries = json as! [JSONDictionary]
let array = json as! Array<[String:Any]>
let newDataSource:foodDataSourceModel = foodDataSourceModel(array: array)
// DispatchQueue.main.async {
//
// }
completion(newDataSource)
}
}.resume()
}
}
foodViewController:-
#IBOutlet private weak var tableView: UITableView!
private var foodViewModel :foodViewModel!
init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?, withViewModel viewModel:foodViewModel) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
foodViewModel = viewModel
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
// tableView.register(UINib(nibName: "foodCell", bundle: nil), forCellReuseIdentifier: "cell")
foodViewModel.loadData()
self.tableView .reloadData()
// Do any additional setup after loading the view.
}
// func numberOfSections(in tableView: UITableView) -> Int {
// return restaurtantViewModel.numberOfItemsInSection(section: Int)
// }
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:UITableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "cell")! as! foodCell
//cell.setRestaurtantData(restaurtant: foodModel)
cell.textLabel?.text = "rtyuiop"
//
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
}
*/
}
foodCell:-
class foodCell: UITableViewCell {
#IBOutlet weak var name: UILabel!
#IBOutlet weak var city: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
func setRestaurtantData(restaurtant:foodModel)
{
self.name.text = restaurtant.name
self.city.text = restaurtant.city
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Here output is not getting .I need to display the values in tableview.Showing an error as failed to obtain a cell from dataSource
{
"query": "sandwich",
"results_count": 12,
"page": 1,
"results": [
{
"name": "Caffè Macs",
"coordinates": {
"lat": 37.330576,
"lng": -122.029739
},
"meals": ["breakfast", "lunch", "dinner"]
},
...
]
}
This is the pattern ,so from this i need to get the values as "name","lng" and "lat".
There is some problem in load the data from Json .In the urlsession task -showing as variable not available. please check .How to solve this?
Please update your viewDidLoad(). You must set delegate and datasource of tableview.
First set in class:-
class yourClass: UIViewController,UITableViewDelegate , UITableViewDataSource
Now
override func viewDidLoad() {
super.viewDidLoad()
// tableView.register(UINib(nibName: "foodCell", bundle: nil), forCellReuseIdentifier: "cell")
foodViewModel.loadData()
self.tableView .delegate = self
self.tableview.dataSource = self
self.tableView .reloadData()
When you fetch data from a web service, this is usually done in a asynchronous manner. In your viewDidLoad method, you're updating your table view immediately after the call which starts fetching the data.
override func viewDidLoad() {
...
// Start fetching the data
foodViewModel.loadData()
// Reloading the table view even though the data might not be ready
self.tableView.reloadData()
...
}
You can fix this by passing a callback to your loadData function in your foodViewModel:
func loadData(completion: (() -> ()) {
loadFromWebserviceData { (newDataSourceModel) in
self.datasourceModel = newDataSourceModel!
completion()
}
}
And in your foodViewController, you would then wait to update your table view until the data source is ready to be displayed:
override func viewDidLoad() {
...
foodViewModel.loadData {
self.tableView.reloadData()
}
...
}
While the code above should work, this is just to highlight the problem you're currently facing and therefore, was kept as simple as possible.
I have one screen like the following picture:
I uploaded list with student name by using custom cell as you are seeing and I want when click on save button save the status of student in array , I initialized array with 0 for all student at the first time and when the status of switch is enabled then this value at the clicked cell index converted to 1 but I couldn't make that when the click action happened on switch this is only now happening when click on the cell ( row ) how I can do the same thing when only change the status of switch to update the array without click on complete row at table
Code of main view :
import UIKit
class teacherAttendanceVC: UIViewController , UITableViewDataSource,UITableViewDelegate {
#IBOutlet weak var studentlistTable: UITableView!
#IBOutlet weak var loadIndicator: UIActivityIndicatorView!
var username:String?
var classID: String?
var branchID: String?
var normal_id = [String]()
var student_name = [String]()
var student_attendance = [String]()
//Sent Data
var n_id = ""
var stu_name = ""
#IBAction func backButton(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil )
}
override func viewDidLoad() {
super.viewDidLoad()
studentlistTable.delegate = self
studentlistTable.dataSource = self
let prefs:NSUserDefaults = NSUserDefaults.standardUserDefaults()
username = prefs.objectForKey("user")as! String
classID = prefs.objectForKey("ClassID")as! String
branchID = prefs.objectForKey("BranchID")as! String
self.loadIndicator.startAnimating()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
self.loadList()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.loadIndicator.stopAnimating()
self.studentlistTable.reloadData()
})
});
}
override func viewDidAppear(animated: Bool) {
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return normal_id.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//This method to define each cell at Table View
let cell = self.studentlistTable.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! teacherAttendanceCell
cell.studentNameLabel.text = student_name[indexPath.row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// Get Cell Label
let currentCell = studentlistTable.cellForRowAtIndexPath(indexPath) as! teacherAttendanceCell!
student_attendance[indexPath.row] = currentCell.status
}
#IBAction func saveButton(sender: AnyObject) {
print(student_attendance) // this only to ensure from the final array before sending to server
}
func loadList()
{
var normallink = "myurl"
normallink = normallink + "?classid=" + self.classID! + "&branchid=" + self.branchID!
print(normallink)
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 no_id = onedata["id"] as? String {
normal_id.append(no_id)
}
if let s_name = onedata["studentName"] as? String {
student_name.append(s_name)
}
}
}
} catch {
print("Error Serializing JSON: \(error)")
}
if(normal_id.count != 0)
{
for i in 1...self.normal_id.count
{
self.student_attendance.append("0")
}
}
print(normal_id.count)
print(student_name.count)
}
}
Cell Code :
class teacherAttendanceCell: UITableViewCell {
#IBOutlet weak var studentNameLabel: UILabel!
#IBOutlet weak var attendSwitch: UISwitch!
var status:String = ""
override func awakeFromNib() {
super.awakeFromNib()
if(attendSwitch.on)
{
status = "1"
print("ON")
}
else{
status = "0"
print("OFF")
}
attendSwitch.addTarget(self, action: "stateChanged:", forControlEvents: UIControlEvents.ValueChanged)
}
func stateChanged(switchState: UISwitch) {
if switchState.on {
status = "1"
print("ON")
} else {
status = "0"
print("OFF")
}
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
#IBAction func attendSwitchChanged(sender: AnyObject) {
}
}
Updated:
Main View Controller:
import UIKit
class teacherAttendanceVC: UIViewController , UITableViewDataSource,UITableViewDelegate,CellInfoDelegate {
#IBOutlet weak var studentlistTable: UITableView!
#IBOutlet weak var loadIndicator: UIActivityIndicatorView!
var username:String?
var classID: String?
var branchID: String?
var normal_id = [String]()
var student_name = [String]()
var student_attendance = [String]()
//Sent Data
var n_id = ""
var stu_name = ""
#IBAction func backButton(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil )
}
override func viewDidLoad() {
super.viewDidLoad()
studentlistTable.delegate = self
studentlistTable.dataSource = self
let prefs:NSUserDefaults = NSUserDefaults.standardUserDefaults()
username = prefs.objectForKey("user")as! String
classID = prefs.objectForKey("ClassID")as! String
branchID = prefs.objectForKey("BranchID")as! String
self.loadIndicator.startAnimating()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
self.loadList()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.loadIndicator.stopAnimating()
self.studentlistTable.reloadData()
})
});
}
override func viewDidAppear(animated: Bool) {
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return normal_id.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//This method to define each cell at Table View
let cell = self.studentlistTable.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! teacherAttendanceCell
cell.delegate = self
cell.studentNameLabel.text = student_name[indexPath.row]
student_attendance[indexPath.row] = cell.status
//print(student_attendance.count)
//let currentCell = studentlistTable.cellForRowAtIndexPath(indexPath) as! teacherAttendanceCell!
// student_attendance.append(cell.status)
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// Get Cell Label
// let currentCell = studentlistTable.cellForRowAtIndexPath(indexPath) as! teacherAttendanceCell!
// student_attendance[indexPath.row] = currentCell.status
//print("OK Status here!" + String(student_attendance.count))
}
#IBAction func saveButton(sender: AnyObject) {
print(student_attendance)
}
func loadList()
{
var normallink = "mylinkhere"
normallink = normallink + "?classid=" + self.classID! + "&branchid=" + self.branchID!
print(normallink)
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 no_id = onedata["id"] as? String {
normal_id.append(no_id)
}
if let s_name = onedata["studentName"] as? String {
student_name.append(s_name)
}
}
}
} catch {
print("Error Serializing JSON: \(error)")
}
if(normal_id.count != 0)
{
for i in 1...self.normal_id.count
{
self.student_attendance.append("0")
}
}
print(normal_id.count)
print(student_name.count)
}
func processThatNumber(theStatus: String) {
print("out : \(theStatus)")
}
}
protocol CellInfoDelegate {
func processThatNumber(theStatus: String)
}
Cell View Controller:
import UIKit
class teacherAttendanceCell: UITableViewCell{
#IBOutlet weak var studentNameLabel: UILabel!
#IBOutlet weak var attendSwitch: UISwitch!
var status:String = ""
var delegate: CellInfoDelegate?
override func awakeFromNib() {
super.awakeFromNib()
if(attendSwitch.on)
{
status = "1"
print("ON")
}
else{
status = "0"
print("OFF")
}
attendSwitch.addTarget(self, action: "stateChanged:", forControlEvents: UIControlEvents.ValueChanged)
}
func stateChanged(switchState: UISwitch) {
if switchState.on {
status = "1"
print("ON")
} else {
status = "0"
print("OFF")
}
if let delegate = self.delegate {
delegate.processThatNumber(self.status)
}
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
#IBAction func attendSwitchChanged(sender: AnyObject) {
}
}
There are few ways to do this: using closure or delegate, but I preferred to use delegate.
Create a delegate for your teacherAttendanceCell cell like in this answer https://stackoverflow.com/a/25792213/2739795
Make you teacherAttendanceVC conforms the delegate
Each time when cellForRowAtIndexPath calls set cell.delegate = self. Also return the cell into your delegate method
Call method from delegate insidestateChanged
And when delegate method calls you can get an index if switched cell
tableView.indexPathForCell(cellFromParam)
I have a problem with reload data in tableView in my simple swift app for iOS.
If I for the first time enter the city name into the cityTextField and press the getDataButton, so the data displays correctly, but If I enter the new city name into cityTextField and press button, so data are still the same like for the first city.
ViewController
import UIKit
class ViewController: UIViewController,UITableViewDelegate {
var arrDict :NSMutableArray=[]
#IBOutlet weak var cityTextField: UITextField!
#IBOutlet weak var weatherTableView: UITableView!
#IBAction func getDataButton(sender: AnyObject) {
weatherDataSource("http://api.openweathermap.org/data/2.5/forecast?q=" + cityTextField.text! + "&appid=<app id>")
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func weatherDataSource(urlString: String) {
let urlUTF = urlString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
let url = NSURL(string: urlUTF!)
let query = NSURLSession.sharedSession().dataTaskWithURL(url!) { (data, response, error) in dispatch_async(dispatch_get_main_queue(), { ()
self.loadDataWeather(data!)
self.weatherTableView.reloadData()
})
}
query.resume()
}
func loadDataWeather(dataPocasi: NSData){
do {
if let json = try NSJSONSerialization.JSONObjectWithData(dataPocasi, options: []) as? NSDictionary {
print(json)
for var i = 0 ; i < (json.valueForKey("list") as! NSArray).count ; i++
{
arrDict.addObject((json.valueForKey("list") as! NSArray) .objectAtIndex(i))
}
}
} catch {
print(error)
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return arrDict.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell : TableViewCell! = tableView.dequeueReusableCellWithIdentifier("Cell") as! TableViewCell
if(cell == nil)
{
cell = NSBundle.mainBundle().loadNibNamed("Cell", owner: self, options: nil)[0] as! TableViewCell;
}
let strTitle : NSNumber=arrDict[indexPath.row] .valueForKey("dt") as! NSNumber
let epocTime = NSTimeInterval(strTitle)
let myDate = NSDate(timeIntervalSince1970: epocTime)
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "hh:mm"
let dateString = dateFormatter.stringFromDate(myDate)
cell.dayLabel.text=dateString
let strDescription : NSDictionary=arrDict[indexPath.row] .objectForKey("main") as! NSDictionary
if let bla = strDescription["temp"]{
cell.tempLabel.text=bla.stringValue
}
return cell as TableViewCell
}
}
TableViewCell
import UIKit
class TableViewCell: UITableViewCell{
#IBOutlet weak var dayLabel: UILabel!
#IBOutlet weak var tempLabel: UILabel!
}
You are not instantiating your tableView delegate. Make sure you call self.weatherTableView.delegate = self inside viewDidLoad().
Also, you should create a new arrDict every time you load your data. self.arrDict = [].
In case the above ajustments dont work you should get some time debugging it. Make sure the second request is loading the data and, if so, your self.weatherTableView.reloadData() might not being called. You could try moving it to loadDataWeather().
You can reload tableview in "loadDataWether()" function.
Like,
func loadDataWeather(dataPocasi: NSData){
do {
if let json = try NSJSONSerialization.JSONObjectWithData(dataPocasi, options: []) as? NSDictionary {
print(json)
for var i = 0 ; i < (json.valueForKey("list") as! NSArray).count ; i++
{
arrDict.addObject((json.valueForKey("list") as! NSArray) .objectAtIndex(i))
}
}
} catch {
print(error)
}
self.weatherTableView.reloadData()
}
I can't figure out what is wrong with my tableView: cellForRowAtIndexPath. its never getting called for some reason. i have called the proper delegate and datasource. When I add a print("") line under the cellForRowAtIndexPath function, it never appears when i simulate the app.
Thank you in advanced.
here is my code for the whole page:
class MainPageViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var sportCells = [PFObject]()
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var profilePictureImageView: UIImageView!
#IBOutlet weak var fullNameLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.dataSource = self
self.tableView.delegate = self
//Do any additional setup after loading the view.
}
override func viewDidAppear(animated: Bool) {
updateSportsTable()
print("its happening")
let lastName = PFUser.currentUser()! ["last_name"]
if let firstName = PFUser.currentUser()?["first_name"] as? String {
self.fullNameLabel.text = "\(firstName) \(lastName)"
}
if let userPicture = PFUser.currentUser()?["profile_picture"] as? PFFile {
userPicture.getDataInBackgroundWithBlock { (imageData: NSData?, error: NSError?) -> Void in
if (error == nil) {
self.profilePictureImageView.image = UIImage(data:imageData!)
}
}
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("sportCells count is \(sportCells.count)")
return sportCells.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
print("data extracted1")
let cell = tableView.dequeueReusableCellWithIdentifier("sportCell") as! SportTableViewCell
print("data extracted")
let sportPost = self.sportCells[indexPath.row]
let user = sportPost["user"] as! PFUser
print("data extracted")
do {
try user.fetchIfNeeded()
print("its happening 3rd time")
} catch _ {
print("There was an error")
}
cell.sportTitle.text = sportPost["basketballTitle"] as? String
cell.sportLogo.text = sportPost["basketballLogo"] as? String
cell.numberOfPOTM.text = "5"
return cell
}
func updateSportsTable() {
let query = PFQuery(className: "Sports")
query.findObjectsInBackgroundWithBlock { (sportCells:[PFObject]?, error:NSError?) -> Void in
if error == nil {
self.tableView.reloadData()
print("its happening again")
}
}
}
As confirmed from the comments, you problem is data population in model sportCells.
Ensure that sportCells is populated properly and that you call self.tableView.reloadData after that.