ImageView in UITableViewCell won't display - ios

I've put an ImageView in a UITableViewCell on my Storyboard but at run time it is not showing up on my simulator. How do I solve this?
My storyboard:
The object overview of my storyboard:
The Swift code that fills up the cells:
func tableView(gamesListTableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = gamesListTableView.dequeueReusableCellWithIdentifier("Game", forIndexPath: indexPath) as! UITableViewCell
if (indexPath.row < GamesList.count) {
cell.detailTextLabel?.text = GamesList[indexPath.row]["game_guid"].string!;
cell.textLabel?.text = GamesList[indexPath.row]["opponent_name"].string!;
if (GamesList[indexPath.row]["self_turn"] == false) {
cell.textLabel?.textColor = UIColor.greenColor();
} else if (GamesList[indexPath.row]["game_idle_time"] <= 60) {
cell.textLabel?.textColor = UIColor.yellowColor();
} else {
cell.textLabel?.textColor = UIColor.redColor();
}
} else {
cell.detailTextLabel?.text = InvitesList[indexPath.row - GamesList.count]["invite_guid"].string!;
cell.textLabel?.text = InvitesList[indexPath.row - GamesList.count]["invite_text"].string!;
cell.textLabel?.textColor = UIColor.blueColor();
}
return cell
}
What it looks like at runtime:

You should probably pause the execution and view your view hierarchy in Xcode. Check what the frame size it at run time and see if A.) something is overlapping it or B.)If your constraints are wrong.

Related

UITableView scrolls up on reloadData

