Swift Cells Not Displaying - ios

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.

Related

Video preload in uicollectionview in swift

I am developing Instagram-like an app that has insta reels-like UI where videos are played in the list but what happens now is when cell comes on scree video buffers or loads and it takes 1-2 sec to load because of that uicollectionview scroll lags.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let currentItem = appData[indexPath.item]
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "swipablePostCollectionViewCell", for: indexPath) as! swipablePostCollectionViewCell
preFetchNextItems(currentIndexPath: indexPath)
if currentItem["video_url"] != "" && currentItem["video_url"] != nil {
cell.postVideoView.isHidden = false
cell.postImageView.isHidden = true
cell.postVideoView.tag = indexPath.item
DispatchQueue.main.async {
if let imageURL: URL = URL(string: currentItem["video_url"]!) {
if indexPath.item == 0 {
let item = VersaPlayerItem(url: imageURL)
cell.postVideoView.set(item: item)
cell.postVideoView.play()
} else {
if let newItem = self.prefetchedData[indexPath.item - 1] as? VersaPlayerItem {
cell.postVideoView.set(item: newItem)
}
}
cell.postVideoView.controls?.behaviour.shouldHideControls = false
cell.postVideoView.isPipModeEnabled = false
cell.postVideoView.autoplay = false
cell.postVideoView.renderingView.playerLayer.videoGravity = AVLayerVideoGravity.resizeAspect
cell.postVideoView.layer.backgroundColor = UIColor.black.cgColor
cell.postVideoView.use(controls: cell.controls)
cell.postVideoView.playbackDelegate?.startBuffering(player: cell.postVideoView.player)
cell.tag = indexPath.item
}
}
return cell
} else {
cell.postVideoView.isHidden = true
cell.postImageView.isHidden = false
if let imageURL: URL = URL(string: currentItem["image_url"] ?? "") {
cell.postImageView.sd_setImage(with: imageURL, placeholderImage: UIImage(named: "error"), options: .delayPlaceholder, context: nil)
cell.postImageView.contentMode = .scaleAspectFill
cell.postImageView.clipsToBounds = true
}
return cell
}
}
And for prefetch
func preFetchNextItems(currentIndexPath: IndexPath?) {
if currentIndexPath?.item == 0 {
for i in 1...4 {
let indexP = IndexPath(item: i, section: 0)
arrFetchedIndexPaths.append(indexP)
lastFetchedIndexPath = indexP
GetDataForPrefetchIndexPath()
}
} else {
let newIndePath = IndexPath(item: lastFetchedIndexPath!.item + 1, section: lastFetchedIndexPath!.section)
arrFetchedIndexPaths.append(newIndePath)
lastFetchedIndexPath = newIndePath
GetDataForPrefetchIndexPath()
}
print("Prefetch indexpath - ", arrFetchedIndexPaths)
}
func GetDataForPrefetchIndexPath() {
if appData.count > lastFetchedIndexPath!.item {
let currentItem = appData[lastFetchedIndexPath!.item]
if currentItem["video_url"] != "" && currentItem["video_url"] != nil {
if let imageURL: URL = URL(string: currentItem["video_url"]!) {
let newItem = VersaPlayerItem(url: imageURL)
prefetchedData.append(newItem)
}
} else {
if let imageURL: URL = URL(string: currentItem["image_url"] ?? "") {
// let newImage = sd_setImage(with: imageURL, placeholderImage: UIImage(named: "error"), options: .delayPlaceholder, context: nil)
prefetchedData.append(imageURL)
}
}
for item in prefetchedData {
print(item)
}
}
}
What i need is on first cell next 4 cell video should preloaded and after user scrolls next cell video should load
so that when user scrolls to next cell video will be preloaded and played without buffer.

In swift - UITableview gets jerky while scrolling

