Is it possible to select a ViewObject in TableViewCell Content - ios

In other places, we can drag the object as Outlet in a ViewController, give it a name and use it as a reference later. But, In a table cell is it possible to select the Object through Code as:
var cell = tableView.dequeueReusableCellWithIdentifier("menuCell") as UITableViewCell
let contentView:UIView = cell.contentView;
//Can we achieve this?
let imgView = contentView.ImageView

Even though the subviews are added to the contentView, the outlets should be made to the cell itself. So you should have outlets in your cell's .h file, and connect them from the cell to the subview in IB. In code, you would refer to them with cell.label, etc.

Related

StoryBoard actions cannot be targeted at repeating content [duplicate]

I have just created an app and have started hooking up #IBOutlet's to the storyboard. I am connecting some of them to labels in a UITableViewCell Prototype Cell with a Basic Style. When I connect it though I get this error in the Storyboard:
The detailText Outlet from the TableViewController to the UILabel is invalid. Outlets cannot be connected to repeating content.
Can someone help me out? I have set it up the way I always do successfully but this time it has chucked me this error.
Create a table view cell subclass and set it as the class of the prototype. Add the outlets to that class and connect them. Now when you configure the cell you can access the outlets.
There are two types of table views cells provided to you through the storyboard, they are Dynamic Prototypes and Static Cells
1. Dynamic Prototypes
From the name, this type of cell is generated dynamically. They are controlled through your code, not the storyboard. With help of table view's delegate and data source, you can specify the number of cells, heights of cells, prototype of cells programmatically.
When you drag a cell to your table view, you are declaring a prototype of cells. You can then create any amount of cells base on this prototype and add them to the table view through cellForRow method, programmatically. The advantage of this is that you only need to define 1 prototype instead of creating each and every cell with all views added to them by yourself (See static cell).
So in this case, you cannot connect UI elements on cell prototype to your view controller. You will have only one view controller object initiated, but you may have many cell objects initiated and added to your table view. It doesn't make sense to connect cell prototype to view controller because you cannot control multiple cells with one view controller connection. And you will get an error if you do so.
To fix this problem, you need to connect your prototype label to a UITableViewCell object. A UITableViewCell is also a prototype of cells and you can initiate as many cell objects as you want, each of them is then connected to a view that is generated from your storyboard table cell prototype.
Finally, in your cellForRow method, create the custom cell from the UITableViewCell class, and do fun stuff with the label
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "yourCellIdentifier") as! YourCell
cell.label.text = "it works!"
return cell
}
2. Static Cells
On the other hand, static cells are indeed configured though storyboard. You have to drag UI elements to each and every cell to create them. You will be controlling cell numbers, heights, etc from the storyboard. In this case, you will see a table view that is exactly the same from your phone compared with what you created from the storyboard. Static cells are more often used for setting page, which the cells do not change a lot.
To control UI elements for a static cell, you will indeed need to connect them directly to your view controller, and set them up.
If you're using a table view to display Settings and other options (like the built-in Settings app does), then you can set your Table View Content to Static Cells under the Attributes Inspector. Also, to do this, you must embedded your Table View in a UITableViewController instance.
Or you don't have to use IBOutlet to refer to the object in the view. You can give the Label in the tableViewCell a Tag value, for example set the Tag to 123 (this can be done by the attributes inspector). Then you can access the label by
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "someID", for: indexPath)
let label = cell.viewWithTag(123) as! UILabel //refer the label by Tag
switch indexPath.row {
case 0:
label.text = "Hello World!"
default:
label.text = "Default"
}
return cell
}
With me I have a UIViewcontroller, and into it I have a tableview with a custom cell on it. I map my outlet of UILabel into UItableviewcell to the UIViewController then got the error.
As most people have pointed out that subclassing UITableViewCell solves this issue.
But the reason this not allowed because the prototype cell(UITableViewCell) is defined by Apple and you cannot add any of your own outlets to it.
Sometimes Xcode could not control over correctly cell outlet connection.
Somehow my current cell’s label/button has connected another cell
I just remove those and error goes away.
For collectionView :
solution:
From viewcontroller, kindly remove the IBoutlet of colllectionviewcell
. the issue mentions the invalid of your IBOutlet. so remove all subclass which has multi-outlet(invalids) and reconnect it.
The answer is already mentioned in another question for collectionviewcell
Click on simulator ,
Navigate to Window and enable Device Bezels

