StoryBoard actions cannot be targeted at repeating content [duplicate] - ios

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

Related

UITableView just for GUI controls, no DataSource

I'm about to write an iOS app in Swift. The main View Controller is a UISplitViewController. The master view of it is a navigation controller whose root view controller is a UITableViewController.
The cells in this TableView should only contain GUI elements (UIButton, UISwitch, UITextField etc.). There are quite a few of them so that I want to make use of the scrolling feature of the TableView and want to design a few custom Prototype Cells.
However, I'm still a learner of Swift, Cocoa Touch and all that. I know that a TableView needs a DataSource (and a Delegate) but because I don't have data to display in my cells ... how would my cellForRowAtIndex function look like? How would I even create a few "constant" cells (of prototype 1, prototype 2, ...) in the TableView? I guess it's not possible at design time in IB but only by code? How so?
Thanks so much in advance!
Setting your tableView delegate in your viewController class is mandatory to override those methods.
You can use numberOfRowsInSection to return a constant value that will be your number of rows.
Inside your cellForRowAt you can verify which row are you in and call appropriated cell.
internal func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
//call cell type 1
}
}
Here you have a reference to create custom cells using xib and call it into your table.
Custom UITableViewCell from nib in Swift

tableview cell in xib can't autosize

here need some help T_T.
I'm design a page that use a collection View to display 4 different table view in 4 collection view cell. Therefore I design collection view in xib and put a table view in it, but in this case tableview have no prototype cell when it is designed in a collection view cell in xib , so I create another xib to handle my tableview cell.
The problem is , when Im adding "estimatedRowHeight" and "AutomaticDimension" in cellForRowAt below
let backgroundCell = detailCellTableView.dequeueReusableCell(withIdentifier: "baseDetailTableViewCell") as! BaseDetailTableViewCell
backgroundCell.setTitleLabelText(title: backgroundTitle)
backgroundCell.setContentLabelText(content: background)
self.detailCellTableView.estimatedRowHeight = 300
self.detailCellTableView.rowHeight = UITableViewAutomaticDimension
return backgroundCell
it would be none change tvcell
The cell size won't autosizing , the label in my custom cell is stacked.
I guess that the problem might be the prototype cell , but I don't know how to solve it..
This is because, this property is added to the tableview and you are adding it to cell.
Steps:
1) Create a tableview outlet.
2) add following code in viewdidload()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 300

How to set header exectaly above the particular content in tableview

I used checkbox and switches in my custom tableview cell. But as shown in the image i need to place the header at the proper place above the checkbox and switch.
How should i suppose to do this.
Thanks in advance.
Follow these steps for achieving your task.
Add a UITableViewController to your storyboard
Create two cell in your UITableView
First cell identifier take as headerCell and second cell identifier take as listCell
Take two label inside your first cell
Now it's time to set constraint first controller click on right label and drag it to first cell and set it to vertical center.
Now click on same label and set its constraint from left as 8 as shown in image.
Set same for Label two which is Selectable.
Now comes with the new cell which is called as listCell see the image and set all constraint as shown in image.
Also don't forget to set width to both label which in header cell.
You would probably need a custom tableview header as well.
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return YOUR_CUSTOM_HEADER_VIEW
}

Configuring UICollectionView to keep the same cell view

I have a collection view delegate
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath)
-> UICollectionViewCell {
}
I wanted the property of the cell to persist between each call to this method.
let cell = levelView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier,
forIndexPath: indexPath)
But retrieving cell using dequeueReusableCellWithReuseIdentifier seems to create a new cell view element that is different from the initial one.
cell.accessibilityIncrement()
So the cell accessibility value cannot persist after tapping on the cell.
I need to do this because I wanted to do UI testing by tapping on the cell.
Any help is appreciated!
Reusable cells in iOS are handled with a queue. This helps the tableViews and collectionViews move smoothly and remain efficient with a large amount of data. I don't think you would want to change the way that is designed to work in your application. This way, the device only needs to load as many cells into memory as can be displayed on a single screen. As cells move off the screen, they can be reused as another cell as cellForItemAtIndexPath will be called to load the required data into the reused cell.
If the goal is to have a value persisted between cell reloads, consider using a map or some other similar variable that could be managed by the collectionView's dataSource delegate.
For example, in your viewController that contains your dataSource delegate, you could have a Dictionary defined like so:
let numberOfTapsByIndexPath = [NSIndexPath: Int]()
Then every time a cell is tapped, you would increment the value in the map for the cell tapped. That code might look something like this:
let previousTaps = numberOfTapsByIndexPath[indexPath]
numberOfTapsByIndexPath[indexPath] = previousTaps + 1
I'm not 100% sure that was the goal you explained above, but regardless, you'll want to move any persistent information out of the cell and into a variable that the dataSource delegate or some other singleton can manage.
Hope this helps!

My header view in UITableView is not added to the UIView Hierarchy

Using UITableView and NSFetchedResultsController I refresh and display the content of my table. At some point I hava a screen without header view. It should be instead of the space between cells.
When I debug View hierarchy I have the following info. Selected cell in UI View hierarchy is appriopriate to the selected cell in Debug View Hierarchy.
To create a header view I use following method:
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let workday = workDayObjectForSection(section)
let cell = tableView.dequeueReusableCellWithIdentifier(PBOUserWorkDayCellIdentifier) as! PBOUserWorkDayTableViewCell
cell.configureCellWithWorkDay(workday)
return cell
}
You shouldn't get view for tableView header using dequeueReusableCellWithIdentifier method. From the documentation:
If a cell object is reusable you assign it a reuse identifier (an arbitrary string) in the storyboard. At runtime, the table view stores cell objects in an internal queue. When the table view asks the data source to configure a cell object for display, the data source can access the queued object by sending a dequeueReusableCellWithIdentifier: message to the table view, passing in a reuse identifier
That means when you return header as reuse cell, tableView might take it do display in another place as cell. Note that behavior of header is different than cell, it stays at the top while section is visible.
However, you may use same view for header but create it from xib, storyboard etc every time and do not assign any reuse identifier. And if you looking for some optimization, you can store them in some array and return cached values. But I would like to recommend not to use subclasses of UITableViewCell as table header views

Resources