Am make a tableview listing, data loading dynamically and a image
contain in cell and some text. When it scroll gets jerking and
irritating the users
Any idea for improving the table view performance?
class MainViewController: UIViewController,UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var listTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.listTable.delegate = self
self.listTable.dataSource = self
self.listTable.separatorStyle = .None
self.listTable.registerNib(UINib(nibName: "cellOne", bundle: nil), forCellReuseIdentifier: "cellOne")
self.listTable.registerNib(UINib(nibName: "cellTwo", bundle: nil), forCellReuseIdentifier: "cellTwo")
self.listTable.registerNib(UINib(nibName: "cellThree", bundle: nil), forCellReuseIdentifier: "cellThree")
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int{
return 1
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if pageIndex == 7 {
return 120
} else if indexPath.row == 0 {
return 280
} else if (indexPath.row == 5 || indexPath.row == 4) {
return 200
} else if (indexPath.row == 8 || indexPath.row == 11) {
return 160
}
return 80
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return 50
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
let listArray = self.listDataArray[indexPath.row]
if indexPath.row == 0 && pageIndex != 7 {
var cell = tableView.dequeueReusabl eCellWithIdentifier("cellOne") as! cellOne!
if cell == nil {
tableView.registerClass(cellOne.classForCoder(), forCellReuseIdentifier: "cellOne")
cell = cellOne(style: UITableViewCellStyle.Default, reuseIdentifier: "cellOne")
}
cell.headLbl.text = "\(listArray["title"]!)".html2String
cell.addImageView.userInteractionEnabled = true
let guster = UITapGestureRecognizer(target: self, action: "addTarget:")
cell.addImageView.addGestureRecognizer(guster)
cell.addImageView.tag = 1
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
if listArray["image"] != nil && self.imagesLocalDictionary[indexPath.row] == nil {
let u = listArray["image"] as! String
let url = NSURL(string: u)
if url != nil {
let data = NSData(contentsOfURL: url!)
if data != nil {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
cell.imageViews.image = UIImage(data: data!)
})
self.imagesLocalDictionary.setObject(data!, forKey: indexPath.row)
}
}
} else {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
cell.imageViews.image = UIImage(data: self.imagesLocalDictionary[indexPath.row] as! NSData)
})
}
})
if Constants.sharedInstance.addData["1"] != nil {
cell.addImageView.image = UIImage(data: Constants.sharedInstance.addData["1"] as! NSData)
}
return cell
} else if indexPath.row == 4 && pageIndex != 7 {
var cell = tableView.dequeueReusableCellWithIdentifier("cellTwo") as! cellTwo!
if cell == nil {
tableView.registerClass(cellTwo.classForCoder(), forCellReuseIdentifier: "cellTwo")
cell = cellTwo(style: UITableViewCellStyle.Default, reuseIdentifier: "cellTwo")
}
cell.headLbl.text = "\(listArray["title"]!)".html2String
cell.addImageView.userInteractionEnabled = true
let guster = UITapGestureRecognizer(target: self, action: "addTarget:")
cell.addImageView.addGestureRecognizer(guster)
cell.addImageView.tag = 2
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
if listArray["image"] != nil && self.imagesLocalDictionary[indexPath.row] == nil {
let u = listArray["image"] as! String
let url = NSURL(string: u)
if url != nil {
let data = NSData(contentsOfURL: url!)
if data != nil {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
cell.imageViews.image = UIImage(data: data!)
})
self.imagesLocalDictionary.setObject(data!, forKey: indexPath.row)
}
}
} else {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
cell.imageViews.image = UIImage(data: self.imagesLocalDictionary[indexPath.row] as! NSData)
})
}
})
if Constants.sharedInstance.addData["2"] != nil {
cell.addImageView.image = UIImage(data: Constants.sharedInstance.addData["2"] as! NSData)
}
return cell
} else if indexPath.row == 5 && pageIndex != 7 {
var cell = tableView.dequeueReusableCellWithIdentifier("cellThree") as! cellThree!
if cell == nil {
tableView.registerClass(cellThree.classForCoder(), forCellReuseIdentifier: "cellThree")
cell = cellThree(style: UITableViewCellStyle.Default, reuseIdentifier: "cellThree")
}
cell.headLbl.text = "\(listArray["title"]!)".html2String
cell.addImageView.userInteractionEnabled = true
let guster = UITapGestureRecognizer(target: self, action: "addTarget:")
cell.addImageView.addGestureRecognizer(guster)
cell.addImageView.tag = 3
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
if listArray["image"] != nil && self.imagesLocalDictionary[indexPath.row] == nil {
let u = listArray["image"] as! String
let url = NSURL(string: u)
if url != nil {
let data = NSData(contentsOfURL: url!)
if data != nil {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
cell.imageViews.image = UIImage(data: data!)
})
self.imagesLocalDictionary.setObject(data!, forKey: indexPath.row)
}
}
} else {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
cell.imageViews.image = UIImage(data: self.imagesLocalDictionary[indexPath.row] as! NSData)
})
}
})
if Constants.sharedInstance.addData["3"] != nil {
cell.addImageView.image = UIImage(data: Constants.sharedInstance.addData["3"] as! NSData)
}
return cell
} else {
cell.backgroundColor = UIColor.groupTableViewBackgroundColor()
let container = UIView()
container.frame = CGRectMake(2, 1, tableView.frame.width-4, 78)
container.backgroundColor = UIColor.whiteColor()
cell.addSubview(container)
let headerLbl = UILabel()
headerLbl.backgroundColor = UIColor.clearColor()
headerLbl.frame = CGRectMake(120, 1, self.view.frame.width-130, 76)
headerLbl.numberOfLines = 0
headerLbl.font = UIFont(name: "TelegramHead", size: 18)
headerLbl.text = "\(listArray["title"]!)".html2String
headerLbl.lineBreakMode = NSLineBreakMode.ByCharWrapping
let imageView = UIImageView()
imageView.frame = CGRectMake(5, 5, 100, 68)
imageView.image = UIImage(named: "place_holder.jpg")
imageView.contentMode = UIViewContentMode.ScaleAspectFill
imageView.clipsToBounds = true
let blackLayerView = UIView();
blackLayerView.frame = CGRectMake(0, 0, 0, 0);
blackLayerView.backgroundColor = UIColor.blackColor();
blackLayerView.alpha = 0.4;
container.addSubview(imageView)
container.addSubview(blackLayerView);
container.addSubview(headerLbl)
if pageIndex == 7 {
container.frame = CGRectMake(2, 1, tableView.frame.width-4, 118)
imageView.frame = CGRectMake(5, 5, container.frame.width-10, 108)
blackLayerView.frame = imageView.frame;
headerLbl.frame = imageView.frame//CGRectMake(10, 5, self.view.frame.width-20, 100)
headerLbl.textColor = UIColor.whiteColor()
headerLbl.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.2)
} else if (indexPath.row == 8 || indexPath.row == 11) && pageIndex != 7 {
let add = UIImageView()
add.frame = CGRectMake(2, 82, tableView.frame.width-4, 76)
//add.contentMode = UIViewContentMode.ScaleAspectFit;
cell.addSubview(add)
add.userInteractionEnabled = true
let guster = UITapGestureRecognizer(target: self, action: "addTarget:")
add.addGestureRecognizer(guster)
if Constants.sharedInstance.addData["4"] != nil && indexPath.row == 8{
add.image = UIImage(data: Constants.sharedInstance.addData["4"] as! NSData)
add.tag = 4
}
if Constants.sharedInstance.addData["5"] != nil && indexPath.row == 11{
add.image = UIImage(data: Constants.sharedInstance.addData["5"] as! NSData)
add.tag = 5
}
}
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
if listArray["image"] != nil && self.imagesLocalDictionary[indexPath.row] == nil {
let u = listArray["image"] as! String
let url = NSURL(string: u)
if url != nil {
let data = NSData(contentsOfURL: url!)
if data != nil {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
imageView.image = UIImage(data: data!)
self.imagesLocalDictionary.setObject(data!, forKey: indexPath.row)
})
}
}
} else {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
imageView.image = UIImage(data: self.imagesLocalDictionary[indexPath.row] as! NSData)
})
}
})
}
return cell
}
}
I do get the required functionality. But there is a very unnatural jerk on the TableView which results in a bad User experience.
There are a number of improvements you could make to this code to improve performance.
Don't register cells in cellForRow
Define specific custom classes for each cell and register them for reuse in viewDidLoad
Reduce the logic used in cellForRowAt
At the start of cellForRowAt you create a new instance of a cell and later add subviews to it if none of the other cases match. there is no reuse for this cell. Always reuse. you'll use less resources
I have built a complex table view before and created functions that configure and return reusble cells for the particular indexPath.
class LargeImageCell: UITableViewCell {
var imageView: UIImageView()
// in init, init the cell, add imageview as subview, setup constraints
func setContent(imageURL: URL) {
// load image from cache or fetch from network in background
}
}
// in tableview/view controller
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
switch indexPath.row {
case 0:
return self.getLargeImageCell(indexPath: indexPath)
// all other cases
}
}
This is just roughly how I implemented mine, just try to reduce the amount of logic in the cell and I've alwayss found it best to create custom cells rather than adding them in cellForRowAt, let the cell configure itself
func getLargeImageCell(indexPath: NSIndexPath) -> UITableViewCell {
let data = self.data[indexPath.row] // model from db
var cell: UITableViewCell
if let c = self.tableView.dequeueReusableCellWithIdentifier("largeImageCell") as? LargeImageCell {
cell = c
} else {
cell = LargeImageCell(style: UITableViewCellStyle.Default, reuseIdentifier: "largeImageCell")
}
cell.setContent(imageURL: data.imageURL)
return cell
}