I have a UITableView that gets reloaded if a button in some of its cells gets tapped. The issue appears if the following steps are made:
Tap a button on a cell so that another cells appear below the tapped cell on reloadData.
Scroll up the table view so that it hides some of the upper content.
Tap the button again to hide the cells that were just shown making another call to reloadData.
Then the table view goes up and hides the upper content (the whole first cell and part of the second one). Here is some of the code:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if shouldShowImageResolutionOptions && (indexPath.row == 2 || indexPath.row == 3 || indexPath.row == 4) {
return isLastKnownDeviceOrientationLandscape ? 60 : 80
}
if shouldShowImageDisplayOptions && (indexPath.row == 3 || indexPath.row == 4) {
return isLastKnownDeviceOrientationLandscape ? 60 : 80
}
return isLastKnownDeviceOrientationLandscape ? tableView.frame.size.height / 2.5 + 40 : tableView.frame.size.height / 4.5 + 40
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if shouldShowImageResolutionOptions {
return 6
}
if shouldShowImageDisplayOptions {
return 5
}
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.row {
case 0:
let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifiers.IntervalCell) as! IntervalCell
cell.selectionStyle = .none
cell.dottedSliderView.contentMode = .redraw
cell.adjustThumbPosition()
return cell
case 1:
let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifiers.SettingsCell) as! SettingsCell
cell.selectionStyle = .none
cell.titleLabel.text = LabelTitles.ImageResolution
cell.choiseLabel.text = LabelTitles.HDResolutioin
cell.onButtonTap = {
self.shouldShowImageResolutionOptions = !self.shouldShowImageResolutionOptions
self.shouldShowImageDisplayOptions = false
self.menuTableView.reloadData()
}
return cell
case 2:
if(shouldShowImageResolutionOptions) {
let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifiers.SingleSettingCell, for: indexPath) as! SingleSettingCell
cell.selectionStyle = .none
cell.mainSettingLabel.text = Settings.HDResolution
return cell
}
let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifiers.SettingsCell) as! SettingsCell
cell.selectionStyle = .none
cell.titleLabel.text = LabelTitles.ImageDisplay
cell.choiseLabel.text = LabelTitles.EnlargeImage
cell.onButtonTap = {
self.shouldShowImageDisplayOptions = !self.shouldShowImageDisplayOptions
self.shouldShowImageResolutionOptions = false
self.menuTableView.reloadData()
}
return cell
case 3, 4:
if(shouldShowImageResolutionOptions) {
let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifiers.SingleSettingCell, for: indexPath) as! SingleSettingCell
cell.selectionStyle = .none
cell.mainSettingLabel.text = indexPath.row == 3 ? Settings.HighResolution : Settings.MediumResolution
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifiers.SingleSettingCell, for: indexPath) as! SingleSettingCell
cell.selectionStyle = .none
cell.mainSettingLabel.text = indexPath.row == 3 ? Settings.ShowFullImage : Settings.EnlargeImage
return cell
}
case 5:
let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifiers.SettingsCell) as! SettingsCell
cell.selectionStyle = .none
cell.titleLabel.text = LabelTitles.ImageDisplay
cell.choiseLabel.text = LabelTitles.EnlargeImage
cell.onButtonTap = {
self.shouldShowImageDisplayOptions = !self.shouldShowImageDisplayOptions
self.shouldShowImageResolutionOptions = false
self.menuTableView.reloadData()
}
return cell
default:
return UITableViewCell()
}
}
From the UITableView's reloadData method documentation (https://developer.apple.com/documentation/uikit/uitableview/1614862-reloaddata):
The table view’s delegate or data source calls this method when it wants the table view to completely reload its data. It should not be called in the methods that insert or delete rows, especially within an animation block implemented with calls to beginUpdates and endUpdates.
There are dedicated insert/delete rows methods for inserting and deleting:
insertRowsAtIndexPaths:withRowAnimation:(https://developer.apple.com/documentation/uikit/uitableview/1614879-insertrowsatindexpaths)
deleteRowsAtIndexPaths:withRowAnimation: (https://developer.apple.com/documentation/uikit/uitableview/1614960-deleterowsatindexpaths)
So when you refactor your code to use those it should work smoothly and as expected.

Align cell textLabel to top left programmatically in swift

I have programmatically created a TableView using sections in swift. The amount of sections and rows will always be the same, as they're just displaying info that I pull in from Firebase.
I would like to change the textLabel of one of the cells to align to the top, instead of the middle of the cell. All other textLabels I would like to remain centered. The cell in question is section 1, row 1.
It currently looks like:
I've been looking for how to do this for a while, and a lot of people say to do:
cell.textLabel?.numberOfLines = 0
cell.textLabel?.sizeToFit()
But this isn't working. I'm placing this code in my cellForRowAtIndexPath method.
if indexPath.section == 0 {
if indexPath.row == 0 {
cell.textLabel!.text = "Our review"
} else {
cell.textLabel!.text = film?.Main_Review
cell.textLabel?.numberOfLines = 0 // HERE
cell.textLabel?.sizeToFit() // HERE
}
}
Nothing happens, the text still aligns to centre of the cell.
Does anyone know a simple way of doing this? Preferably without having to create a custom cell (as this only needs to effect 1 row)? Thanks
UPDATE - All code for cellForRowAtIndexPath
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = UITableViewCell(style: .Value1, reuseIdentifier: cellId)
cell.selectionStyle = .None
cell.textLabel?.font = UIFont(name: "Verdana", size: 14)
cell.textLabel?.textColor = UIColor.darkGrayColor()
cell.detailTextLabel?.font = UIFont(name: "Verdana", size: 14)
if indexPath.section == 0 {
if indexPath.row == 0 {
cell.textLabel!.text = "Share"
}
} else if indexPath.section == 1 {
if indexPath.row == 0 {
cell.textLabel!.text = "Our review"
} else {
cell.textLabel!.text = film?.Main_Review
cell.textLabel?.numberOfLines = 0
cell.textLabel?.sizeToFit()
}
} else if indexPath.section == 2 {
if indexPath.row == 0 {
cell.textLabel!.text = "UK release date"
cell.detailTextLabel!.text = film?.Date_Released?.capitalizedString
} else if indexPath.row == 1 {
cell.textLabel!.text = "Directed by"
cell.detailTextLabel!.text = film?.Directed_By?.capitalizedString
} else if indexPath.row == 2 {
cell.textLabel!.text = "Running time"
cell.detailTextLabel!.text = film?.Running_Time
} else {
cell.textLabel!.text = "Certificate rating"
cell.detailTextLabel!.text = film?.Certificate_Rating
}
}
return cell
}
cell.textLabel is a default label in UITableViewCell. If you want your text to start at the top you should create a subclasse of UITableViewCell and create your own view for this cell.
For example
import Foundation
import UIKit
class ItemCell: UITableViewCell {
var label : UILabel!
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.label = UILabel()
self.contentView.addSubview(label)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
self.label.frame = CGRectMake(15,10,200,30)
self.label.adjustsFontSizeToFitWidth = true
self.label.textColor = UIColor.greenColor()
}
}
Then in your viewController dont forget to use the register class method like this
self.tableView.dataSource = self
self.tableView.delegate = self
self.tableView.registerClass(ItemCell.self, forCellReuseIdentifier: "cellIdentifier")
And in your cellForRowAtIndexPath
let cell:ItemCell! = tableView.dequeueReusableCellWithIdentifier("cellIdentifier") as? ItemCell
cell.textLabel?.sizeToFit()
should make your UILabel has the size need it to wrap the content. So a good thing you could do is change the background to see if this line is do the job.
I guess the problem is your constraints in the cell. You should have a look either looking at your code or your storyboards.
Autolayout tutorial
Note: you should edit your question, otherwise you could get some negatives for this. If it is section 0 can not be section 1.
if indexPath.section == 0 {
if indexPath.section == 1 {
/*your code */
}
}

