UITableView in swift - swift

can anyone tell me what's wrong with my code i always get the same data repeated in all cells
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel!.textColor = UIColor.whiteColor()
let query = PFQuery(className:"book")
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
var contentString:String = String()
if error == nil {
print("Success retrieved \(objects!.count) scores.")
if let objects = objects {
for object in objects {
let a:String = object.objectForKey("title") as! String
contentString = a
}
}
cell.textLabel!.text = contentString
}}
return cell
}

It will be better to query all your data into viewDidLoad() or any life cycle you would like.
var contentString = [String]() //<-- use an array of string instead of a string variable
override func viewDidLoad()
{
super.viewDidLoad()
let query = PFQuery(className:"book"){ query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
print("Success retrieved \(objects!.count) scores.")
if let objects = objects {
for object in objects
{
let value = object["title"] as! String
self.contentString.append(value) //<-- save the query value to your array
}
self.tableView.reloadData() //<--- then you reload your UI
}
}}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel!.textColor = UIColor.whiteColor()
cell.textLabel!.text = self.contentString[indexPath.row] //<-- then assign the value into your cell
return cell
}

content inside your loop should be like this.
let a:String = object.objectForKey("title") as! String
contentString += a
and i noticed your block calls for same query always. can you tell me whats the different there
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
var contentString:String = String()
if error == nil {
print("Success retrieved \(objects!.count) scores.")
if let objects = objects {
for object in objects {
let a:String = object.objectForKey("title") as! String
contentString = a
}
}
cell.textLabel!.text = contentString
}}

The query in cellForRowAtIndex is trouble. Imagine, every time a cell comes into view, the code asks for every book from the server.
Put the query outside the datasource method (viewWillAppear, for example). When the query is complete, initialize an array property with the results (e.g. self.bookObjects = objects).
Then in cellForRowAtIndex...
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel!.textColor = UIColor.whiteColor()
// this is the important idea...
let object = self.bookObjects[indexPath.row]
let a:String = object.objectForKey("title") as! String
cell.textLabel!.text = a
return cell

Related

How do I get the value from the model to the controller

This is my first program using MVC design pattern, I'm stuck how to get the values from the model to my controller and to display it in my view. I'll show you what I have done. Kindly clarify me what I did wrong? Or show me how it can be done in other way around.
Model
class songData: NSObject {
var artistName: String
var albumName: String
init(artistName: String, albumName: String) {
self.artistName = artistName
self.albumName = albumName
}
}
Controller
#IBAction func doTheSearch(sender: AnyObject) {
itunesAPI().itunesSearch({(song : songData) in
})
self.tableView.reloadData()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return song1.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
var artistAndAlbum = itunesAPI().array[indexPath.row]
cell.textLabel?.text =
cell.detailTextLabel?.text =
return cell
}
API
func itunesSearch(completionHandler:(songData)->()) {
Alamofire.request(.GET, "http://itunes.apple.com/search?", parameters: ["term" : "tamil new songs", "media" : "music"])
.responseJSON { (response) in
let json = JSON(response.result.value!)
if let jsonData = json["results"].arrayObject {
self.array = jsonData as! [[String : AnyObject]]
if self.array.count > 0 {
// self.array = jsonData as! [[String : AnyObject]]
// if let resultsDict = resultsArray.first {
let albumName = json["results"]["collectionName"].stringValue
let artistName = json["results"]["artistName"].stringValue
let song = songData(artistName: artistName, albumName: albumName)
completionHandler(song)
}
}
I do have the nothing on my view except the story board which consists of a table view with a single cell. I need to get the response from the API and show it in the view.
First, you're going to want to reload your table after the data is returned. Update your IBAction to this:
itunesAPI().itunesSearch({(song : songData) in
self.tableView.reloadData()
})
Otherwise reloadData will get called before the data is returned. Set a property on the viewController to house the data. Also, it's good practice to start a class name with a capital letter.
var tableData:[SongData] = [SongData]()
Then set this variable when the data successfully returns:
itunesAPI().itunesSearch({(song : songData) in
self.tableData.append(song) // add the result to the list of data
self.tableView.reloadData() // reload the table
})
Then set the cells as so:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
var artistAndAlbum = self.tableData[indexPath.row]
cell.textLabel?.text = artistAndAlbum.artistName
cell.detailTextLabel?.text = artistAndAlbum.albumName
return cell
}

Swift: Bool if true, doesn't display image

I'm a beginner so please be patient explaining, Thanks.
So, basically I have a bool column in parse and I want to display an image if it's false and don't display anything if its true.
here are my codes:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCellWithIdentifier("todayCell", forIndexPath: indexPath) as! reqTodaysCell
let cellDataParse: PFObject = self.dataparse.objectAtIndex(indexPath.row) as! PFObject
var newReadQuery = PFQuery(className: "request")
newReadQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
for object in objects {
if object["reqRead"] as! Bool == true {
myCell.isRead.image = nil //here is where I say pic to be nil but what happens is that if the first one is true then it will remove the pic for all of them.
// and if its not true it should display the pic
} else {
myCell.isRead.image = UIImage(named: "newReq")
print("user not read")
}
}
}
})
If I don't explain properly please let me know and I will try my best to explain again.
This sounds like an ideal use case for a ternary operator. As per my example below, you use the ? : syntax following a Bool, if the bool is true it will return the first case and if it's false it will return the second case.
newReadQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
for object in objects {
let reqRead = object["reqRead"] as! Bool
cell.image.image = reqRead ? nil : UIImage(named: "newReq")
}
}
})
UPDATE
The above may not have worked as the Parse call might not be completed before the cells are loaded.
Create a global variable (outside of any function):
var reqRead = [Bool]()
In ViewDidLoad you can create an array of the bools.
var newReadQuery = PFQuery(className: "request")
newReadQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
for object in objects {
reqRead.append(object["reqRead"] as! Bool)
}
tableView.reloadData()
}
})
Then in your CellForRow:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCellWithIdentifier("todayCell", forIndexPath: indexPath) as! reqTodaysCell
let cellDataParse: PFObject = self.dataparse.objectAtIndex(indexPath.row) as! PFObject
cell.image.image = reqRead[indexPath.row] ? nil : UIImage(named: "newReq")
return cell
}
There's a possibility that it will try to populate the cells before the array is loaded but let me know if this works for you.
if object["reqRead"] as! Bool == false {
myCell.isRead.image = nil
myCell.isRead.hidden = false
} else {
myCell.isRead.hidden = true
}

