What is the appropriate UITableView delegation strategy for this situation? - objective-c

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.

Related

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

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.

Separate Delegate and Controller

As many other developers new to Cocoa, I struggle with delegate and controller concept. I get the basics, but one thing bugs me. Practically every explanation says that "usually" or "in simple cases" (which are the only ones they give as examples) controller and delegate tend to be the same object.
That leads to a question: when would you want to separate controller and delegate for the same interface object?
Two general cases when using a separate class for your delegate is needed are
When you need to perform unrelated actions in response to the same delegate message, or
When you would like to share the logic of the delegate among multiple views or controllers.
An example of the first situation would be a page with two unrelated tables. Each UITableView would need its own delegate, so using the controller as the delegate would require an ugly if statement in each delegate method; defining and using separate delegates is clearly preferred in this case.
An example of the second situation would be a group of similar pages that show DB data from tables of similar structure. Pages themselves are sufficiently dissimilar, so you cannot reuse the controller in its entirety. If you choose to put the delegate into the controller, most of the logic behind the table view's data source would be identical. You can put the code into a shared delegate implementation, and have each controller instantiate that delegate with the configuration parameters specific to the table associated with this controller.
One note to keep in mind when using another object besides the controller as your delegate: the controller should retain / keep a strong reference to the delegate, since the view will only keep a weak / assign reference to it. See property "assign" and "retain" for delegate for more information on this.

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.