Can't access cell subviews Swift - ios

I have this function inside my UICollectionView Class:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("MoreCell", forIndexPath: indexPath) as! UICollectionViewCell
if let icLab = cell.viewWithTag(491) as? UILabel{
icLab.text = moreitems[indexPath.section][indexPath.row].title
}else{
println("Couldnt find label")
}
// Same code for imageView
The rest of the UICollectionView is fine because it does display the cells properly on the screen, as well as the initially set label text ("Label")
But I just can't seem to access the subviews inside. Here is how they're set up:
And I do have the Tags and the Cell ID set up correctly.
Has anyone any idea why it keeps printing Couldn't find Label
Screen looks like this:
Obviously the placeholder image and label is not being edited.

From apples's document
Installed views are added to the view hierarchy. Uninstalled views are not added.
Choose the label and select 'Installed'

From the UICollectionViewCell documentation :
var contentView: UIView { get }
When configuring a cell, you add any custom views
representing your cell’s content to this view. The cell object places
the content in this view in front of any background views.
So you must look for your views inside cell's contentView and not cell itself
if let icLab = cell.contentView.viewWithTag(491) as? UILabel{
icLab.text = moreitems[indexPath.section][indexPath.row].title
}else{
println("Couldnt find label")
}

Related

How to create tableview cells without using prototype cells?

In my tableview, every cell will be different and determined by a JSON response from server. And there will be infinite possibilities. So defining a prototype for each type of cell is not possible.
For example, one cell will have labels and buttons, another cell have images and buttons in different orders.
How to achieve this dynamic structure in tableview cells?
Currently what I am doing is: adding views as subview in cellForRowAtIndexPath but scrolling is very laggy this way.
How to achieve this without affecting performance this much
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell") as! MyCell
for myview in data[indexPath.row].myviews{
cell.addSubview(myview)
}
return cell
}
If you're using a table view then your content is going to scroll vertically, right?
There is a physical limit to the amount of UI that you can put horizontally. Limited by the screen size.
So I'm guessing your UI parts are being laid out vertically in the cell?
So instead of laying out a button, label, image, another button, and a text field vertically in a cell...
Create a cell type called ButtonCell, LabelCell, ImageCell, MultiLineLabelCell, TextFieldCell, etc...
So now, instead of creating one cell with all these elements added. You instead create multiple cells each containing one type of UI. Now you can dequeue your cells in any particular order (driven by your JSON) and won't lose the performance.
The only solution I see is to have empty cell and add/remove subviews as needed. But you should add new subviews to a cell only if you did not add them before.
For example:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell") as! MyCell
if cell.contentView.viewWithTag(1) == nil {
let label = UILabel()
label.tag = 1
cell.contentView.addSubview(label)
}
let label = cell.contentView.viewWithTag(1)
// label config there
return cell
}
Also don't forget to add subviews to cell's contentView not to cell itself.

How to change view height according to it is recently added subview?

I have such problem, while trying to create a simple messenger.
Here what I came to:
class ChatBubleUIView that class is responsible for creating a bubleview with label in it. It works fine, calculating view height according to label height
Inside my cell I've created a content view. In the cell class, I'm adding new ChatBubleUIView instance as a subview to content View.
The problem is that, content doesn't scale up to the size of my ChatBubleInstance.
class ChatMessageTableViewCell: UITableViewCell, MessageCellConfiguration {
var message: Message?
override func awakeFromNib() {
super.awakeFromNib()
}
func configureCell() {
let chatBubleView = ChatBubleUIView(message: message!)
self.addSubview(chatBubleView)
}
}
In my tableView delegate
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "messageCell") as! ChatMessageTableViewCell
let data = currentUser.mesaageHistory[indexPath.row]
cell.message = data
cell.configureCell()
return cell
}
Also I have set estimated row height for my tableView
messageTableView.rowHeight = UITableViewAutomaticDimension
messageTableView.estimatedRowHeight = 44
What should I do to set to my tableView row height chatViewBubleUIView instance height.
Previously, I solved this problem using old-school approach, programmaticly determine chatViewBubleUIView instance height and then implement heightForRowAtIndexPath. But I'd like to do that using AutoLayoaut.
set your label's four constraint like top,bottom,leading,trailing and number of height of your label should be 0. Then it will automatically increased it's height as per content. If you are taking this label in any view then view's constrains should be same as label i have mentioned above!

UICollectionReusableView header possible bug

