IOS 7 DateCell example with a XIB - ios

I have looked through Apple's DateCell example, unfortunately as all other examples I found it is based on a storyboard. I am trying to create a simple TableViewController with two cells, one for showing the selected date and another for showing a date picker.The Controller will be connected to a bigger app which does not use storyboards. Can somebody write a short guidelines how to recreate the TableView from Apple's example as a XIB and a few sentences regarding the implementation?
Thank you in advance!

After making a sufficient research on the topic, I managed to build a solution out of two separate tutorials.
My main problem were the dynamic prototype cells used in the storyboard example provided by Apple. Therefore I created a customised cell with UIDatePicker inside. I used this tutorial to customise the cell xib file according to my needs and then used it in the UITableView.
Afterwards I followed this tutorial, only instead of a storyboard I created a UITableViewController and used the custom cell with UIDatePicker inside. This example seemed much easier to follow than the sample code provided by Apple.
I didn't encounter any other problems on the way, but if you have any questions I would gladly try to answer. I am still quite new to iOS and Objective-C, so maybe three is a better and easier solution out there.

First of all you need to create two custom cells (one for selected date, second for picker), which both are subclasses of UITableViewCell.
You also need to create two xib files for them. Then change the class of xib to our custom class and connect outlets. Next import that classes to your UITableViewController. In method viewDidLoad write something:
UINib *customNib = [UINib nibWithNibName:#"CustomNibName" bundle:nil];
[self.tableView registerNib:customNib forCellReuseIdentifier:#"CustomCellIdentifier"];
After that you can use your cells in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method:
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CustomCellIdentifier" forIndexPath:indexPath];

Related

How to create a repeatable view in iOS and XCode

I am somewhat new to iOS, but am experienced in Android.
I have an app I am working on and it needs to populate a page with your "history" of past people you've interacted with, and it shows their picture, name, rating, and some other information.
This needs to populate in a vertical list, maybe a table? See the image below...
Now, in android, I would create a custom class with a layout that houses the picture, name, information, rating, and what not in one xml file, and in the activity I would call that class in a for loop, grabbing all the users and then programmatically it would add each view one after another, with their own unique user information until there is no more users to populate with.
How exactly can I do this in iOS and xcode? Do I need to make an XIB and add the picture, name, rating, and info place holders in that, and create a custom class for it that I would use to run in a for loop as well? I am a little stuck on how to do this with iOS.
Any help is much appreciated, and I can provide any additional information! Thanks :)
In iOS, you probably want to use a UITableView, with each row being a custom subclass of UITableViewCell. You can either create the layout for those cells in a separate XIB, or put the whole lot, tableView and "prototype" cells in a storyboard. You can achieve a lot without even subclassing, so fire up a dummy project in XCode and play (using one of Apple's templates gives you a good start). Enjoy.
What you probably want is to use a UITableView.
You don’t do the for-loop yourself. What you do is implement a set of delegate methods that the table view calls back to.
You can create your prototype cell in your XIB or Storyboard. When you add a Table View to the layout, you can then add a cell to that table view, and that cell will be your prototype. It looks like you only need one prototype cell, but you can create as many as you need. In Interface Builder you give the prototype cell a “reuse identifier”, which is just an arbitrary tag you use to refer to the prototype in your code. Your prototype cell can be your own subclass of UITableViewCell, or if you don’t need any custom code in it, you can just use UITableViewCell.
Then you implement several delegate methods. One is where you set the number of sections in the table view; it looks like you will only have on section.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tv
{
return 1;
}
Then you tell it how many items are in the table view. Assuming you have the objects you want to display in an array, you just return the length of the array.
- (NSInteger)tableView:(UITableView *)tv numberOfRowsInSection:(NSInteger)section
{
return self.objects.count;
}
Then, for each item in the array, cellForRowAtIndexPath will be called. Make that method return the actual cell. You call dequeueReusableCellWithIdentifier to retrieve your prototype cell, using the reuse identifier you assigned in Interface Builder. Then use the corresponding object to set up the UI elements in your cell.
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)i
{
UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:i];
Thingy *item = self.objects[i.row];
cell.textLabel.text = item.name;
return cell;
}
That should be enough to get you started with the documentation, now that you have the overview of what you need to implement.
The first thing you have to do in switching from Android to iOS is to learn the terminology. Then you'll know what to search for on Google, SO, etc.
What's you're looking to do is create a UITableView.
Here is a link to a super basic 'how-to' to get you started with tableviews.
http://www.appcoda.com/uitableview-tutorial-storyboard-xcode5/
Once you've got the basics down, you'll want to take that a step further with learning how to customize the UITableViewCell within your tableview, so you can accomplish the look you've detailed in the question.
http://www.appcoda.com/customize-table-view-cells-for-uitableview/
I'm not sure I can help anymore than that at the moment. Jump in, learn tableviews, and start searching on OS to answer the million other questions you'll have a long the way.
Good luck!

