iOS >> Separated .h&.m Files to Manage a UITableView - objective-c

In my app there's a UITableView that appears in several different UIViewControllers - same data base, same design, same IB. The difference is that in each different UIViewController the UITableView size and specific data taken from the data base is different.
I thought of creating one set of .h&.m files that will manage these UITableViews for all the different UIViewControllers and then I can avoid duplicating the UITableView methods.
I'm familiar with how to do that for UIView by creating a new Objective-C Class file of type UIView. Is there a way to do the same for UITableView or do I need to create a UIView.m&.h files and have them be delegated to UITableView?

EDIT: I misunderstood your question the first time - let me try again.
You want a class that can handle the datasource and delegate operations whereever the table is used. So this is a helper class, and it will be a subclass of NSObject. There are several ways to configure this - that said, you will almost for sure need a "delegate" - the object that instantiates this class and with whom you will most likely need to update as things happen.
So create a protocol - as you design this you will find out exactly what needs there as you code the class and try to use it.
to populate this class you have several methods:
1) use an NSArray property, and populate the array with dictionaries. Each dictionary will have the info for one row. Or if multiple sections, the array has arrays, each of the latter containing dictionaries with the information to populate cells with.
2) provide a large number of properties on the class that contain the information to configure each cell with
3) use the protocol to request information from the "owner" class on an as needed basis.

Related

Access the same object inside two different nib files

I want to know how the same reference of an object of a particular class can be accessed inside two different Xibs.
I understand that by creating an object reference for the class inside each xib creates different objects. Even when using AppDelegate its creating different objects.
What I want to achieve is that referenced object inside both the xibs should be the same (so that I can use the object as the datasource of two different table views for instance.)
Only create the object once, and put it somewhere you can get to it from both classes. For instance, you could create the object as a property of your application delegate. Then add
AppDelegate *app = [[UIApplication sharedApplication] delegate];
to your classes (after importing AppDelegate.h) and access the object with app.objectName.
The other answer will work but it's a bad design.
You should stick to the tell don't ask rule. Give your objects the dataSource you want them to use, do not have them asking for a dataSource, which is actually a nasty global.
The other issue is your understanding of nibs. They store an object graph, when a nib is loaded the graph is un archived and each object in it is instantiated. If you have two of the same objects in the graph then you will end up with two instances not two references to one instance. It is the same for when you drag out multiple views, you end up with multiple instances of UIView (and subclasses) which is exactly what you would expect.
It's well worth the effort in learning the boundaries between what you can/can't do in a nib and what you have to do in code and how they all fit together.
Interesting !
Try using singleton approach, check out this link http://www.duckrowing.com/2010/05/21/using-the-singleton-pattern-in-objective-c/
Using this approach, you can create an instance which will be available throughout the application life cycle

What is the appropriate UITableView delegation strategy for this situation?

I have a UITableView and I would like all the functionality that comes built into the UITableViewController except that I would like to have the delegate be a separate class. The problem is I need to pull an identifying piece of information from my data source in order for my delegate class to function. Should I make UITableView delegate to UITableViewController, which would then pull the appropriate identifying information, and then just call the third class from within didSelectRowAtIndexPath? I just want to structure this in the appropriate way.
I am fairly new to iOS and objective-C, so I feel like there is a solution that everyone would use, but it is not obvious to me.
I would make the delegate and the data source both point to your custom class. It will be easier to manage table view events all in one place and you really don't need a UITableViewController. If you separate them, there will most likely be heavy coupling between the delegate and the data source as it sounds like you would need to transfer a lot of information between each of them, which defeats the purpose of dividing them into separate classes.
A strategy that I normally use when I have two table views in the same UIViewController and that can fit your needs is to create an Object class for each tableView for example: MyFirstTableViewManager and MySecondTableViewManager.
Each table view manager is set as the delegate and data source to each tableview.
If I need to display a lot of information on each tableview I create properties on each Table View Manager class which I set from the UIViewController.
This way I split the logic of managing each table view to make it easier and keep it clean and from my UIViewController I can set the information to display on each table view by settings each Table View Manager properties and make them to reload its data when required.
Hope this helps you.

Splitting up large iOS View Controller?

