Splitting up large iOS View Controller? - objective-c

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.

Related

IOS: is it possible to bind one story board view controller to several different classes?

I know it's possible to attach a custom view controller class to several different view controllers on a storyboard, but can it be done in the other direction; that is, depending on the situation, I want to bind different custom classes to a single view controller on the storyboard that will be instantiated using:
[self.storyboard instantiateViewControllerWithIdentifier:]
background: I used to have several view controllers on my storyboard that are almost identical. In fact, the custom classes that they each bind to are very similar as well. In an effort to clean this up, I refactored my custom classes into one base class and several subclasses. I then removed all the similar view controllers from the storyboard leaving only one which I've bounded to my base class. I then call:
MySubclass* mySubclass = [self.storyboard instantiateViewControllerWithIdentifier:#"StoryboardControllerBoundToBaseClass"];
Unfortunately, my subclass code is being ignored and only the base class code is ever run. Does anyone know how I can make it work without duplicating view controllers on the storyboard and binding each one to a different subclass?
It's not possible. Just because you say MySubclass *object = something doesn't magically convert object into a MySubclass object. It's stored in the storyboard with whatever class was assigned at storyboard compile time.
Rather than using subclassing, I figure I can reuse a view controller on the storyboard by using a delegate/proxy model. More specifically, I can bind the storyboard's view controller to a custom class that delegates all of its methods/events to others classes to handle. This isn't as elegant as subclassing but at least I can keep my storyboard leaner, not having to keep several copies of pretty much the same view controller. Plus, I won't need to duplicate future changes to every copy of these controllers to boot.
As guylegend writes. Apple doesn't support the way to do that. There are many workarounds e.g. with delegates but I finally found the answer and answered in another topic. Hope it helps!
https://stackoverflow.com/a/32103618/1943053

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.

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.

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.