Some cells won't show

I'm trying to create a chat applications with tableview to show the messages. Everything works fine except that some cells just won't show. It aren't always the same cells. I'm getting the messages from my Firebase database.
My Code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = cellCache.object(forKey: indexPath as AnyObject) as? UITableViewCell{
return cell
}
let cell = messagesTableView.dequeueReusableCell(withIdentifier: "otherMessageCell") as! OtherMessageTableViewCell
DispatchQueue.global(qos: .userInteractive).async {
let message = self.messages[indexPath.row]
let ref = FIRDatabase.database().reference()
let uid = FIRAuth.auth()?.currentUser?.uid
if(uid == message.sender) {
cell.sender.textAlignment = .right
cell.message.textAlignment = .right
}else{
cell.sender.textAlignment = .left
cell.message.textAlignment = .left
}
let uidReference = ref.child("Users").child(message.sender!)
uidReference.observeSingleEvent(of: .value, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let username = dictionary["Username"] as! String
let imageLink = dictionary["Image Link"] as! String
cell.sender.text = username
cell.message.text = message.message
cell.profileImage.image = nil
cell.profileImage.loadImageWithURLString(urlString: imageLink)
}
}, withCancel: nil)
}
DispatchQueue.main.async {
self.cellCache.setObject(cell, forKey: indexPath as AnyObject)
}
return cell
}
Example:
I hope someone will be able to help me. Thanks
I've found a solution:
var savedSenders = [Int: String]()
var savedMessages = [Int: String]()
var savedImages = [Int: UIImage]()
var savedAlignments = [Int: NSTextAlignment]()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = messagesTableView.dequeueReusableCell(withIdentifier: "otherMessageCell") as! OtherMessageTableViewCell
if(savedSenders[indexPath.row] != nil && savedMessages[indexPath.row] != nil && savedImages[indexPath.row] != nil && savedAlignments[indexPath.row] != nil) {
cell.sender.textAlignment = savedAlignments[indexPath.row]!
cell.message.textAlignment = savedAlignments[indexPath.row]!
cell.sender.text = savedSenders[indexPath.row]
cell.message.text = savedMessages[indexPath.row]
cell.profileImage.image = savedImages[indexPath.row]
return cell
}
cell.sender.text = ""
cell.message.text = ""
cell.profileImage.image = nil
DispatchQueue.global(qos: .userInteractive).async {
let message = self.messages[indexPath.row]
let ref = FIRDatabase.database().reference()
let uid = FIRAuth.auth()?.currentUser?.uid
if(uid == message.sender) {
cell.sender.textAlignment = .right
cell.message.textAlignment = .right
self.savedAlignments.updateValue(.right, forKey: indexPath.row)
}else{
cell.sender.textAlignment = .left
cell.message.textAlignment = .left
self.savedAlignments.updateValue(.left, forKey: indexPath.row)
}
let uidReference = ref.child("Users").child(message.sender!)
uidReference.observeSingleEvent(of: .value, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let username = dictionary["Username"] as! String
let imageLink = dictionary["Image Link"] as! String
cell.sender.text = username
cell.message.text = message.message
cell.profileImage.image = nil
cell.profileImage.loadImageWithURLString(urlString: imageLink)
let url = URL(string: imageLink)
URLSession.shared.dataTask(with: url!) { (data, response, error) in
if(error != nil){
print(error as Any)
return
}
DispatchQueue.main.async {
if let downloadedImage = UIImage(data: data!) {
let image = downloadedImage
self.savedSenders.updateValue(username, forKey: indexPath.row)
self.savedMessages.updateValue(message.message!, forKey: indexPath.row)
self.savedImages.updateValue(image, forKey: indexPath.row)
}
}
}.resume()
}
}, withCancel: nil)
}
return cell
}
The data for every cell is saved into the arrays (savedSenders, savedMessages, savedImages and savedAlignments). If I don't save it into arrays, the cells will have to load all the data from Firebase and this will take longer. If it takes longer, it won't look good.
I tested everything and it works.

