'[AnyObject]?' is not convertible to 'NSArray'(xcode,swift) - ios

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
})
}
}
}

Related

Fetching data unordered with predicate from array

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
}

Swift Cells Not Displaying

I have a profile page that is made up of two custom tableview cells. The first custom cell is the user's info. The second custom cell is the user's friend. The first row is the user's info, and all of the cells after that are the user's friends. My code worked in Xcode 6, but stopped working after the update.
Problem: A user with 2 friends, their profile page should have a table with three cells: 1 user info cell, 2 friend cells. However, the first and second cell aren't showing. Only the third cell is showing.
Clarification: There should be three cells. Cell 1 is not showing. Cell 2 is not showing. But Cell 3 is showing. Cell 1 is the user's info. Cell 2 is one friend. Cell 3 is another friend.
Here's my code:
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return friendList.count + 1
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row == 0{
return 182.0
}else{
return 95.0
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.row != 0{
let cell = tableView.dequeueReusableCellWithIdentifier("friendCell", forIndexPath: indexPath) as! ProfileFriendTableViewCell
let friend = friendList[indexPath.row - 1]
cell.nameLabel.text = friend[1]
cell.usernameLabel.text = friend[2]
cell.schoolLabel.text = friend[3]
cell.sendRequestButton.tag = indexPath.row
var profileImageExists = false
if profileImages != nil{
for profileImage in profileImages{
if profileImage.forUser == friend[2]{
profileImageExists = true
cell.friendImageProgress.hidden = true
cell.profilePic.image = UIImage(data: profileImage.image)
UIView.animateWithDuration(0.2, animations: {
cell.profilePic.alpha = 1
})
}
}
}else if loadingImages == true{
profileImageExists = true
cell.friendImageProgress.hidden = true
cell.profilePic.image = UIImage(named: "profileImagePlaceholder")
UIView.animateWithDuration(0.2, animations: {
cell.profilePic.alpha = 1
})
}
if profileImageExists == false{
if Reachability.isConnectedToNetwork() == true{
let query = PFUser.query()
query?.getObjectInBackgroundWithId(friend[0], block: { (object, error) -> Void in
if error == nil{
if let object = object as? PFUser{
let friendProfilePicture = object.objectForKey("profileImage") as? PFFile
friendProfilePicture?.getDataInBackgroundWithBlock({ (data, error) -> Void in
if data != nil{
let image = UIImage(data: data!)
cell.profilePic.image = image
if let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext {
let newProfileImage = NSEntityDescription.insertNewObjectForEntityForName("ProfileImageEntity", inManagedObjectContext: managedObjectContext) as! ProfileImage
newProfileImage.forUser = friend[2]
newProfileImage.image = UIImagePNGRepresentation(image!)
do{
try managedObjectContext.save()
}catch _{
print("insert error")
}
}
}else{
cell.friendImageProgress.hidden = true
cell.profilePic.image = UIImage(named: "profileImagePlaceholder")
}
}, progressBlock: { (progress: Int32) -> Void in
let percent = progress
let progressPercent = Float(percent) / 100
cell.friendImageProgress.progress = progressPercent
cell.friendImageProgress.hidden = true
})
}
}
})
}
else{
cell.friendImageProgress.hidden = true
cell.profilePic.image = UIImage(named: "profileImagePlaceholder")
}
}
return cell
}else{
let cell = tableView.dequeueReusableCellWithIdentifier("profileTopCell", forIndexPath: indexPath) as! ProfileTableViewCell
var profileImageExists = false
if profileImages != nil{
for profileImage in profileImages{
if profileImage.forUser == PFUser.currentUser()!.username!{
profileImageExists = true
cell.profilePic.image = UIImage(data: profileImage.image)
}
}
}else if loadingImages == true{
profileImageExists = true
cell.profilePic.image = UIImage(named: "profileImagePlaceholder")
}
if profileImageExists == false{
if Reachability.isConnectedToNetwork() == true{
let profilePicture = PFUser.currentUser()!.objectForKey("profileImage") as? PFFile
profilePicture?.getDataInBackgroundWithBlock({ (data, error) -> Void in
if data != nil{
let image = UIImage(data: data!)
cell.profilePic.image = image
if let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext {
let newProfileImage = NSEntityDescription.insertNewObjectForEntityForName("ProfileImageEntity", inManagedObjectContext: managedObjectContext) as! ProfileImage
newProfileImage.forUser = PFUser.currentUser()!.username!
newProfileImage.image = UIImagePNGRepresentation(image!)
do{
try managedObjectContext.save()
}catch _{
print("insert error")
}
}
}else{
cell.profilePic.image = UIImage(named: "profileImagePlaceholder")
}
})
}else{
cell.profilePic.image = UIImage(named: "profileImagePlaceholder")
}
}
cell.nameLabel.text = PFUser.currentUser()!.objectForKey("Name") as? String
cell.usernameLabel.text = PFUser.currentUser()!.objectForKey("username") as? String
let friendNumber = PFUser.currentUser()!.objectForKey("numberOfFriends") as? Int
if friendNumber != 1{
cell.numberOfFriendsLabel.text = "\(friendNumber!) Friends"
}else{
cell.numberOfFriendsLabel.text = "1 Friend"
}
return cell
}
}
Try to use estimatedRowHeightand rowHeight = UITableViewAutomaticDimension on your viewDidLoad or viewWillAppear and on heightForRowAtIndexPath return UITableViewAutomaticDimension, remember to put constraints on your custom cell, so these can work properly.
Thanks to Jeremy Andrews (https://stackoverflow.com/a/31908684/3783946), I found the solution:
"All you have to do is go to file inspector - uncheck size classes - there will be warnings etc.run and there is the data - strangely - go back to file inspector and check "use size classes" again, run and all data correctly reflected. Seems like in some cases the margin is set to negative."
It was just a bug.

Loading indicator until tableView loads

I am using Parse to load some data for title , http req for ImageView and ratingView. I also have a segment control view with 2 options.
I put an indicator where the image is presented , but when I scroll down
or when I press another segment(different movies) I get for 1-2 seconds the previous image , ratingView , titles and they change after this instantly. And obviously not all together. Can I somehow sync the changes or give an indicator 'waiting to load' until everything loads ?
func segmentView(segmentView: SMSegmentView, didSelectSegmentAtIndex index: Int) {
self.currentSegmentSelected = index
loadData().findObjectsInBackgroundWithBlock { [weak self] objects, error in
if error == nil {
dispatch_async(dispatch_get_main_queue(), {
self?.loadObjects()
})}
}
}
queryForTable(Parse)
override func queryForTable() -> PFQuery {
let query:PFQuery = PFQuery(className:"Movies")
if(objects?.count == 0)
{
query.cachePolicy = PFCachePolicy.CacheThenNetwork
}
if self.currentSegmentSelected == 0 {
query.whereKey("genres", containsString: "Adventure")
}
else if currentSegmentSelected == 1 {
query.whereKey("genres", containsString: "Comedy")
}
return query
}
cellForRowAtIndexPath
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {
let cellIdentifier:String = "cell"
var cell:TableCell? = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? TableCell
if(cell == nil) {
cell = TableCell(style: UITableViewCellStyle.Default, reuseIdentifier: cellIdentifier)
}
//??? indicator.startAnimating()
//??? indicator.backgroundColor = UIColor.whiteColor()
if let pfObject = object {
PFCloud.callFunctionInBackground("averageStars", withParameters: ["movieId":pfObject["movieId"]]) {
(response: AnyObject?, error: NSError?) -> Void in
if let rating = response as! Float? {
cell?.rating.rating = rating
}}
if let movieId = pfObject["movieId"] as? Int {
if RecommendedSet.ratings[movieId] == nil {
cell?.userRating.rating = 0
} else {
cell?.userRating.rating = RecommendedSet.ratings[movieId]!
}
}
cell?.title?.text = pfObject["title"] as? String
if let Id = pfObject["tmdbId"] as? Int {
Alamofire.request(.GET, timdb , parameters: ["api_key": APIkey])
.responseJSON { response in
if let JSON...
let imgData: NSData = NSData(contentsOfURL: imgURL)!
dispatch_async(dispatch_get_main_queue(), {
cell?.posterView?.image = UIImage(data: imgData)
//??? self.indicator.stopAnimating()
//??? self.indicator.hidesWhenStopped = true
})
}}}}}}}
return cell
}

Swift - 'PFObject is not convertible to NSString'

I've been trying to print the PFQuery called in my viewWillAppear in the cell but I'm getting the error from this line:
cell?.textLabel?.text = message as NSString as String
Here's the code for the tableView cellForRowAtIndexPath:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellId: NSString = "cell"
var cell: UITableViewCell? = tableView.dequeueReusableCellWithIdentifier(cellId as String) as? UITableViewCell
if (cell == nil) {
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: cellId as String)
}
let message = myMessagesArray![indexPath.row] as! PFObject
cell?.textLabel?.text = message as NSString as String
return cell!
}
Here's the PFQuery:
var query = PFUser.query()
query!.orderByAscending("Messages")
query!.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
println("Successfully retrieved \(objects!.count) messages.")
self.myMessagesArray = objects
self.tableView?.reloadData()
} else {
println(error!.localizedDescription)
}
}
Use this code:
let message = myMessagesArray[indexPath!.row] as! PFObject
cell.textLabel?.text = message.objectForKey("Messages") as? String

Displaying content from Parse into a UITableViewController using Swift

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()
}
}
}

Resources