TableView extension swift 2 image hidden

I am using Swift 2 with XCode 7.2 in my extension. I am rendering UITableView with Cells that have image and label in it the problem is that the image are hidden ! Idn't know why! can anyone help me please
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel!.textColor = UIColor.whiteColor()
let query = PFQuery(className:"Recipe")
query.orderByDescending("createdAt")
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
print("Success retrieved \(objects!.count) scores.")
if let objects = objects {
for object in objects {
let a:String = object.objectForKey("title") as! String
self.contentString.append(a)
}
}
let cellImg : UIImageView = UIImageView(frame: CGRectMake(5, 5, 50, 50))
cellImg.backgroundColor=UIColor.whiteColor()
cellImg.image = UIImage(named: "jj.png")
// cell.addSubview(cellImg)
cell.imageView!.image=cellImg.image
cell.textLabel!.text = self.contentString[indexPath.row]
}}
return cell
}

Unable to load and display data from parse

var findPublisher:PFQuery = PFUser.query()!
findPublisher.whereKey("objectId", equalTo: quote.objectForKey("publisher")!)
findPublisher.findObjectsInBackgroundWithBlock{
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
if let objects = objects as? [PFUser] {
for object in objects {
//println(object.objectId)
let user:PFuser = (objects as NSArray).lastObject as PFUser
cell.publisherLabel.text = user.username
}
}
}
// Configure the cell...
}
The code here is supposed to query for the objectId and display the username instead of the label. I am getting an error that says use of undeclared type of 'PFUser'... I used "println" right after the error == nil statement and it logs correctly so the error definitely occurs after there.
if you are using a TableViewController, you don't need to create an Outlet of the tableview. So you need to query all the objects from the _User class into an array. So it is up to you to know where you want to place this code either in the ViewDidLoad or ViewWillAppear.
var arrayOFUser :NSMutableArray = []
var findPublisher:PFQuery = PFQuery(className:"_User")
findPublisher.findObjectsInBackgroundWithBlock{ (objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil{
if let objects = objects as? [PFObject] {
for object in objects {
var getusername = object["username"] as! String
self.arrayOFUser.addObject(getusername)
self.tableview.reloadData()
}
}
}
}
// return the count of user into the each cell in the tableview
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.arrayOFUser.count
}
then you go into the ** cellForRowAtIndexPath** method
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = self.tableview.dequeueReusableCellWithIdentifier("CellSubtitle", forIndexPath: indexPath) as! UITableViewCell
let name = self.arrayOFUser[indexPath.row] as! String
cell.textlabel?.text = name
return cell
}
QuickNote "CellSubtitle" is the name of the cell in the tableview so go into the storyboard in change it.

Swift: UICollectionView & UIImage fatal error: Array index out of range

Hi Im new to swift and need some help thank you. The program worked once, tried to run it again then it crashed. The items are in the array when I debugged but when I try to display the images I get the fatal error.
// Get Brands
func getBrand () {
// Create PFQuery
var query:PFQuery = PFQuery(className: "BrandInfo")
// Call findobjects
query.findObjectsInBackgroundWithBlock {
(objects:[AnyObject]?, error: NSError?) -> Void in
// refresh array
self.brands = [String]()
self.pics = [UIImage]()
// loop through array
for brandObject in objects! {
// get PFObjects
let brandName:String? = (brandObject as! PFObject)["Name"] as? String
if brandName != nil {
self.brands.append(brandName!)
}
let brandPicture = brandObject["Image"] as! PFFile
brandPicture.getDataInBackgroundWithBlock({ (imageData:NSData?, error:NSError?) -> Void in
if(error == nil){
let brandImage = UIImage(data: imageData!)
self.pics.append(brandImage)
println(self.pics.count)
}
})
}
// Refresh CollectionView
self.collectionView.reloadData()
}
}
// Setting up collection view
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.brands.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell:collectionViewCell = self.collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! collectionViewCell
// Get elements
let picToDisplay:UIImage? = pics[indexPath.row] // this is the error line
let dataToDisplay:String = brands[indexPath.row]
let imageView:UIImageView? = cell.viewWithTag(2) as? UIImageView
// Set labels
cell.brandImage.image = picToDisplay
cell.brandLabel.text = dataToDisplay
return cell
}
///////////////////////////////
struct brandCollection {
var brandText:[String] = [String]()
var brandImage:[UIImage?] = [UIImage]()
}
You have brands.count items, and you need brand.count images. But you are using a different array pics which will fail if it has less elements than brands. Looking at your code, there are several possibilities why this could happen.
This is bad design. You should have a data array that encapsulates all the information you need. Each image should be connected to its object (the brand), not held in some other array.