Synching parse object array with UIImageView array

I'm building an app for creating events which uses parse as a back end. The main interface is a collection view with a custom cell, which when flipped displays an array of UIImageViews added to the cell file as an IBOutlet collection.
#IBOutlet var imageViewArray: [UIImageView]!
Inside the event.getDataInBackground block I have this code, which doesn't get called for some reason, I think it will work once it is but does anyone know what's up? Thanks!
//gets profile pictures for image view array on back of cell
if let attendeeArray = event?.objectForKey("attendees") as? [PFUser] {
for var index = 0; index < attendeeArray.count; ++index {
let profileImageView = cell.imageViewArray[index]
let usr : PFUser = (attendeeArray[index] as PFUser?)!
if let picture = usr.objectForKey("profilePicture") as? PFFile {
picture.getDataInBackgroundWithBlock({ (data, error) -> Void in
profileImageView.image = UIImage(data: data!)
})
}
}
}
The whole cell for row at index path method (The creator image shows up and is called but the attendee array part is not).
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
//sets up cell
let cell : EventCell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! EventCell
//adds attend action
cell.attendButton.addTarget(self, action: "buttonTapped:", forControlEvents: UIControlEvents.TouchUpInside)
//queries parse for events
let event = events?[indexPath.row]
event?.eventImage.getDataInBackgroundWithBlock({ (data, error) -> Void in
if let data = data, image = UIImage(data: data) {
cell.eventBackgroundImage.image = image
cell.eventTitleLabel.text = event?.eventTitle
//gets profile picture of events creator
if let eventCreator = event?.objectForKey("user") as? PFUser {
if let creatorImage = eventCreator.objectForKey("profilePicture") as? PFFile {
creatorImage.getDataInBackgroundWithBlock({ (data, error) -> Void in
cell.creatorImageView.image = UIImage(data: data!)
})
}
}
//gets profile pictures for image view array on back of cell
if let attendeeArray = event?.objectForKey("attendees") as? [PFUser] {
for var index = 0; index < attendeeArray.count; ++index {
let profileImageView = cell.imageViewArray[index]
let usr : PFUser = (attendeeArray[index] as PFUser?)!
if let picture = usr.objectForKey("profilePicture") as? PFFile {
picture.getDataInBackgroundWithBlock({ (data, error) -> Void in
profileImageView.image = UIImage(data: data!)
})
}
}
}
//sets correct category for cell image
if event?.category == "" {
cell.categoryImageView.image = nil
}
if event?.category == "The Arts" {
cell.categoryImageView.image = UIImage(named: "Comedy")
}
if event?.category == "The Outdoors" {
cell.categoryImageView.image = UIImage(named: "Landscape")
}
if event?.category == "Other" {
cell.categoryImageView.image = UIImage(named: "Dice")
}
if event?.category == "Sports" {
cell.categoryImageView.image = UIImage(named: "Exercise")
}
if event?.category == "Academics" {
cell.categoryImageView.image = UIImage(named: "University")
}
if event?.category == "Science" {
cell.categoryImageView.image = UIImage(named: "Physics")
}
if event?.category == "Entertainment" {
cell.categoryImageView.image = UIImage(named: "Bowling")
}
if event?.category == "Food & Drinks" {
cell.categoryImageView.image = UIImage(named: "Food")
}
if let date = event?.eventDate {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
cell.eventDescriptionLabel.text = event?.eventDescription
cell.eventDateLabel.text = dateFormatter.stringFromDate(date)
}
}
})
cell.layer.cornerRadius = 20
return cell
}
EDITED:
//gets profile pictures for image view array on back of cell
if let attendeeArray = event?.objectForKey("attendees") as? [PFUser] {
for var index = 0; index < attendeeArray.count; ++index {
let profileImageView = cell.imageViewArray[index]
let usr : PFUser = (attendeeArray[index] as PFUser?)!
usr.fetchIfNeededInBackgroundWithBlock({ (object: PFObject?, error: NSError?) -> Void in
if let picture = object!.objectForKey("profilePicture") as? PFFile {
picture.getDataInBackgroundWithBlock({ (data, error) -> Void in
profileImageView.image = UIImage(data: data!)
})
}
})
}
}
You need to fetch the usr before you can get picture
usr.fetchIfNeededInBackgroundWithBlock({ (object: PFObject?, error: NSError?) -> Void in
if let picture = object.objectForKey("profilePicture") as? PFFile {
picture.getDataInBackgroundWithBlock({ (data, error) -> Void in
profileImageView.image = UIImage(data: data!)
})
}
})

