I'm new to iOS and trying to rewrite an app from android.
What I do in Android - I have a layout - same as nib in xcode
And then I inflate this view as many times I want - same as ListView (TableView's android analog) is working
I need to do this on iOS :
which means having some container like Android's horisontal LinearLayout where I can add nib's with their class - like UITableViewCell and fill data.
When I asked one person who is iOS developer, he told me that it is almost impossible to do due to compexity and lack of android-like ViewGroups and that it's better to do in a WebView than natively.
So please, tell me , is there a solution - to inflate as many views as needed from a nib into container-views one under another ? Please answer in Swift, I don't know Obj-c at all
Yes you can do it by registering your tableView with Xib in viewDidLoad
tableView.registerNib(UINib(nibName: "CustomCellXib", bundle: nil), forCellReuseIdentifier: "CustomCell")
Then do this in delegate method
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomCell", forIndexPath: indexPath) as! CustomCell
cell.middleLabel.text = items[indexPath.row]
cell.leftLabel.text = items[indexPath.row]
cell.rightLabel.text = items[indexPath.row]
return cell
}
where CustomCellXib is your Xib file name.
CustomCell is your class of CustomCellXib
and #"CustomCell" is string identifier for reusing cells
Note down that you will have to implement other few delegates methods too for complete working of TableView.
There is nothing extremely complex here. It's a common UITableView with multiple sections.
Red text labels for every sections should be implemented as section headers
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
//create a view here
}
Custom UITableViewCell with grey labels, red - and + buttons in it.
Custom cell should contain a UIImageView below it's content. Since it is different for first, middle and last rows, you should set one of three images in cellForRow method depending on the cell's indexPath.row.
P.S. Don't listen to your iOS developer. You should not use UIWebView whenever you need to implement UI a bit more complex than default UITableView. Most probably he was joking ;)
Related
I have a table view controller and I overrode this function:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath)
// Configure the cell...
return cell
}
My cell identifier is myCell. I created 4 static cells, and went into each cell and gave each the identifier myCell. However, this crashes due to not recognizing the cell identifier. However, if I change to dynamic prototypes, give the cell the myCell identifier, it works as intended. I guess this will do for now...as I can just tell it dynamically how many cells I want. But I'm really interested to find out why my static cells aren't working with the same exact method. Any ideas?
When you have static cells (i.e. a small, fixed set of static cells, rather than dynamic cells with cell prototypes where you control how many of which types of cells will be dynamically generated), you shouldn’t implement any of the UITableViewDataSource methods. Just create IBOutlet references for the various controls you have in your static cells and update them just like you would if you weren’t using a UITableView at all.
As an aside, if you were using dynamic cells, you would never give two different cell prototypes the same reuse identifier. The purpose of the reuse identifier is to let it know which cell prototype to use, and it wouldn’t therefore make any sense to give multiple cell prototypes the same identifier.
I am making ios app, and I am beginer in iOS. I am making an app and in this I am trying to make the custom tableview cell.
For this I Have added a cocoa touch class and also check to create its nib file.
Now in IB I am putting views like UiLabel,Buttons etc int it , making its height bigger in IB. But this is not updating the View. I can not see any thing inside the View.
I want to see it visually so that I can set autolayout constraints
through IB. Did any one notice this thing? Why the view of IB is not
updating? I have started my mac. but it did not help. Any suggestion
please?
Note: I am using Xcode 9.2
Have you registered your nib file as UITableViewCell? First you need to register your nib file in viewDidLoad of your class where you have dropped the outlet of your tableView.
override func viewDidLoad() {
super.viewDidLoad()
tableView.registerNib(UINib(nibName: "CustomOneCell", bundle: nil), forCellReuseIdentifier: "CustomCellOne")
}
After this, go to your tableView delegates,
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomCellOne", forIndexPath: indexPath) as! CustomOneCell
return cell
}
Make sure to assign the tableview delegate and datasource.
I'm creating a couple of cards with information to display. Each card is going to be represented with a UIView, so I'm creating each card in different .xib files.
One of my cards contains a custom UITableView and cells which are going to be loaded and managed with the UITableViewDataSource and UITableViewDelegate protocols.
However when I search for the Table View component and drag it to my .xib file it loads a predefined UITableView which I can't customize.
I'm fairly new to using separate .xib files (I've been using storyboards) so I don't know how to customize my TableView in this context so any help would be appreciated.
Xibs dont have the tableviewcell prototypes like in the storyboard, unfortunately its a storyboard only feature. Xibs are a bit archaic but still have their purpose. But you can have the different cells within the same xib file as your tableview, they will just be separate to the tableview.
you would load the xib like
var objects: NSArray?;
NSBundle.mainBundle().loadNibNamed("MyTableView", owner: self, topLevelObjects: &objects)
then in the array, depending on the order of the elements in the xib, you will get back an array of all the elements in your xib. so probably at position 0 will be your tableview, then 1 will be a cell, 2 a cell etc.. depending how many you have. you'll probably only load the cells in cellForRowAtIndexPath: only though, while the table will be in viewDidLoad or something
make a tableview and create a tableview instance.
write this code in viewdidload...
self.tableView.registerNib(UINib(nibName: "PackageDetailTVCell", bundle: nil), forCellReuseIdentifier: "Cell")
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return self.arrayDict.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! PackageDetailTVCell
let dict = self.arrayDict[indexPath.row]
cell.labelOfferPrice.text = (dict .objectForKey("offer_price") as! String)
cell.labelName.text = (dict .objectForKey("title") as! String)
cell.labelRegularPrice.text = (dict .objectForKey("price") as! String)
return cell
}
I'm trying to make a simple UITableView that has a button appended to the right side of every cell. I added the button to the prototype cell in my storyboard and set up the constraints so that AutoLayout takes over and puts it in the right spot. When I go to preview the layout in the Assistant Editor, everything looks great. However, once I start the simulator and go to that view, the button is no longer there (the cell is blank).
I ran into a similar problem when I tried to add a Disclosure Indicator and it wasn't showing up - to fix it I had to add that accessory programatically. Isn't the point of storyboard to help make changes without using code? I'm still really new at this and would appreciate some guidance.
EDIT: Some code as requested (sorry):
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
let addButton = UIButton()
let menuItem = currentOrder?.getSortedMenuItems()[indexPath.row]
let itemPrice = "\(currentOrder!.menu[menuItem!]!)"
cell.textLabel!.text = menuItem! + " - " + itemPrice
return cell
}
Most of the code in there is pretty irrelevant, but as you can see I tried adding a button and then stopped cause I wasn't sure where to go from there. I was under the impression that all of this could be done using storyboard.
The problem which you have arises from the fact that you are NOT using the cells which you created in your storyboard. When you call
let cell = UITableViewCell()
it creates a cell with default style. What you want to do instead is to use the cells which you created in the storyboard.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cellWithSwitch") as! UITableViewCell
// setup your cells (e.g. update its title)
return cell
}
You should change the "cellWithSwitch" to the identifier which you have set for your cell in storyboard.
You can find the identifier of your cell by selecting it in the storyboard and then checking info in the Attributes inspector:
If you haven't yet set this identifier - set it and then use it. And then changes which you make in storyboard will get reflected on the phone ;)
Extra
It is often necessary to subclass your cell to make it easier to work with. Here is an example:
class MyCell:UITableViewCell {
#IBOutlet var myButton: UIButton!
}
Now, you have to do 3 other things:
1) Select your cell in the storyboard and set its class to MyCell in Identity inspector (that's the third tab in the image which I posted)
2) Open Connections inspector (last tab) and connect the myButton outlet
3) Modify your cellForRowAtIndexPathFunction:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cellWithSwitch") as! MyCell
// setup your cells (e.g. update its title)
// you can now access your button as cell.myButton
return cell
}
I am having two different tableviews in two different controller. But the cells, that I need to display in them, look identical. I have created a prototype cell in one tableView and subclassed UiTableViewCell. Now, if I want to use the same cell in a different controller, how can I use it ?
If I just import that customCell file in the new controller and deque it using the same identifier given in the storyboard, it wont work. It says
Assertion failure in -[UITableView
_configureCellForDisplay:forIndexPath:]
Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'UITableView dataSource
must return a cell from tableView:cellForRowAtIndexPath:'
So, clearly it means , the cell is nil. So how can I instantiate the same cell from the storyboard ? Is it possible or do I have to create a different customCell for the new table too ?
K.. I got it. First of all,
I can NOT use one prototype cell in two different tableview. But, I
can use the same tableViewCell subclass in two different tableviews.
To achieve it, one just have to copy the prototype cell from one controller and paste it as a prototype cell of the other tableview. Class of the pasted tableview remains the same. Just change the reuseIdentifier. and use it.
Edit:
If your cell has a fairly complicated UI, then it makes more sense to create separate xib for the cell alone. Then programmatically register the xib with the table view. That way, you will have only one copy of the cell and much better at maintaining it when there are changes to the ui.
You can use same prototype cell in different view controllers, you just need to dequeue it from the tableview of controller in which you designed it.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let viewControllerInWhichCellWasDefined = tabBarController?.viewControllers?[0]
let cell = viewControllerInWhichCellWasDefined.tableView.dequeueReusableCell(withIdentifier: "identifier", for: indexPath)
return cell
}
If you create a custom cell in XIB it should work just fine. However, I suspect the cell's identifier caused the problem. Try to change your cell's identifier for each table view controller.
If it's not, you might want to post the source code
Yes. We can use a prototype cell of ViewControllerA's tableview for tableview of ViewControllerB. Just need to implement the following code in ViewControllerB
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let vc_array = self.navigationController?.viewControllers
let view_controller = vc_array![vc_array!.count - 2] as! ViewControllerA
let cell = view_controller.tableView.dequeueReusableCell(withIdentifier: "ViewControllerA_ID", for: indexPath) as! ViewControllerA
return cell
}
Here ViewControllerA is the ViewController which contains the tableview with prototype cell, and we are using the same cell on the tableview of ViewControllerB
I have used the same UITableViewCell in different apps. just copy one TableViewCell to the other app. That is both apps have the same layout and such. The apps don't belong to the same workspace. The setup works nice, no problems or errors.. just don't know if thats good practice.