iOS todo-tutorial, can't repopulate tableview

So yesterday i began learning iOS programming, and i followed the tutorial for the to-do app.https://developer.apple.com/library/ios/referencelibrary/GettingStarted/RoadMapiOS/SecondTutorial.html#//apple_ref/doc/uid/TP40011343-CH8-SW1
I have created my own tablelistviewcontroller as the guide tells me, and all my previous static data is gone when i boot, and the tutorial tells me this
you’ll notice that it implements three methods—numberOfSectionsInTableView:, tableView:numberOfRowsInSection:, and tableView:cellForRowAtIndexPath:. You can get your static data to display again by commenting out the implementations of these methods. Go ahead and try that out if you like.
So i commented out the cellForRowAtIndexPath, it was the only one commented out. And then i got an error at the "reuseIdentifier", so after a time of googling, i have managed to name my cells "Cells" and i ended up with this code,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cells";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
return cell;
}
But everytime i build and start the app, i cant see my previous data, i can see it in my storyboard, but not in app.. And now i am out of ideas and since i am a newbie i believe the solution is pretty easy.
Please notify if you need any additional data.
I think you really misunderstood these lines:
So why doesn’t your data show up? Table views have two ways of getting
data—statically or dynamically. When a table view’s controller
implements the required UITableViewDataSource methods, the table view
asks its view controller for data to display, regardless of whether
static data has been configured in Interface Builder. If you look at
XYZToDoListTableViewController.m, you’ll notice that it implements
three methods—numberOfSectionsInTableView:,
tableView:numberOfRowsInSection:, and
tableView:cellForRowAtIndexPath:. You can get your static data to
display again by commenting out the implementations of these methods.
Go ahead and try that out if you like.
The thing is when you are adding data using your app, the data is no more static. It is dynamic. UITableView doesn't store your data. It just displays it. And when you are using dynamic data, you will need a datasource which will give the tableView the data to display. You must store the data by some possible storage mechanisms in IOS. Here is a link to one such tutorial which will get you started with Core Data.
Here is a good tutorial which will get you started with UITableView that will display a dynamic data.
The problem is you got the concept totally wrong.
EDIT
You might have added something like <UITableViewDataSource> in the interface file and may have added the ViewController as the datasource for the table(either using ctrl-drag in story board or tableView.datasource = self; in the code). Just remove these two and your static content will display again.

invalid nib registered for identifier (CELLNAME) - nib must contain exactly one top level object which must be a UITableViewCell instance