I have a custom UICollectionReusableView with a single label inside: the label has leading, trailing, top and bottom constraints set to 8.
On the controller, I register the cell and then:
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return self.sectionSizeForIndex(section)
}
func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
let cell = self.collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "cellID", forIndexPath: indexPath) as! FooCollectionViewCell
cell.setupLabelWithText("Lorem ipsum")
return cell
}
For debugging reasons, I show both the borders of the cell and the borders of the inner label, with different colors.
Here's what happens: The cell got the right frame, but the inner label seems not update constraints according to its parent view (cell).
On "Debug View Hierarchy", I see that also cell.contentView doesn't update itself -> I suppose that is this the reason why the label doesn't update.
In cell awake from nib:
override func awakeFromNib() {
super.awakeFromNib()
self.label.numberOfLines = 0
self.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
self.translatesAutoresizingMaskIntoConstraints = true
}
add this inside viewForSuplementary
switch kind {
case UICollectionElementKindSectionHeader:
let cell = self.collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "cellID", forIndexPath: indexPath) as! FooCollectionViewCell
cell.setupLabelWithText("Lorem ipsum")
return cell
default: break
}
this will let you collectionView know that you actually are using a header and not a footer or other type of view kind
The problem may be that you are using an instance of UICollectionViewCell for a supplementary view instead of the usual custom subclass of UICollectionReusableView.
UICollectionReusableView does not have a contentView property, unlike UICollectionViewCell. The latter creates its own view for that property by manipulating your view hierarchy and constraints. It manages the frame of the content view, and gives it a gesture recognizer, amongst other things. The relationship between the cell (which is itself a view) and the content view (as a subview of the cell) is somewhat opaque and has led to developer grief in previous versions of iOS.
There is nothing in the documentation expressly forbidding the use of UICollectionViewCell as a supplementary view. But there are implicit indications that the expected practice is to the contrary.
The purpose of UICollectionViewCell is to "present the main content" of your collection view, or "your main data items". It "presents the content for a single data item". Supplementary views, on the other hand, "are separate from the collection view's cells". "Like cells, these views are provided by the data source object, but their purpose is to enhance the main content of your app."
When configuring supplementary views in a storyboard, the "Collection View Programming Guide for iOS" provides the following guidance:
For supplementary views, drag a Collection Reusable View from the object library and drop it on to your collection view. Set the custom class and the collection reusable view identifier of your view to appropriate values.
There is no express guidance about configuring supplementary views programmatically, but there is also no reason to think the expected practice would be any different.
In testing your scenario (iOS 10.2 and iOS 9.3, Xcode 8), I could not reproduce the problem. I found that the frames of the content view and label were both set correctly.
But the easiest solution to your problem is likely to be to adopt the expected practice:
Change FooCollectionViewCell (and any associated nib file) from a subclass of UICollectionViewCell to a subclass of UICollectionReusableView.
Remove the autoresizing mask lines from awakeFromNib.

UITableViewRow displays Buttons without Color

I a have 2 Buttons within my custom TableViewCell.
The Buttons are in bright colors. (BackgroundColor set)
However: Running the app - The Buttons color disappear and it becomes white:
I tried to programmatically change the color in viewDidLoad but Xcode doesn't react.
Any Ideas?
The heart of the problem is that you have introduced buttons but you are also setting the cell's textLabel!.text. You can't mix and match like that. If you're going to use a custom cell, you must use a completely custom cell.
Set the cell's type to Custom, drag a label into it, use a custom cell class, give it an outlet to the label, set this label's text, and all will be well.
Here's my custom cell with an outlet:
class MyCell : UITableViewCell {
#IBOutlet var label : UILabel!
}
Here's my cellForRow:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! MyCell
cell.label.text = "Hi" // NOT cell.textLabel!.text
return cell
}
As you can see, the result is that button appears just fine.
You have an extra word in there:
cell.noButton.backgroundColor = UIColor.greenColor()

Comment controller with table view section header and footer

How can I achieve this screen with UITableViewCell and UITableViewController. With table section and header. Some ideas to achieve this?? Thanks!
What have you tried so far?
Your question seems a little broad.
You will need a set of custom UITableViewCell Subclasses, which you design in nibs.
To make the cells seem apart from each other, resize the content size of the Cells, and make the cell background another color.
Create a Segmented Control and add it to the Tableviews HeaderView.
For the FooterView it seems like this is some kind of subclassed Tabbar.
Easiest way to customise it in such a way, would be to create a View, and add buttons to it. Add this View as Subview to your TableViewController.
Have 2 UITableViewCell's one for each type i.e. 1 for showing the image and text and another for showing just the text.
Then in the cellForRowAt delegate method determine which to type to use based off the object you are data binding it to.
Example:
public final func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let customObject = customObjects[indexPath.section]
switch customObject.type {
case .imageAndText:
if let cell = tableView.dequeueReusableCell(withIdentifier: ImageAndTextCell.identifier, for: indexPath) as? ImageAndTextCell {
cell.customObject = customObject
return cell
}
case .text:
if let cell = tableView.dequeueReusableCell(withIdentifier: TextCell.identifier, for: indexPath) as? TextCell {
cell.customObject = customObject
return cell
}
}
return UITableViewCell()
}

Resources