UIView not filling table views tableHeaderView property swift

I have a very peculiar situation and want to know why its happening. I have an edit box and button in a view that I put into a tableview's tableHeaderView property. I call this view InputToListCell.
Now when the view extends UIView I get the following:
i.e all I change in the code is:
class InputToListCell: UIView{
//Code Here
}
I then change InputToListCell to extend UITableViewCell and get the following:
i.e
class InputToListCell: UITableViewCell{
//Code Here
}
Why is this behaviour occurring? I cant see why because UITableViewCell extends UIView. Any thoughts?
Update:
Based on a comment made here are the constraints for the InputToListCell:
I basically pin both the edit text's and Add buttons constraints to the margin, except for the edit text's trailing value.
In short
Use UITableViewCell for table view elements.
self.tableView.tableHeaderView =
tableView.dequeueReusableCellWithIdentifier("sectionIdentifier")
Discussion
Using UITableViewCell objects for all table view elements not only provide an umbrella behavior when presented inside a UITableView, but will also allow loading from a .storyboard or .xib, an added bonus and cohesion.
Thus, even though tableHeaderView (and viewForHeaderInSection for that matter) is informally just a UIView, you can return a UITableViewCell. According to this post, to take advantage of Autolayout in tableHeaderView, you need to do a bit of gymnastics:
if let tableHeaderView = tableView.dequeueReusableCellWithIdentifier("tableHeaderViewIdentifier") {
tableHeaderView.setNeedsLayout()
tableHeaderView.layoutIfNeeded()
let height = tableHeaderView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
var frame = tableHeaderView.frame
frame.size.height = height
tableHeaderView.frame = frame
self.tableView.tableHeaderView = tableHeaderView
}
From a different post:
For a complete example on how to use .storyboard or .xib for headers, including an Xcode project, see https://stackoverflow.com/a/32261262/218152

illegal configuration the labelname outlet from the classname to the UILabel is invalid error in ios xcode

i am beginner of iOS and i am trying to display some array objects on the label. the label is located on the table cell. when i am going to hookup label and label object in the class then trowing the above error plz assist me .
Thank's.
If you want to connect your label to class, you must make a subclass of UITableViewCell and set the class of your cell to be this one. e.g. you have a cell in your storyboard, you must set the class of that cell (the custom class that you made) and then you can make the outlet..
You can also work with tags. In this case, you will not need outlets. You can get the label using tag. Let me know if it's still not clear or confusing
Another thing that you can do (if you only need label in your cell, then no need to make custom/prototype cell). You can simply do it using UITableViewCell and it has label in it. You can do this as follows (in Swift):
var cell = tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell!
cell.textLabel!.text = "Your text"
TO connect uilabel outlet you have to subclass UITableViewCell first. Then declare uilabel outlet in that class. Assign that class to your tableview cell in xib and then try to set outlet.

Howto fix TableView right margin? (swift)

I've created a tableview within Viewcontroller and inserted disclosure indicator, but it is not showing, because the right margin is not correct.
What I tried:
selecting table and click in xCode on "pin" button and set left and right to 0, select there all frames in container and clicked: add constraints
but without results.
How can i fix this?
I attached the problem as image. (i have added a frame to focus the problem)
Okay, there can be multiple reasons for which this can happen. For instance, one can forget to deck the cell with wrong identifier or may have set the accessory Indicator in a wrong way. My personal assumption is you probably have set constrain improperly.
So, I am just going to show you the whole process.
Step 1: Drag and UITableView inside your ViewController and drag a UITableViewCell inside that TableView. Select the Table View Cell and assign an identifier. Make sure, in your datasource method, -cellForRowAtIndexPath, you use this same identifier.
Step 2: Go to your View Controller and take an IBOutlet of a UITableView.
#interface MyViewController : UIViewController<UITableViewDataSource>
#property(nonatomic, strong) IBOutlet UITableView *myTableView;
#end
Step 3: Go to the connection Inspector of your storyboard and connect the UITableView with this outlet.
Step 4: Go to the implementation file of your View Controller and populate the datasource methods. Also make sure, you set your TableView's datasource to your view controller.
Now when you build and run this code you won't see the accessory Indicator.
The reason is you didn't set the constraints.
Step 4: Just set the constrains like the following and you are good to go.
This is my final view.
You need to change seperator inset inorder to remove left margin. Its set to default change it to custom and make left insets and right insets to zero. You can set the 'Separator Inset' from the storyboard:
Change Seperator insets to Custom and make left to zero
Try to programmatically set the width and height of the tableView like so...
#IBOutlet weak var resultsTable: UITableView! // connect to tableView
override func viewDidLoad() {
super.viewDidLoad()
let theWidth = view.frame.size.width
let theHeight = view.frame.size.height
resultsTable.frame = CGRectMake(0,0, theWidth, theHeight)
}
The problem was not the margin/layout.
To show disclosure indicator in tableview cell's, it is needed to select disclosure indicator from Accessory menu AND give a identifier for the cell.
Without given identifier the disclosure indicator is not showing.

