I have been following a tutorial on Youtube which helps you create an app like Twitter using Parse as a backend service. So far I was able to add things to classes in Parse but I was either not able to retrieve them or display them in my table view.
I believe this is where my mistake is:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:messageTableViewCell = tableView!.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath!) as messageTableViewCell
let sweet:PFObject = self.timelineData.objectAtIndex(indexPath!.row) as PFObject
cell.messageTextView.alpha = 0
cell.timestampLabel.alpha = 0
cell.usernameLabel.alpha = 0
cell.messageTextView.text = sweet.objectForKey("content") as String
var dataFormatter:NSDateFormatter = NSDateFormatter()
dataFormatter.dateFormat = "yyyy-MM-dd HH:mm"
cell.timestampLabel.text = dataFormatter.stringFromDate(sweet.createdAt)
var findSweeter:PFQuery = PFUser.query()
findSweeter.whereKey("objectId", equalTo: sweet.objectForKey("username").objectId)
findSweeter.findObjectsInBackgroundWithBlock{
(objects:[AnyObject]!, error:NSError!)->Void in
if error == nil{
let user:PFUser = (objects as NSArray).lastObject as PFUser
cell.usernameLabel.text = user.username
UIView.animateWithDuration(0.5, animations: {
cell.messageTextView.alpha = 1
cell.timestampLabel.alpha = 1
cell.usernameLabel.alpha = 1
})
}
}
return cell
}
If you could help me figure this out I would really appreciate it, also please try to be detailed.
The error might also be here, I'm completely lost so I will post this as well!
func loadData(){
timelineData.removeAllObjects()
var findTimelineData:PFQuery = PFQuery(className: "Messages")
findTimelineData.findObjectsInBackgroundWithBlock{
(objects:[AnyObject]!, error:NSError!)->Void in
if error == nil{
for object in objects{
let message:PFObject = object as PFObject
self.timelineData.addObject(message)
}
let array:NSArray = self.timelineData.reverseObjectEnumerator().allObjects
self.timelineData = NSMutableArray(array: array)
self.tableView.reloadData()
}
}
}
Related
Here is function where I try to fetch images from parse for users that are in the namesArray.
func fetchData(){
let imagePredicate = NSPredicate(format: "username IN %#", namesArray)
let imageQuery = PFQuery(className: "_User", predicate: imagePredicate)
imageQuery.findObjectsInBackgroundWithBlock { (objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
for object in objects! {
self.imagesArray.append(object["image"] as! PFFile)
if self.imagesArray.count == self.namesArray.count {
self.tableView.reloadData()
}
} else {
print("error: \(error?.localizedDescription)")
}
}
}
Here is my tableView:cellForRowAtIndexPath method:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! ChatsCell
cell.nameLabel.text = namesArray[indexPath.row]
if imagesArray.count == namesArray.count && self.imagesLoaded == false{
imagesArray[indexPath.row].getDataInBackgroundWithBlock { (imageData: NSData?, error: NSError?) -> Void in
if error == nil {
let image = UIImage(data: imageData!)
cell.imageView?.image = image
self.tableView.reloadData()
self.imagesLoaded = true
}
}
}
return cell
}
But when I do so I see that images are not synchronised with names of the users. Even if I put my users in other order images will stay in the same order as they was before.
How can I change it?
Not sure what you're asking here. Is it that you were expecting the images to be returned in an array sorted by the user?
If so, then you will need to add a sort order to your PFQuery. I suggest you sort your namesArray by username, and then also sort the imageQuery by username:
imageQuery.orderByDescending("username")
Hope I understood the question ;]
--T
So I found that if you use one query you will receive ordered data so I've changed my code and now it works pretty well. So what I've done is that I do query for every separate member of the namesArray:
func fetchData() {
for index in 0..<self.namesArray.count {
let imagePredicate = NSPredicate(format: "username == %#", namesArray[index])
let imageQuery = PFQuery(className: "_User", predicate: imagePredicate)
imageQuery.findObjectsInBackgroundWithBlock({ (objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
for object in objects! {
self.imageFilesArray![index] = object["image"] as? PFFile
}
for imageFile in self.imageFilesArray! {
let index = self.imageFilesArray?.indexOf{$0 == imageFile}
imageFile?.getDataInBackgroundWithBlock({ (imageData: NSData?, error: NSError?) -> Void in
let userImage = UIImage(data: imageData!)
self.imagesArray?[index!] = userImage
self.tableView.reloadData()
})
}
}
})
}
}
and here is tableView:cellForRowAtIndexPath:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! ChatsCell
cell.nameLabel.text = namesArray[indexPath.row]
cell.messageTextLabel.text = messagesArray[indexPath.row]
cell.chatImageView.image = self.imagesArray![indexPath.row] != nil ? self.imagesArray![indexPath.row] : UIImage(named: "add")
return cell
}
I have an array with song titles, and I am adding a play button to each cell with a title, but when I click the play button it crashes, I get the array out of index error. Why is this error occurring? How do I fix it?
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = table.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.textLabel?.text = ret[indexPath.row]
let playButton : UIButton = UIButton(type: UIButtonType.Custom)
playButton.tag = indexPath.row
let imageret = "playbutton"
playButton.setImage(UIImage(named: imageret), forState: .Normal)
playButton.frame = CGRectMake(230, 20, 100, 100)
playButton.addTarget(self,action: "playit:", forControlEvents: UIControlEvents.TouchUpInside)
for view: UIView in cell.contentView.subviews {
view.removeFromSuperview()
}
cell.contentView.addSubview(playButton)
return cell
}
Below is the code for playing the song based on which play button is clicked.
func playit(sender: UIButton!){
let cell = table.dequeueReusableCellWithIdentifier("cell")
let playButtonrow = sender.tag
print(titleatcell[playButtonrow])
if let nowPlaying = musicPlayer.nowPlayingItem{
let title = nowPlaying[MPMediaItemPropertyTitle] as? String
let artist = nowPlaying[MPMediaItemPropertyTitle] as? String
print("now playing \(title!) \(artist!)")
print("cell: \(playButtonrow) \(titleatcell[playButtonrow])")
let query = PFQuery(className: "Songs")
query.whereKey("SongName", equalTo: ret[playButtonrow])
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
print("Successfully retrieved \(objects!.count) song(s).")
// Do something with the found objects
if let objects = objects as? [PFObject] {
for object in objects {
print(object.objectId)
print(playButtonrow)
let object = object as PFObject
let parseAudio = object.valueForKey("SongFile") as! PFFile
let audioPath: String = parseAudio.url!
let urlParse: NSURL = NSURL(string: audioPath)!
player = AVPlayer(URL: urlParse)
player.volume = 1.0
//let timeInterval: NSTimeInterval = 10.0
//let timesArray = [NSValue(CMTime: CMTimeMake(Int64(timeInterval), 1))]
timeObserver = player.addBoundaryTimeObserverForTimes([30.0], queue:nil) { () -> Void in
print("30s reached", terminator: "")
player.removeTimeObserver(timeObserver)
player.pause()
}
player.play()
}
}
} else {
// Log details of the failure
print("Error: \(error!) \(error!.userInfo)")
}
}
}
}
"Fatal error: Array index out of range"
this error occurs when you try to access an array index that does not exist. maybe you're not getting parse the data, and when you click the button start , xcode tries to access a pointer that does not exist .... but we need more information to help you effectively
The error is in let USER:PFUser... It was working good but when I updated Xcode this problem appeared. The name of the username is not being displayed.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let postcells: postsTableViewCell = tableView.dequeueReusableCellWithIdentifier("PostCell", forIndexPath: indexPath) as! postsTableViewCell
let Post:PFObject = self.PostData.objectAtIndex(indexPath.row) as! PFObject
postcells.postTimetextView.text = Post.objectForKey("Content") as! String
var dateFormatter:NSDateFormatter = NSDateFormatter()
dateFormatter.dateStyle = NSDateFormatterStyle.NoStyle
dateFormatter.timeStyle = NSDateFormatterStyle.ShortStyle
postcells.timeStamp.text = dateFormatter.stringFromDate(Post.createdAt!)
var findPostedBy:PFQuery = PFUser.query()!
findPostedBy.whereKey("objectId", equalTo: Post.objectForKey("Postedby")!)
findPostedBy.findObjectsInBackgroundWithBlock{
(objects, error) -> Void in
if error == nil {
let USER:PFUser = (objects as NSArray).lastObject as! PFUser
postcells.usernameLabel3.text = USER.username
}
}
return postcells
}
You need to make sure that an array was returned from parse
You can use this:
findPostedBy.findObjectsInBackgroundWithBlock{
(objects, error) -> Void in
if error == nil {
if objects?.count > 0 {
let USER:PFUser = objects!.last as! PFUser
// Avoid updating the UI on a background thread
dispatch_async(dispatch_get_main_queue(), { () -> Void in
postcells.usernameLabel3.text = USER.username
})
}
}
}
I'm making an social application in which I want to display the comments from the users.
Now sometimes when I open the VC it will display the same cell twice (or sometimes even more). See the picture below:
The strange thing is when I 'println' the objects from the 'PFQuery Block' in the CellForRowAtIndexPath it shows the println 2 times or more. I have no idea how this comes.. Something to do with CachePolicy maybe?
P.s: No answer found at same problem: Here
}else {
let commentCell:commentTableViewCell = tableView.dequeueReusableCellWithIdentifier("commentCell") as commentTableViewCell
let commentIndex:NSIndexPath = NSIndexPath(forRow: indexPath.row-2, inSection: 0)
let comment:PFObject = userComments.objectAtIndex(commentIndex.row) as PFObject
// Comment Label
commentCell.commentLabel.text = comment.objectForKey("content") as String!
// Datum
let date:NSDate = NSDate(timeIntervalSinceNow: 1)
let string:NSString = date.timeAgoSinceDate(comment.createdAt)
commentCell.datumLabel.text = string
// Load each comment after row: 1
var userCommentImage:PFQuery = PFUser.query()
userCommentImage.whereKey("objectId", equalTo: comment.objectForKey("gebruiker").objectId)
userCommentImage.findObjectsInBackgroundWithBlock({
(objects:[AnyObject]!, error:NSError!) -> Void in
if error == nil{
println("How many reactions are there? = \(objects.count)")
let user:PFUser = (objects as NSArray).firstObject as PFUser
commentCell.userLabel.text = user.username
// Profile Image
let profileImage:PFFile = user["profileImage"] as PFFile
profileImage.getDataInBackgroundWithBlock({
(imageData:NSData!, error:NSError!) -> Void in
if error == nil{
let image = UIImage(data: imageData)
commentCell.userImageView.image = image
UIView.animateWithDuration(0.5, animations: {
commentCell.userImageView.alpha = 1
commentCell.userLabel.alpha = 1
commentCell.datumLabel.alpha = 1
commentCell.commentLabel.alpha = 1
})
}
})
}
})
return commentCell
}
While reloading a tableView the app crashes and I am getting error
malloc:
error for object 0x7f8c7b99be80: pointer being freed was not allocated
set a breakpoint in malloc_error_break to debug
I have set the Symbolic breakpoint for
malloc_error_break
Also try to find memory leakage with "Instruments" but it just showing same error in console but here is no any memory leakage.
How to solve this issue.
(I am using 8.3 SDK and 6.3.1 Xcode)
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var ResultCellIdentifier = "placementID"
var LoadCellIdentifier = "LoadingCell"
var count = self.arrayOfAllData.count as NSInteger
if count == 0 && indexPath.row == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("LoadingCell") as! UITableViewCell
return cell
}
else {
let cell = tableView.dequeueReusableCellWithIdentifier("placementID") as! PlacementsTableViewCell
indexPATH = indexPath
var tweet = self.arrayOfAllData.objectAtIndex(indexPath.row) as! NSDictionary
let created_at = tweet.valueForKey("created_at") as? NSString
var dateArray : NSArray = created_at!.componentsSeparatedByString(" ")
if dateArray.count != 0 {
let month = dateArray.objectAtIndex(1) as! String
let date = dateArray.objectAtIndex(2) as! String
cell.timeLabel.text = String(format: "%# %#", date,month)
}
///////////any url present in tweet text
var entities = NSDictionary()
entities = tweet.valueForKey("entities") as! NSDictionary
var urlsArray = entities.valueForKey("urls") as! NSArray
if urlsArray.count == 0 {
}else {
for item in urlsArray as! [NSDictionary] {
let expanded_url = item.valueForKey("expanded_url") as? String
}
}
///////////
var tweet_id_str = NSString()
var user_id_str = NSString()
var data = NSData()
// var name = NSString()
///////////count of retweets
var retweet_count = tweet.valueForKey("retweet_count") as! NSInteger
var retweeted_status = tweet.valueForKey("retweeted_status") as! NSDictionary
var favorite_count = retweeted_status.valueForKey("favorite_count") as! NSInteger
///////////tweet id
tweet_id_str = retweeted_status.valueForKey("id_str") as! NSString
if retweeted_status.isEqual(nil) {
}
else {
var user = retweeted_status.valueForKey("user") as! NSDictionary
///////////last update
let created_at = retweeted_status.valueForKey("created_at") as! NSString
///////////
///////////user name who added this tweet
cell.titleLabel.text = user.valueForKey("name") as? String
///////////user id who added this tweet
user_id_str = user.valueForKey("id_str") as! NSString
///////////screen name
let screen_name = user.valueForKey("screen_name") as! NSString
var followers_count = user.valueForKey("followers_count") as! NSInteger
///////////profile image of the tweet
cell.avatarImageView.image = UIImage(named: "Twitter Avatar.jpg")
let profile_image_url = user.valueForKey("profile_image_url") as! NSString
var imageUrl = NSURL(string: profile_image_url as String)
let request: NSURLRequest = NSURLRequest(URL: imageUrl!)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {(response: NSURLResponse!,data: NSData!,error: NSError!) -> Void in
if error == nil {
if data != nil {
var image = UIImage(data: data)
cell.avatarImageView.image = image
}
}
})
if retweet_count >= 5 || favorite_count >= 15 || followers_count >= 30000 {
cell.featuredImageView.hidden = false
cell.featuredImageView.image = UIImage(named: "new feature star")
}
else {
cell.featuredImageView.hidden = true
}
}
cell.mailLabel.text = ""
let tweetText = tweet.valueForKey("text") as? NSString
cell.beattypeLabel.text = tweetText as? String
if tweetText?.containsString("#gmail") == true{
NSLog("Mail id is present at index : %d", indexPath.row)
var words = NSArray()
words = NSArray(array: tweetText!.componentsSeparatedByString(" "))
var mailAddress = NSString()
for var i = 0; i < words.count; i++ {
var mailAdd = words.objectAtIndex(i) as! NSString
if mailAdd.rangeOfString("#gmail").location != NSNotFound {
NSLog("mail Address : %#", mailAdd)
if mailAdd.rangeOfString(".com").location == NSNotFound {
var lastChar = mailAdd.characterAtIndex(mailAdd.length-1)
var lastCharStr:NSString = NSString(format: "%ch", lastChar)
mailAddress = mailAdd.stringByAppendingString(".com")
}
}
}
}
return cell
}
}
at the same time Thread 1 showing this
http://i.stack.imgur.com/2YoQp.jpg
(please go through this image)
use
var cell = tableView.dequeueReusableCellWithIdentifier("placementID") as! PlacementsTableViewCell
if cell.isEqual(nil) {
cell = PlacementsTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "placementID")
}
instead of
let cell = tableView.dequeueReusableCellWithIdentifier("placementID") as! PlacementsTableViewCell
and change downloading image in other thread like follow
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
println("This is run on the background queue")
var imageData = NSData(contentsOfURL: imageUrl!)
var image = UIImage(data: imageData!)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
println("This is run on the main queue, after the previous code in outer block")
cell.avatarImageView.image = image
})
})