I have a view table view controllers that contain a fairly large set of functionality and many lines of code - Is there an accepted way to split the single controller into multiple controllers or objects to help make it more readable and easier to navigate/maintain?
Yes there are ways to make your code more modular. First off using a UITableView there is a Delegate and a DataSource. You can create separate NSObject classes for each of these.
The DataSource class would contain things like tableView:cellForRowAtIndexPath: and tableView:numberOfRowsInSection:. With the full list here: UITableViewDataSource.
The Delegate class would contain things like: tableView:didSelectRowAtIndexPath: and tableView:willDisplayCell:forRowAtIndexPath:. WIth the full list of here: UITableViewDelegate
It really matter on where most of your code is. If its all in creating a custom cell create a class for that and just send it the info it needs to build its self.
You could just use two subclasses of UIView (or tableView depending on what your are doing) to make the View code a bit more modular. Without more details on what you are attempting it is hard to be more specific.

Adding data to a scrollview/table

I have an NSCrollView that contains an NSTableView. It has 3 columns and 4 rows. I have 4 NSStrings with content that I need to copy into the scrollview.
Using Xcode 4 I tried connecting the table or the NSTextFieldCell and then adding the text via
[_Cell1 setStringValue:MyString];
But nothing happens. It doesn't get updated.
Any way to do this?
Thank you.
EDIT:
I found the following answer to a similar question. I still am confused but after reading Apple's example about bindings I can only say that this does not make any sense, so much code to achieve something so simple. That's the problem with everything being an object and with OOP in general.
Any simple samples out there? I don't even know how to start setting this or connecting the gazillion things you need to connect to start working with this
You should use the NSTableViewDelegate. That's a set of methods the NSTableView calls to get the data that it should display. You just have to declare the delegate object of the tableview.
Delegate Protocol
NSTableView Tutorial
Unfortunately, you can't "add" or "set" the content of a table view. Like most view objects, a table view doesn't store content; it depends on a controller to provide content when it needs it.
There are two options:
Data source: simplest, easiest to understand
Binding to an array controller: harder to understand, but less work to implement
The best Apple resource on the subject: Populating Cell-Based Table Views from the Table View Programming Guide. If you're struggling, I suggest you start with the data source option. It'll be just a few lines of code, and you can adapt the simple samples from that document.
To populate the table, you need to implement these two methods:
– numberOfRowsInTableView:
– tableView:objectValueForTableColumn:row:
And to change the data, you'll need to implement one more:
- tableView:setObjectValue:forTableColumn:row:
You'll need to set your controller as the data source for the table view in interface builder. And the correct protocol for this is NSTableViewDataSource, not NSTableViewDelegate.
You could use an NSArrayController and bind the table columns' value bindings to the array controller's arranged objects. Then add the values you want to display to the array controller.

Drag-and-drop files onto an NSTableView?

I have an NSTableView which I wish to allow users to drag-and-drop video files onto. When they drop the file, it'll get added as a row in the table view.
How would I go about doing this? Currently the tableview's takes its data from an Array Controller (which takes its data from a NSMutableArray)
I found this documentation, but cannot seem to make it work..
I have..
made a "TableCon" class (which I changed to inherit from NSTableView, not NSObject)
changed the NSTableView class to TableCon
set the NSTableView's delegate outlet to that class
called registerForDraggedTypes in TableCon's init
implemented - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender; (again in TableCon)
..but, nothing, it acts like I never changed anything (no errors), what am I doing wrong?
Edit: I've tried implementing Boaz Stuller's suggestion, and also found this description of the solution (the first reply includes the solution to the first post). So what I have done now is..
Subclass NSArrayController which feeds content to the table view (TableListCon)
Add tableView outlet to TableListCon (and pointed it at the NSTableView)
Implement validateDrop, writeRowsWithIndexes, and acceptDrop in TableListCon
Called registerForDraggedTypes on the tableView outlet.
Again, no errors/warnings, but only the awakeFromNib method seems to be called (None of the other methods are called)
NSTableView handles drag-and-drop differently from generic views, which is overall a good thing. It means that you don't have to manually handle the complicated highlighting, cell tracking and inserting behaviours that tables require.
A description of what is required can be found here. Basically, you still call -registerDraggedTypes: (generally in your -awakeFromNib method) but instead of implementing the NSDraggingDestination methods, you implement the various data source methods associated with drag and drop, which can be found here. You should not need to subclass NSTableView to implement drag-and-drop in this fashion.
Note those are data source methods. You need to hook the table view's dataSource outlet to the class that implements those methods in order for them to be called.
In addition to what Boaz said, it sounds like you're creating an NSTableView subclass and then making an instance of that subclass the delegate of NSTableView. If you're going to subclass, that subclass should be used in place of NSTableView, not in addition to it. Also, it's almost always a violation of concerns to have a view be a delegate for another object.