Hide custom ViewTableCell Button for a specific cell

I'm facing a problem with a UITableViewCell.
When I generate my tableCells, I check if a value is equal to something and if so, I hide a custom button I made in my prototype cell. The problem is, the button with the identifier I hide is hidden in every Cell and not the current one only...
I looked around but can't find something to do... Could you help ? Here's my code, look at the line if currentPost.valueForKey... == "noLink". Thanks !
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
var cell = tableView.dequeueReusableCellWithIdentifier("postCell", forIndexPath: indexPath) as! PostTableViewCell
var currentCell = indexPath
var currentPost = post[indexPath.row]
var currentUser = followedInfo[currentPost.valueForKey("userID") as! String]
cell.username.contentHorizontalAlignment = UIControlContentHorizontalAlignment.Left
cell.userProfil.layer.cornerRadius = 0.5 * cell.userProfil.bounds.size.width
cell.username.setTitle(currentUser?.valueForKey("username") as? String, forState: UIControlState.Normal)
cell.postArtist.text = currentPost.valueForKey("artistName") as? String
cell.postDescription.text = currentPost.valueForKey("postDescription") as? String
cell.postTitle.text = currentPost.valueForKey("songName") as? String
cell.postTime.text = "7J"
cell.postDescription.sizeToFit()
if currentPost.valueForKey("itunesLink") as? String == "noLink" {
cell.postItunes.hidden = true;
}else{
cell.postItunes.addTarget(self, action: "getToStore:", forControlEvents: .TouchUpInside)
}
if currentPost.valueForKey("previewLink") as? String == "noPreview" {
cell.postPlay.alpha = 0;
}else{
cell.postPlay.addTarget(self, action: "getPreview:", forControlEvents: .TouchUpInside)
}
if currentPost.valueForKey("location") as? String == "noLocalisation" {
cell.postLocation.text = "Inconnu"
}else{
cell.postLocation.text = currentPost.valueForKey("location") as? String
}
if currentUser?.valueForKey("profilePicture")! != nil{
var pictureFile: AnyObject? = currentUser?.valueForKey("profilePicture")!
pictureFile!.getDataInBackgroundWithBlock({ (imageData, error) -> Void in
var theImage = UIImage(data: imageData!)
cell.userProfil.image = theImage
})
}
if currentPost.valueForKey("coverLink") as? String == "customImage" {
var profilPictureFile: AnyObject? = currentPost.valueForKey("postImage")
profilPictureFile!.getDataInBackgroundWithBlock { (imageData , imageError ) -> Void in
if imageError == nil{
let image = UIImage(data: imageData!)
cell.postPicture.image = image
}
}
}else{
if currentPost.valueForKey("coverLink") as? String == "noCover"{
var cover = UIImage(named: "noCover")
cell.postPicture.image = cover
}else{
var finalURL = NSURL(string: currentPost.valueForKey("coverLink") as! String)
let request: NSURLRequest = NSURLRequest(URL: finalURL!)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {(response: NSURLResponse!,data: NSData!,error: NSError!) -> Void in
if error == nil {
var image = UIImage(data: data)
cell.postPicture.image = image
}
else {
println("Error: \(error.localizedDescription)")
}
})
}
}
return cell;
}
You are not setting the bottom back to visible if you want it to show, because you are reusing the cell the last setup is part of the cell, so as soon as you set it to hidden to true it will still hidden until you set hidden back to false, the best way to use reusable cell is to always set all the options to what you want to be for that cell to avoid the setting to be as the old cell.
if currentPost.valueForKey("itunesLink") as? String == "noLink" {
cell.postItunes.hidden = true;
}else{
cell.postItunes.hidden = false;
cell.postItunes.addTarget(self, action: "getToStore:", forControlEvents: .TouchUpInside)
}

Resources