Connect outlet of a Cell Prototype in a storyboard

I'm a newbie with the Storyboard and so I have some difficulties...
I have created a TableViewController and I would like to customize the Cell Prototype. In the Cell Prototype I have added several Labels I would like to customize with my own class which inherits from UITableViewCell (AreaListCell).
In the Storyboard, for the Cell Prototype I have configured the Custom Class with "AreaListCell" and its style is "Custom".
In the storyboard, when I select the Cell Prototype and then the assistant, the assistant display my class that implements the UITableViewController (AreasTableViewController) and not
my "AreaListCell" class.
The consequence is I can create outlet (using Ctrl + Drag from the label of the Cell Prototype) to the AreasTableViewController class but not to the AreaListCell class !
Any idea how to connect the Cell Prototype with my AreaListCell class?
Thanks for your help!
UPDATE: As of Xcode 4.6 (possibly earlier) you can now create outlets by control-dragging! - This has to be done into an interface section or class extension (the class extension doesn't exist by default for new cell subclasses. Thanks to Steve Haley for pointing this out.
You can't get the outlet automatically connected and created by dragging into the code block in the assistant editor, which is poor, but you can create the outlets manually and connect them then.
In your cell subclass interface:
#interface CustomCell : UITableViewCell
#property (nonatomic) IBOutlet UILabel* customLabel;
#end
Synthesize as normal in the implementation.
In the storyboard, select the cell and go to the connections inspector, you will see the new outlet. Drag from there to the relevant element in your prototype:
This can now be accessed as cell.customLabel in your cellForRowAtIndexPath: method.
Yeah you can't connect views that are inside of a custom prototype cell using the ctrl+drag method. Instead use the tag property of the view and then when you are building the cell pull the labels out using their tags.
Here:
//Let's assume you have 3 labels. One for a name, One for a count, One for a detail
//In your storyboard give the name label tag=1, count tag=2, and detail tag=3
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomTableViewCell *theCell = [tableView dequeueReusableCellWithIdentifier:#"Prototype Cell"];
UILabel *nameLabel = (UILabel *)[theCell viewWithTag:1];
UILabel *countLabel = (UILabel *)[theCell viewWithTag:2];
UILabel *detailLabel = (UILabel *)[theCell viewWithTag:3];
nameLabel.text = #"name";
countLabel.text = #"count";
detailLabel.text = #"details";
return theCell;
}
You could also set the labels up as properties in your custom cell code and then when the cell is initialized use the viewWithTag call to assign the label properties to the labels you have created on your storyboards.
It took me a few days to realize I couldn't ctrl+drag from inside a custom cell to create an IBOutlet.
Good luck!
EDIT: You CAN create IBOutlets for your labels inside of a custom cell and create the links programatticaly, just not through the ctrl+drag method.
EDIT 2: I was totally wrong, you can ctrl+drag. See the second answer to this question. It is tricky, but it works quite well.
Swift 3
// we are using this if your images are at server.
// we are getting images from a url.
// you can set image from your Xcode.
The URL of images are in an array name = thumbnail i.e self.thumbnail[indexPath.row]
on UITableviewCell put a imageView on cell
select UIimageView assign it a tag from storyboard.
let pictureURL = URL(string: self.thumbnail[indexPath.row])!
let pictureData = NSData(contentsOf: pictureURL as URL)
let catPicture = UIImage(data: pictureData as! Data)
var imageV = UIImageView()
imageV = cell?.viewWithTag(1) as! UIImageView
imageV.image = catPicture

Resources