Swift: Using custom accessoryType for cell freezes UI and 99% CPU Usage

I'm trying to use a custom accessory type (UIImage) for my tableview cell which has a expand/collapse functionality. When user taps a cell the row expands or collpases if parent is tapped again.
The imageview I'm using to set the accessory type is below:
var expandIcon : UIImageView?
expandIcon = UIImageView(frame:CGRectMake(0, 0, 16, 16))
expandIcon!.image = UIImage(named:"expand")
Following code is when user taps a row which if its parent it should epxand or if its already expanded it will collapse.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellData = dataForCellAtRowIndex[indexPath.section]!.rows[indexPath.row]
var cell:UITableViewCell!
if isParentCell(indexPath.row) == true {
cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.textLabel?.text = "test" + String(indexPath.row)
cell.detailTextLabel?.text = "detail"
cell.backgroundColor = UIColor.whiteColor()
cell.accessoryView = expandIcon
}else{
cell = tableView.dequeueReusableCellWithIdentifier("childCell", forIndexPath: indexPath)
cell.backgroundColor = UIColor.lightGrayColor()
cell.textLabel?.text = "child name"
cell.detailTextLabel?.text = "child detail"
cell.accessoryType = UITableViewCellAccessoryType.None
}
return cell
}
The bit that is causing the problem is cell.accessoryView = expandAccessory which causes the UI to freeze and cpu usage goes to 99% as reported by xcode. if i remove cell.accessoryView = expandIcon everything is fine! Why is this happening?
You should implement a function to return an expandIcon and then call it in place of expandIcon variable.
func expandImageView() -> UIImageView {
let expandIcon = UIImageView(frame:CGRectMake(0, 0, 16, 16))
expandIcon.image = UIImage(named:"expand")
return expandIcon
}
cell.accessoryView = expandImageView()
The fix for this as #rmaddy mentioned was the reuse of UIImage view which was causing the UI freeze. Creating a new UIImage for each cell fixed my problem so instead of:
if isParentCell(indexPath.row) == true {
cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.textLabel?.text = "test" + String(indexPath.row)
cell.detailTextLabel?.text = "detail"
cell.backgroundColor = UIColor.whiteColor()
cell.accessoryView = expandIcon
}
i had to :
if isParentCell(indexPath.row) == true {
cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.textLabel?.text = "test" + String(indexPath.row)
cell.detailTextLabel?.text = "detail"
cell.backgroundColor = UIColor.whiteColor()
//put the below two lines in a func and return a UIImage
let expandIcon = UIImageView(frame:CGRectMake(0, 0, 16, 16))
expandIcon.image = UIImage(named:"expand")
cell.accessoryView = expandIcon
}

Cell not being displayed - "no index path for table cell being reused"

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
print("Wall Delegate: caso 2")
let cell = tableView.dequeueReusableCellWithIdentifier("you1on1Cell", forIndexPath: indexPath) as! OneToOneCell
let cell1 = tableView.dequeueReusableCellWithIdentifier("other1on1Cell", forIndexPath: indexPath) as! OneToOneCell
let newMessage = messages[indexPath.row]
if(newMessage.you == true){
if let picture = imageYou { cell.profilePictureyou.image = picture }
if let textmsg = newMessage.text {
cell.messageTextYou.text = textmsg
}
return cell
} else {
if let picture = imageOther { cell1.profilePicture.image = picture }
if let textmsg = newMessage.text { cell1.messageText.text = textmsg }
return cell1
}
I don't know what is the problem, this error is being showed up, however app is still running, but text is only displayed when I click on tableview with mouse on simulator - it is the first app I am developing and it is the first time I am using a table view with two different cell structure (however it is the same cell file). This is meant to be a chat.

CollectionView objects (Swift)

