Can someone please tell me what am I doing wrong?
Probably a lot cos I am newbie, but looking forward to solve this!
I am using Koloda libray (https://github.com/Yalantis/Koloda/tree/networking_example) to fetch an Array of Objects into the Card so every card gets a row from my database. I have seen the networking exemple with Alamofire and tried my own code that implements Parse using the same exemple. It is getting the objects from Parse but I have not been able to display them into the cards. Weird, actually I have no errors and the console display "Successfully retrieved 5 objects", but this is only the loadData() function.
I am going to display a lot of text there from a nib!
What am I basically trying to achieve:
I have (MyView.xib, MyView.swift) that provides the labels.
(What I want, is to retrieve from the array to texts into the labels from xib)
I am retrieving the objects but I have not been successful on displaying them into the card:
Successfully retrieved 5 posts.
Optional("EvUICgRQ6E")
Optional("5kC0FLKQON")
Optional("1Uyxb2M1Et")
Optional("aeJpRCG7Qn")
Optional("GDmGh3IULm")
Some Errors:
If I am returning the "numberOfCards" --- I am getting this error:
fatal error: Array index out of range
(lldb)
If I return: "return UInt (self.data.count)"
I am not getting any errors but the cards are not being displayed at all.
I am a bit of a newbie, but pointed into a good direction I will be able to get it done.
This is my ViewController.swift code:
//
// ViewController.swift
// TinderCardsSwift
//
// Created by Eugene Andreyev on 4/23/15.
// Copyright (c) 2015 Eugene Andreyev. All rights reserved.
//
import UIKit
import Koloda
import pop
import Parse
import ParseUI
private var numberOfCards: UInt = 5
class ViewController: UIViewController, KolodaViewDataSource, KolodaViewDelegate {
#IBOutlet weak var kolodaView: KolodaView!
#IBOutlet weak var menuLeft: UIBarButtonItem!
#IBOutlet weak var searchRight: UIBarButtonItem!
var cardsCollection: [MyView] = []
var labelText3 = ""
var labelText4 = ""
var currentObject:PFObject?
override func viewDidLoad() {
super.viewDidLoad()
kolodaView.dataSource = self
kolodaView.delegate = self
menuLeft.target = self.revealViewController()
menuLeft.action = Selector("revealToggle:")
searchRight.target = self.revealViewController()
searchRight.action = Selector("rightRevealToggle:")
self.modalTransitionStyle = UIModalTransitionStyle.FlipHorizontal
loadData()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
}
//MARK: Geting Data From Parse and displaying 5 posts with a print result - WORKING
func loadData (){
if (!cardsCollection.isEmpty) {
self.kolodaView.reloadData()
return
}
let query = PFQuery(className:"Countries")
query.orderByAscending("nameEnglish")
query.findObjectsInBackgroundWithBlock {
(objects:[PFObject]?, error:NSError?) -> Void in
if error == nil {
// The find succeeded.
print("Successfully retrieved \(objects!.count) posts.")
// Do something with the found objects
if let objects = objects {
for object in objects {
let view = NSBundle.mainBundle().loadNibNamed("MyView", owner: self, options: nil)[0] as! MyView
view.label1.text = object["nameEnglish"] as? String
view.label2.text = object["capital"] as? String
self.cardsCollection += [view]
print(object.objectId)
}
}
} else {
// Log details of the failure
print("Error: \(error!) \(error!.userInfo)")
}
}
self.kolodaView.reloadData()
return
}
/*func printData () {
let dataView = NSBundle.mainBundle().loadNibNamed("MyView",
owner: self, options: nil)[0] as? MyView
if let nameEnglish = object?["nameEnglish"] as? String {
let lbl2 = dataView?.label1 as UILabel!
lbl2!.text = nameEnglish
}
//return printData()
}*/
#IBAction func logOut4(sender: AnyObject) {
// Send a request to log out a user
PFUser.logOut()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let viewController:UIViewController = UIStoryboard(name: "SlideMain", bundle: nil).instantiateViewControllerWithIdentifier("Login_Platform")
self.presentViewController(viewController, animated: true, completion: nil)
})
}
override func viewWillAppear(animated: Bool) {
if (PFUser.currentUser() == nil) {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let viewController:UIViewController = UIStoryboard(name: "SlideMain", bundle: nil).instantiateViewControllerWithIdentifier("Login_Platform")
self.presentViewController(viewController, animated: true, completion: nil)
})
}
}
//MARK: IBActions
#IBAction func leftButtonTapped() {
kolodaView?.swipe(SwipeResultDirection.Left)
}
#IBAction func rightButtonTapped() {
kolodaView?.swipe(SwipeResultDirection.Right)
}
#IBAction func undoButtonTapped() {
kolodaView?.revertAction()
}
//MARK: KolodaViewDataSource
func kolodaNumberOfCards(koloda: KolodaView) -> UInt {
return numberOfCards
//return UInt (self.data.count)
//return UInt(cardsCollection.count)
}
func kolodaViewForCardAtIndex(koloda: KolodaView, index: UInt) -> UIView {
//return UIImageView(image: UIImage(named: "Card_like_\(index + 1)"))
return (NSBundle.mainBundle().loadNibNamed("MyView",
owner: self, options: nil)[0] as? MyView)!
//let view = cardsCollection[Int(index)]
//return view
/* let dataView = NSBundle.mainBundle().loadNibNamed("MyView",
owner: self, options: nil)[0] as? MyView
let parseData = data[Int(index)]
dataView?.label1?.text = parseData.labelText
dataView?.label2?.text = parseData.label2Text
return dataView!*/
}
func kolodaViewForCardOverlayAtIndex(koloda: KolodaView, index: UInt) -> OverlayView? {
return NSBundle.mainBundle().loadNibNamed("OverlayView",
owner: self, options: nil)[0] as? OverlayView
}
//MARK: KolodaViewDelegate
func kolodaDidSwipedCardAtIndex(koloda: KolodaView, index: UInt, direction: SwipeResultDirection) {
//Example: loading more cards
if index >= 3 {
numberOfCards = 5
kolodaView.reloadData()
}
}
func kolodaDidRunOutOfCards(koloda: KolodaView) {
//Example: reloading
kolodaView.resetCurrentCardNumber()
loadData()
}
func kolodaDidSelectCardAtIndex(koloda: KolodaView, index: UInt) {
UIApplication.sharedApplication().openURL(NSURL(string: "http://yalantis.com/")!)
}
func kolodaShouldApplyAppearAnimation(koloda: KolodaView) -> Bool {
return true
}
func kolodaShouldMoveBackgroundCard(koloda: KolodaView) -> Bool {
return true
}
func kolodaShouldTransparentizeNextCard(koloda: KolodaView) -> Bool {
return true
}
func kolodaBackgroundCardAnimation(koloda: KolodaView) -> POPPropertyAnimation? {
return nil
}
}
This is MyView.swift (where I defined everything)
//
// MyView.swift
//
//
// Created by Viorel Petrisor on 12/29/15.
// Copyright © 2015 Viorel Petrisor. All rights reserved.
//
import UIKit
class MyView: UIView {
#IBOutlet var label1: UILabel!
#IBOutlet var label2: UILabel!
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func drawRect(rect: CGRect) {
// Drawing code
}
*/
}
MyView has it's own nib.
Gonna place some pictures with my project also:
KolodaView in my Main StoryBoard
Does anybody knows how to make this work? I have been struggling for 10 days now and still didn't get it to work.
I would deeply appreciate some help, hints!
UPDATE: I am now using this function for loadData()
func loadData (){
if (!cardsCollection.isEmpty) {
self.kolodaView.reloadData()
return
}
let query = PFQuery(className:"Countries")
query.orderByAscending("nameEnglish")
query.findObjectsInBackgroundWithBlock {
(objects:[PFObject]?, error:NSError?) -> Void in
if error == nil {
// The find succeeded.
print("Successfully retrieved \(objects!.count) posts.")
// Do something with the found objects
if let objects = objects {
for object in objects {
let view = NSBundle.mainBundle().loadNibNamed("MyView", owner: self, options: nil)[0] as! MyView
view.label1.text = object["nameEnglish"] as? String
view.label2.text = object["capital"] as? String
self.cardsCollection += [view]
print(object.objectId)
}
}
} else {
// Log details of the failure
print("Error: \(error!) \(error!.userInfo)")
}
}
self.kolodaView.reloadData()
return
}
WITH this variable
var cardsCollection: [MyView] = []
I had a similar issue with the Card not getting the data. Apparently, it was a problem with how I was calling the Bundle. Correct Swift 3.0 code below.
func koloda(_ koloda: KolodaView, viewForCardAt index: Int) -> UIView {
let bundle = Bundle(for: MyView.self) // This gets the correct bundle for your class, as sometimes you might have many bundles.
let nib = UINib(nibName: String(describing: MyView.self), bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! MyView
return view
}
Could you please add an issue on GitHub? https://github.com/Yalantis/Koloda/issues
thank you
Related
I am using firebase when I follow user his post show up nicely in the UITableView . but when unfollow him , his post still in the UITableView. UITableView not reloading data after unfollow.
View Controller :
import UIKit
import SVProgressHUD
import SDWebImage
class HomeVC: UIViewController {
#IBOutlet weak var tableViewOutLet: UITableView!
#IBOutlet weak var activityIndicatorView: UIActivityIndicatorView!
var postContentArray = [Post]() // contine all Posts .
var userContentArray = [UserModel]()
override func viewDidLoad() {
super.viewDidLoad()
tableViewOutLet.dataSource = self
tableViewOutLet.estimatedRowHeight = 521
tableViewOutLet.rowHeight = UITableView.automaticDimension
loadPosts()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.tabBar.isHidden = false
}
#objc func loadPosts () {
// activityIndicatorView.startAnimating()
API.Feed.ObserveFeedWithMyPostAndFollowerPost(withid: API.User.Curren_User!.uid) { (postr) in
self.fetchUserInfo(PostUserID: postr.userPostId!, Completed: {
self.postContentArray.append(postr)
// self.activityIndicatorView.stopAnimating()
self.tableViewOutLet.reloadData()
})
}
API.Feed.ObserveFeedReomved(withid: API.User.Curren_User!.uid) { (key) in
// print(key)
self.postContentArray = self.postContentArray.filter {$0.userPostId != key }
self.tableViewOutLet.reloadData()
}
}
#objc func fetchUserInfo (PostUserID : String , Completed : #escaping ()-> Void) {
API.User.observeUserInformation(CommentUserID: PostUserID) { (User) in
self.userContentArray.append(User)
Completed()
}
}
#IBAction func logOutButton(_ sender: Any) {
AuthServices.logout(OnSuccess: {
SVProgressHUD.showSuccess(withStatus: "تم تسجيل الخروج")
let storyBoard = UIStoryboard(name: "Start", bundle: nil)
let signInvc = storyBoard.instantiateViewController(withIdentifier: "SignInVC")
self.present(signInvc, animated: true, completion: nil)
}) { (error) in
SVProgressHUD.showError(withStatus: error)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "commentIconSequeToCommentPage" {
let commentvc = segue.destination as! CommentsVC
commentvc.postID = sender as? String
}
}
}
extension HomeVC: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return postContentArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath) as! HomeTableViewCell
let postContent = postContentArray[indexPath.row]
let userContent = userContentArray[indexPath.row]
cell.postContent = postContent
cell.userContentInfo = userContent
cell.homeView = self
return cell
}
}
Observe Functions :
import Foundation
import FirebaseDatabase
class FeedAPI {
var REF_FEED = Database.database().reference().child("Feed")
func ObserveFeedWithMyPostAndFollowerPost (withid id : String , complation : #escaping (Post)->Void) {
REF_FEED.child(id).observe(DataEventType.childAdded) { (snapshto : DataSnapshot) in
let key = snapshto.key
API.Post.observePostFuntion(withID: key, Complation: { (post) in
complation(post)
})
}
}
func ObserveFeedReomved (withid id : String , complation : #escaping (String)->Void) {
REF_FEED.child(id).observe(DataEventType.childRemoved) { (snapshot : DataSnapshot) in
let key = snapshot.key
complation(key)
}
}
}
where exactly is the unfollow function?
Also you should set the tableview delegate
override func viewDidLoad() {
tableViewOutLet.delegate = self
}
Please show where exactly are you preforming the unfollow function.
my follow And unfollow func
class FollowAPI {
var REF_FOLLOWERS = Database.database().reference().child("Follower")
var REF_FOLLOWING = Database.database().reference().child("Following")
func followAction (withId id : String) {
API.Follow.REF_FOLLOWERS.child(id).child(API.User.Curren_User!.uid).setValue(true)
API.Follow.REF_FOLLOWING.child(API.User.Curren_User!.uid).child(id).setValue(true)
API.myPOSTS.REF_MYPOSTS.child(id).observeSingleEvent(of: DataEventType.value) { (snapshot : DataSnapshot) in
print(snapshot.key)
if let dic = snapshot.value as? [String : Any]{
for key in dic.keys {
API.Feed.REF_FEED.child(API.User.Curren_User!.uid).child(key).setValue(true)
}
}
}
}
func UnFollowAction (withid id : String) {
API.Follow.REF_FOLLOWERS.child(id).child(API.User.Curren_User!.uid).setValue(NSNull())
API.Follow.REF_FOLLOWING.child(API.User.Curren_User!.uid).child(id).setValue(NSNull())
API.myPOSTS.REF_MYPOSTS.child(id).observeSingleEvent(of: DataEventType.value) { (snapshot : DataSnapshot) in
print(snapshot.key)
if let dic = snapshot.value as? [String : Any]{
for key in dic.keys {
API.Feed.REF_FEED.child(API.User.Curren_User!.uid).child(key).removeValue()
}
}
}
}
func isFollwoing (userid : String , Complated : #escaping (Bool)->Void) {
REF_FOLLOWERS.child(userid).child(API.User.Curren_User!.uid).observeSingleEvent(of: .value) { (snapshot ) in
if let _ = snapshot.value as? NSNull {
Complated(false)
} else {
Complated(true)
}
}
}
}
I need to search in the tableview.I have tableview and textfield.While clicking on the textfield it must search the tableview.
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 datasource model:-
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 SearchViewController: UIViewController,UITableViewDelegate,UITableViewDataSource, UISearchBarDelegate,UITextFieldDelegate {
#IBOutlet private weak var tableView: UITableView!
!
#IBOutlet weak var txt: UITextField!
var filteredSearchArray = NSMutableArray()
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")
}
var filteredData: [String]!
override func viewDidLoad() {
super.viewDidLoad()
txt.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: UIControlEvents.editingChanged)
searchViewModel.loadData { (isSuccess) in
if(isSuccess == true)
{
self.tableView .reloadData()
}
else{
}
}
}
#objc private func textFieldDidChange(textField: UITextField) {
if textField.text == "" {
self .viewDidLoad()
}else{
filterContentForSearchText(searchText: textField.text!)
}
}
func filterContentForSearchText(searchText: String) {
filteredSearchArray = NSMutableArray(array:(searchViewModel.datasourceModel.dataListArray?.filter({(ele:AnyObject) -> Bool in
return (ele as! SearchModel).restaurantname.lowercased().contains(searchText.lowercased())
}))!)
tableView.reloadData()
}
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))
return cell
}
}
my tableviewcell:-
class SearchCell: UITableViewCell {
#IBOutlet weak var name: UILabel!
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
}
func setsearchData(search:SearchModel)
{
self.name.text = search.restaurantname
}
}
This is my code but in the filteredSearchArray always shows as 0 element.
Here the list of names is displaying but clicking on the textfield it doesn't searching and not reloading. How to solve the problem.
The data is not coming in this code:-
func filterContentForSearchText(searchText: String) {
filteredSearchArray = NSMutableArray(array:(searchViewModel.datasourceModel.dataListArray?.filter({(ele:AnyObject) -> Bool in
return (ele as! SearchModel).restaurantname.lowercased().contains(searchText.lowercased())
}))!)
tableView.reloadData()
}
First of all one important thing don't use NSArray, NSDictionary in swift use Array, Dictionary instead.
I have made a change in your model class:
class SearchModel: NSObject {
var restaurantname :String!
init(dictionary :JSONDictionary) {
self.restaurantname = dictionary["name"] as? String ?? ""
}
}
Now filter your array like this:
filteredSearchArray = searchViewModel.datasourceModel.dataListArray?.filter {$0.restaurantname.lowercased().contains(searchText.lowercased())}
And now pass filteredSearchArray in tableView datasource then reload the table. You can take a bool variable isSearching to check which array you have to pass in datasource the filtered one the original. Toggle this isSearching in textFieldDidBeginEiditng and textFieldDidEndEiditng method.
I have tested it by below example in my playground:
var models: Array<SearchModel> = [SearchModel.init(dictionary: ["name": "Khalsa Dhaba"]), SearchModel.init(dictionary: ["name": "Yo! China"]), SearchModel.init(dictionary: ["name": "Sher-e-punjab"]), SearchModel.init(dictionary: ["name": "Haveli"])]
let result = models.filter {$0.restaurantname.lowercased().contains("o!".lowercased())}
print(result)
It works fine!
Secondly I noticed you're reloading your view by calling self.viewDidLoad() method which you should not call ever this calls itself and it is a function of viewContoller lifecycle. Call tableView.reloadData() instead.
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 was following a Swift tutorial which use a xib file as view controller and was trying to get it into the storyboard. I use xCode7 and Swift 2.1 I get some problem for the codes below in particular:
var cell:CatsTableViewCell? = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? CatsTableViewCell
if(cell == nil) {
cell = NSBundle.mainBundle().loadNibNamed("CatsTableViewCell", owner: self, options: nil)[0] as? CatsTableViewCell
}
How can I translate this one above into the one to use in the project with the storyboard?
I got some problem here below as well. I start using xCode not a long time ago and I am a little bit confused about the meaning of the code below. I've tried to google it but I have just got very detailed explanation hard to understand as a beginner.
required init(coder aDecoder:NSCoder)
{
fatalError("NSCoding not supported")
}
Here below you can find the whole code of the view controller and the link to the full tutorial. Hope somebody can help me, please. Thanks in advance.
http://www.appcoda.com/instagram-app-parse-swift/
//
// CatsTableViewController.swift
// Paws
//
// Created by Simon Ng on 15/4/15.
// Copyright (c) 2015 AppCoda. All rights reserved.
//
import UIKit
class CatsTableViewController: PFQueryTableViewController {
let cellIdentifier:String = "CatCell"
override func viewDidLoad() {
tableView.registerNib(UINib(nibName: "CatsTableViewCell", bundle: nil), forCellReuseIdentifier: cellIdentifier)
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func queryForTable() -> PFQuery {
let query:PFQuery = PFQuery(className:self.parseClassName!)
if(objects?.count == 0)
{
query.cachePolicy = PFCachePolicy.CacheThenNetwork
}
query.orderByAscending("name")
return query
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {
var cell:CatsTableViewCell? = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? CatsTableViewCell
if(cell == nil) {
cell = NSBundle.mainBundle().loadNibNamed("CatsTableViewCell", owner: self, options: nil)[0] as? CatsTableViewCell
}
cell?.parseObject = object
if let pfObject = object {
cell?.catNameLabel?.text = pfObject["name"] as? String
var votes:Int? = pfObject["votes"] as? Int
if votes == nil {
votes = 0
}
cell?.catVotesLabel?.text = "\(votes!) votes"
var credit:String? = pfObject["cc_by"] as? String
if credit != nil {
cell?.catCreditLabel?.text = "\(credit!) / CC 2.0"
}
cell?.catImageView?.image = nil
if var urlString:String? = pfObject["url"] as? String {
var url:NSURL? = NSURL(string: urlString!)
if var url:NSURL? = NSURL(string: urlString!) {
var error:NSError?
var request:NSURLRequest = NSURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.ReturnCacheDataElseLoad, timeoutInterval: 5.0)
NSOperationQueue.mainQueue().cancelAllOperations()
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {
(response:NSURLResponse?, imageData:NSData?, error:NSError?) -> Void in
cell?.catImageView?.image = UIImage(data: imageData!)
})
}
}
}
return cell
}
override init(style: UITableViewStyle, className: String!)
{
super.init(style: style, className: className)
self.pullToRefreshEnabled = true
self.paginationEnabled = false
self.objectsPerPage = 25
self.parseClassName = className
self.tableView.rowHeight = 350
self.tableView.allowsSelection = false
}
required init(coder aDecoder:NSCoder)
{
fatalError("NSCoding not supported")
}
/*
// 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.
// Pass the selected object to the new view controller.
}
*/
}
Change below code
var cell:CatsTableViewCell? = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? CatsTableViewCell
if(cell == nil) {
cell = NSBundle.mainBundle().loadNibNamed("CatsTableViewCell", owner: self, options: nil)[0] as? CatsTableViewCell
}
to
let cell = tableView.dequeueReusableCellWithIdentifier("CatsTableViewCell", forIndexPath: indexPath) as! CatsTableViewCell
And for "required" keyword check link What does the "required" keyword in Swift mean?
Your viewController should have a property for the tableview, like this:
#IBOutlet var tableview : UITableView?
Then in your storyboard, connect the tableview to that outlet (tutorials on connecting outlets abound, or let me know if you get stuck). Then, in viewDidLoad, call the same method you have above: self.tableView.registerNib etc.
I am making some good progress on my social networking application. I have run into an issue. I have a ViewController that provides a TableView that is populated with content from my parse database. In the cells I have a RSVP button that is supposed to send a RSVP based on the indexPath to the database when clicked and remove when it is clicked again. I believe my logic is correct, however, I keep receiving the error:
Operation is invalid after previous operation.
I placed a breakpoint to locate the cause of the crash and I have identified that it is happening at the addUniqueObject line within the rsvpButtonClicked IBOutlet function.
Can someone help me? My code is below.
import UIKit
import CoreLocation
class MainFeedViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var eventsTable: UITableView!
var user = PFUser.currentUser()
var refresher: UIRefreshControl!
var eventId = [String]()
var eventNames = [String]()
var eventCity = [String]()
var imageFiles = [PFFile]()
var getEventsQuery = 0
var userRsvps = [NSArray]()
var rsvp = 0
override func viewDidLoad() {
super.viewDidLoad()
getuserlocation()
getTodayDate()
}
override func viewWillAppear(animated: Bool) {
refreshControl()
//getMyRsvps()
}
override func viewDidAppear(animated: Bool) {
let timer = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: "eventQuery", userInfo: nil, repeats: false)
}
func getMyRsvps() {
var getRsvps = PFUser.query()
getRsvps.whereKey("objectId", equalTo: user.objectId)
getRsvps.whereKeyExists("myrsvp")
getRsvps.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
self.userRsvps.append(objects)
}
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.eventsTable.dequeueReusableCellWithIdentifier("mainFeedContent") as MainFeedContentTableViewCell
cell.eventName.text = eventNames[indexPath.row]
imageFiles[indexPath.row].getDataInBackgroundWithBlock{
(imageData: NSData!, error: NSError!) -> Void in
if error == nil {
let image = UIImage(data: imageData)
cell.eventImage.image = image
}
}
cell.rsvpButton.tag = indexPath.row
cell.rsvpButton.addTarget(self, action: "rsvpButtonClick:", forControlEvents: UIControlEvents.TouchUpInside)
return cell
}
#IBAction func rsvpButtonClick(sender: UIButton) {
var senderButton = sender
println("Current row \(senderButton.tag)")
var tempObject = eventId[senderButton.tag]
println("\(tempObject)")
PFUser.currentUser().addUniqueObject(tempObject, forKey: "myrsvp")
PFUser.currentUser().saveInBackground()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return eventId.count
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let mainViewIdentifier = "showDetail"
if segue.identifier == mainViewIdentifier {
if let destination = segue.destinationViewController as? DetailViewController {
if let feedIndex = eventsTable.indexPathForSelectedRow()?.row {
destination.eventNames = eventNames[feedIndex]
destination.eventId = eventId[feedIndex]
destination.eventImagesFile = imageFiles[feedIndex]
}
}
}
}
func eventQuery() {
let getEventsQuery = PFQuery(className: "Events")
getEventsQuery.whereKey("eventLocation", nearGeoPoint: user["location"] as PFGeoPoint, withinMiles: user["preferredDistanceEvents"] as Double)
getEventsQuery.limit = 16
getEventsQuery.findObjectsInBackgroundWithBlock {(objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
println("Successfully retrieved \(objects.count) events")
for object in objects {
self.eventId.append(object.objectId)
self.eventNames.append(object["eventName"] as String)
self.eventCity.append(object["eventCity"] as String)
self.imageFiles.append(object["eventPicture"] as PFFile)
self.eventsTable.reloadData()
}
} else {
println(error)
}
}
}
func refreshControl() {
refresher = UIRefreshControl()
refresher.attributedTitle = NSAttributedString(string: "Pull to refresh")
refresher.addTarget(self, action: "refresh", forControlEvents: UIControlEvents.ValueChanged)
self.eventsTable.addSubview(refresher)
}
/*
func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
var height: CGFloat = scrollView.frame.size.height
var contentYoffset: CGFloat = scrollView.contentOffset.y
var distanceFromBottom: CGFloat = scrollView.contentSize.height - contentYoffset
if distanceFromBottom <= height {
println("End of Table")
refresh()
}
}
*/
func refresh() {
self.getEventsQuery++
if self.getEventsQuery < self.eventId.count {
let refreshEventsQuery = PFQuery(className: "Events")
refreshEventsQuery.whereKey("location", nearGeoPoint: user["location"] as PFGeoPoint, withinMiles: user["preferredDistanceEvents"] as Double)
refreshEventsQuery.whereKey("objectId", notContainedIn: eventId)
refreshEventsQuery.limit = 4
refreshEventsQuery.findObjectsInBackgroundWithBlock {(objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
println("Successfully retrieved \(objects.count) events")
for object in objects {
self.eventNames.append(object["eventName"] as String)
self.eventCity.append(object["City"] as String)
self.imageFiles.append(object["eventPicture"] as PFFile)
self.eventId.append(object.objectId)
self.eventsTable.reloadData()
}
} else {
println(error)
}
}
} else {
println("No More Events. Sorry")
}
self.refresher.endRefreshing()
}
func getuserlocation() {
PFGeoPoint.geoPointForCurrentLocationInBackground { (geopoint: PFGeoPoint!, error: NSError!) -> Void in
if error == nil {
self.user["location"] = geopoint
self.user.saveInBackground()
}
}
}
func getTodayDate(){
var today = NSDate()
var calendar = NSCalendar.currentCalendar()
var flags = NSCalendarUnit.HourCalendarUnit | NSCalendarUnit.MinuteCalendarUnit
var components = calendar.components(flags, fromDate: today)
var hour = components.hour
var minutes = components.minute
println("Today is \(today). The time is \(hour):\(minutes)")
}
}
I think this is a bug in parse (in code shared with JS, because I've experienced the problem there). Specifically, this failure appears when intermixing the add and remove PFObject methods to manipulate array columns.
I've used both of the following workarounds with some success:
Delimit adds and removes with intervening saves. In other words, build your own addToColAndSave and removeFromColAndSave convenience methods. If you've called one of them, don't call the other until the save completes.
Probably easier: restructure the code to avoid the add/remove methods on arrays. Instead, use the getter (get in JS, objectForKey: in iOS) to get the array in memory, then manipulate it natively. Use the sdk setter to update the object.