Sorry for the long title, but I wanted it to be clearly seen from a google search.
Also, this differs from many of the other similar questions on here as its not specifying a 'null' identifier but one that actually exists.
Essentially the problem occurs when your trying to navigate using one of the cells in a table view controller to segue to another view (Whatever that view may be).
Most people would run into this problem after gunning through the apple tutorial on the 'To-Do List' and expecting the cells to operate in the same motion regardless of their purpose.
This problem is probably simplistic to most but for a beginner, its quite hard, it took me around 3 hours.
Basically the error is:
invalid nib registered for identifier (prototypeCell) - nib must contain exactly one top level object which must be a UITableViewCell instance
Where 'prototypeCell' would be whatever your cell is called. This is an exception that occurs immediately as the app is launched.
I had the same problem as above but I wasn't using storyboards and the problem just appeared out of the blue.
I found that the solution was in the tableview cell file. I had added a uibutton, but it had been added outside the bounds of the cell by mistake. This meant it was almost like an extra view in the uiview.
Once I found it and deleted this extra view the problem disappeared immediately.
If you have having this error, check the uitableviewcell for extra views and objects added by mistake
The answer of simon_smiley pointed me to the right direction, but some more trial-and-error was needed leading to the following solution:
The problem doesn't only occur for additional top-level UIView objects, but also for gesture recognizers. So make sure not to use any gesture recognizers in your failing XIB file, you can set them up in code instead.
For example you can do it in awakeFromNib as noted by vahotm in the accepted answers comments.
I had the same problem! And in my case custom cell was the subclass of UIView by mistake instead of UITableViewCell. So replacing UIView with UITableViewCell fixed the problem!
Same problem because I drag and drop a UITapGestureRecognizer on the subviews of ContentView. Just remove it.
In my case, I had an extra ImageView inside the xib added by mistake. Removed it and everything worked perfectly.
The problem is that there are multiple cells in your storyboard that have the same name. Such as for a single table view, there are multiple cells that have the same identifier. In my case I had three cells that were all called 'prototypeCell'.
The fix is actually quite easy. For every cell, name it a simple name with the cell number at the end. This cell number has to match the indexPath.row later on, so basically start from 0 onwards.
For Example:
prototypeCell0
prototypeCell1
prototypeCell2
Then, go into the class thats responsible for the controller, and find the function
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
Then replace the code:
static NSString *CellIdentifier = #"PrototypeCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
With the code:
static NSString *CellIdentifier = #"ListPrototypeCell";
NSString* num = [NSString stringWithFormat:#"%d", indexPath.row];
NSString* actual = [CellIdentifier stringByAppendingString:num];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:actual forIndexPath:indexPath];
Everything else can stay the same. This code basically gets the row number, adds it to the identifier base, the gets the cell from the table using that string. So if its responding to a different row number, it return a different cell.
Just for clarification, my whole function for the problem is as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ListPrototypeCell";
NSString* num = [NSString stringWithFormat:#"%d", indexPath.row];
NSString* actual = [CellIdentifier stringByAppendingString:num];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:actual forIndexPath:indexPath];
cell.textLabel.text = self.content[indexPath.row];
return cell;
}
Good Luck!
Also, this is my first Answer/Question combo, so I really have no idea how to approach it, so if i've done anything wrong, please tell me and/or change it.
Thanks!
I'll put up my dumb solution for the sake of googlers...
This was my personal dumb mistake - when I created a new custom cell for my table view, I went to the top level directory of my project -> add new file -> and created an Empty File type under the OS X section rather than the iOS section.
Hopefully, most people have the other issue described above since it's less embarrassing :P
Sometimes you using storyboard and have collectionView inside it and collectionView as well. After that you decide to simplified your Storyboard and divide cell into another nib. You create empty nib, Ctrl+C from storyboard -> Ctrl+V into nib.
Everything looks fine but you'll have Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'invalid nib registered for identifier (PrettyCollectionViewCell) - nib must contain exactly one top level object which must be a UICollectionReusableView instance'
Ansver: do not do this. After I clean nib and add all of elements as I've in Storyboard - it fixed.
Seems like Bug of xCode IB - Version 7.3.1 (7D1014)
This error is mainly due to some extra views that are added by mistake. Have a look in the .xib file and check for extra unwanted view added by mistake. Delete that and it will work perfect. You can check for unwanted views by this is how it looks
In my case,
I have added UITableViewHeaderFooterView subclass and XIB in different target instead of actual target.
Make sure it is in running target.
I solved this by setting the class name in interface builder to match the cell reuse identifier (for that class) in interface builder.
Note: I'm not saying the class and identifier have to be the same. I'm saying they need to link the corresponding view and backing model.
I had this issue, finally found out that i had created UITableViewCell Subclass instead of CollectionViewCell subclass. it was evening, and i was tired,lol. Fixed it in the mng.
I dragged collection view cell from other project and got this.
'invalid nib registered for identifier (cell) - nib must contain exactly one top level object which must be a UICollectionReusableView instance' .
Then i compared the collection view cell from created my me and found reusable view missing. Hope this help.
It was a silly mistake on my side and I had two tableview cells which caused this error. Removed the other 'table view cell' which fixed the issue.

UITableView inside UIViewController not displaying