I want the highlight to change the size and appearance of an object inside the collection view.
How can I set object properties in a collection view cell, within the "didHighlight" method?
In "cellForItemAtIndexPath" you declare the reusable cells as the class
and just use "cell.MyOutlet.backgroundColor = UIColor.blueColor()"
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
if collectionView == self.CollectionViewController {
let (FriendFirstName,FriendLastName) = friends[indexPath.row]
let cell: CustomCellA = collectionView.dequeueReusableCellWithReuseIdentifier("demoCell", forIndexPath: indexPath) as! CustomCellA
if indexPath.section == 0 {
cell.cellTitle.text = Name
cell.imgCell.image = UIImage(named: Pics[indexPath.row])
cell.imgCell.layer.masksToBounds = true
cell.self.imgCell.layer.cornerRadius = 20
return cell
} else {
let cell2: AddCell = collectionView.dequeueReusableCellWithReuseIdentifier("demoCell2", forIndexPath: indexPath) as! AddCell
return cell2
}
} else if collectionView == self.EmojiCollectionViewController {
let cellB: CustomCellB = collectionView.dequeueReusableCellWithReuseIdentifier("demoCellB", forIndexPath: indexPath) as! CustomCellB
cellB.MyLabel.text = arrayOne[indexPath.row]
return cellB
} else {
let cellC: CustomCellC = collectionView.dequeueReusableCellWithReuseIdentifier("demoCellC", forIndexPath: indexPath) as! CustomCellC
// ...Set up cell
let height = self.CollectionViewController2.frame.height
cellC.frame = CGRectMake(cellB.frame.origin.x, 0, cellB.frame.size.width, height)
cellC.updateConstraintsIfNeeded()
cellC.layoutIfNeeded()
cellC.imgVw.image = UIImage(named: pictures[indexPath.row] as! String)
return cellC
}
}
func collectionView(collectionView: UICollectionView, didHighlightItemAtIndexPath indexPath: NSIndexPath) {
if collectionView == self.CollectionViewController {
if indexPath.section == 0 {
let cell: CustomCellA = CustomCellB()
cell.MyLabel.backgroundColor = UIColor.blueColor() //crashes due to nil value)
}
} else {
}
}
I tried using a similar definition in didHighlight and it keeps crashing.
Let didHighlightItemAtIndexPath only change the data, not the view. So, make friends[indexPath.row] an object or add another parameter to tuple. And in didHighlightItemAtIndexPath do something like the following:
if collectionView == self.CollectionViewController {
if indexPath.section == 0 {
let (fname, lname, color) = friends[indexPath.row];
friends[indexPath.row] = (fname, lname, UIColor.blueColor())
}
}
And in cellForItemAtIndexPath:
if collectionView == self.CollectionViewController {
let (FriendFirstName, FriendLastName, color) = friends[indexPath.row]
if indexPath.section != 0 {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("demoCell2", forIndexPath: indexPath) as! AddCell;
return cell;
} else if color == nil {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("demoCell", forIndexPath: indexPath) as! CustomCellA;
cell.cellTitle.text = Name
cell.imgCell.image = UIImage(named: Pics[indexPath.row])
cell.imgCell.layer.masksToBounds = true
cell.self.imgCell.layer.cornerRadius = 20
return cell
} else {
cell = collectionView.dequeueReusableCellWithReuseIdentifier("demoCellB", forIndexPath: indexPath) as! CustomCellB;
// your code for CustomCellB
return cell;
}
}
EDIT: Updated, so instead of objects it uses tuples. Also added the functionality that you need. Basically, you need to create two prototype cells in the interface builder with different Reuse Identifiers and Classes. And then dequeue the correct identifier in the index path. Also, I refactored some of your code and if I were you I would create a different function for each collectionView and do something like:
if collectionView == self.CollectionViewController {
return self.dequeueCollectionCell(indexPath);
} else if collectionView == self.EmojiCollectionViewController {
return self.dequeuEmojiCell(indexPath);
} else {
return self.dequeueSomeOtherCell(indexPath);
}
Also, the code that you provided... I hope it is not an actual production code and you changed the values for this forum. Otherwise, in couple of days even, you are going to get lost in what is happening here. Too many inconsistent variable names and identifiers.
One more also. Use naming conventions in your class names. Read this forum post for more information. Apple uses camelCase everywhere. In majority of instances, the first letter is capitalized for class names, not object names.
first you have to define the collectionView Cell then do what ever you want on that cell. to define your sell add the below lines into didHighlightItemAtIndexPath
if let cellToUpdate = self.dataCollection.cellForItemAtIndexPath(indexPath) {
//your code here.
}

Resources