I am trying to set up a UITableView inside of a UIViewController. I'm doing this because it allows me to add a top bar with save and cancel buttons. I'm using storyboard and static cells to model the tableview to get input from the user (think of the create new event in Apple's calendar app). I have the view in Xcode, but when running it on my phone or the simulator, the tableview does not display. Here is the simple view in Xcode:
And this is how it displays when running it:
I've read about adding delegates and setting the datasource and such, but really this is all just going to be static cells with text fields, no data being loaded. Why is this happening and what can be done to fix it? Thanks!
#Made2k It looks like you found a solution, but for others who come across this with the same issue, note that you can only use a UITableView with static cells inside of a UITableViewController. This is not a well-documented fact, but apparently only UITableViewController knows how to handle the layout of static cells, whereas a regular UIViewController just needs to implement the UITableViewDelegate and UITableViewDataSource protocols in order to handle display of content in a UITableView added either programmatically or via Storyboard/Nib.
Hopefully this will save someone some time. #Made2k's solution is fine, but does make your storyboard unnecessarily busy. If you don't need to use a UIViewController, then just do your work inside a regular UITableViewController and save yourself a headache.
If you want to use a UITableView in a UIViewController you have to make the ViewController a data source and a delegate of the TableView and then implement methods
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
In case of a static table, in the cellForRowAtIndexPath you'd return outlets of the static cells. For a detailed description check out this answer:
https://stackoverflow.com/a/19110821/3110536
I ended up thinking about this in a different kind of way. The problem I thought I was having was I wanted all the features that a navigation controller provides, but I needed this to be the base of the controller, i.e. nothing to go back to. I was thinking that the only way to do this was to create a UIViewController and add the table view and such in there, but what I came up with is to simply just create a new navigation controller and now this view shows up as the root view like so:
I don't know if this is the best practice, but hopefully it can help somebody else if they are having this problem.
Man, following Hack really works!
You should give it a try!
In my requirement I wanted to add buttons in my Static cells too!and Toggle the visibility of the TableView
[self.tableView setHidden:YES/NO];
and Reload it with new data
[self.tableView reloadData];
and so many things is possible with that way of doing it!
https://stackoverflow.com/a/19110821/1752988
Hope the above link would help you! (Y)

Adding rows to UITableView built from Storyboard

I have a static UITableView built from a Storyboard that works well. I want to fill the first category programmatically, though, from a user-defined file
Simply put, I want to go through all the strings in an array and add them as cells for the rows of the first category. For the second category, I have a series of mildly complex cells (containing a number of labels, textfields, buttons and other controls), defined in the storyboard, that I don't feel like recreating in code.
As far as I understand, the default behaviour for a UITableView built from a storyboard is to use the nib file as an implicit datasource. If I use a custom class as datasource, my second section doesn't work. I have thought of two possible ways to fix this:
Fill my first category from the datasource and delegate the rest to the nib file. Is this possible? Is there some method to programmatically ask the nib to fill my UITableView?
Export my storyboard-built cells into code and paste this code into my datasource. This method has the disadvantage of making my second category harder to modify.
Is one of those two options feasible? Is there another option?
I would use dynamic prototype cells. Then, I would set up the ViewController as the delegate and the dataSource. I would then create a custom subclass of UITableViewCell and connect the elements of the second section to IBOutlets in the custom UITableViewCell.
If the first section wasn't something that could be done with one of the generic cell types, I would also create a custom subclass of UITableViewCell for that section as well.
I would then use the cellForRowAtIndexPath: method to set up the cells with the information that I want in them. So if my first section used FirstSectionCell and my second section used SecondSectionCell as custom subclasses of UITableViewCell my cellForRowAtIndexPath: would look like this:
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.section==0)
{
FirstSectionCell *firstCell = [tableView dequeueReusableCellWithIdentifier:#"First Cell Prototype"];
//Set up the first cell.
return firstCell;
}
else if(indexPath.section ==1)
{
SecondSectionCell *secondCell = [tableView dequeueReusableCellWithIdentifier:#"Second Cell Ptototype"];
//Set up second cell.
secondCell.someLabel.text = #"whatever";
//etc.
return secondCell;
}
else
{
//if you have another section handle it here.
}
}
There are two kinds of table views when you use Storyboards:
Static
Dynamic
You're currently using the former. You define everything in the Storyboard and have very little code.
But you need to change to the latter.
You can still keep your UITableViewCells in the Storyboard; there's no need to do that in code (though you can if it makes things easier). You can refer to the template cells using the "reuse identifer."
Otherwise you've pretty much got it. You'll need to write code to implement the data source and (possibly) more methods of the table view delegate.
It's kind of fiddly switching from static to dynamic. I keep meaning to raise a Radar because I'm sure Xcode could be making it easier to do...

Resources