Re-initialize view controller, or create separate view controllers for image capturing process? - objective-c

I have created a custom camera overlay to capture an item, but my app requires that I go through the capturing process twice, so basically, once the user has taken the picture of the front of an item, they need to take the picture of the back of that same item, back to back. At the moment I am re-initializing the same view controller after the first picture has been taken, but I have read that it would be better practice to create a separate view controllers for each "step".
Which would be the better option, separate view controllers, or one view controller that gets re-used, as and when is needed?
I am quite new to Objective-C, so I am not sure if I have phrased everything correctly, I hope that I was able to adequately convey my problem.

Related

iOS 7 settings like DetailViewController

I have a simple project that was started from a Master/Detail template for iOS7.
I'd like to layout the detail view controller just like iOS settings. Do folks recommend using a table for that or just laying out the controls one by one?
Here is a screenshot of the effect I am looking for:
This is probably a matter of taste/opinion but I prefer tables for this kind of thing for these reasons:
You get all the nice features of tables right out of the box (efficient scrolling, cell reuse and delegate methods to handle where to push new view controllers on to the stack, etc...).
Flexible data model backed cell data. Your table view needs to be backed by some "settings" model object collection, obviously. That collection can be modified to include or exclude settings programmatically. Combine this with custom cells and you're off and rolling. This is really nice if your UI needs to change on the fly.
Code Reuse. If you have another set of "settings" you can use this data-backed table view approach and change only your data model. Doing this manually means you have a new view controller for every settings view. In your example picture, I'd bet my lunch that the 3 view controllers you see in that image are the same type of object.
The table's delegate methods are really helpful when segueing or pushing to new view controllers. Imagine having 10 settings that all took you to separate view controllers. You'd have to manually hook those transitions one by one, yuck.
Of course if you only have 1-2 settings that will never change, perhaps manual is the way to go. For my money, though, tables make sense because things like this always seem to change.

Two views displaying live data at the same time

I have two view controllers which should work like described below:
First view controller displays a view which has a table in it. The table contains data which is constantly changing. I have a delegate method for reloading the data when a change occurs. So that is taken care of. When the user selects a row in the table I would like to display a second view which would also contain live data in text format (one UITextView which would constantly change).
I would like to allow the user to access view 1 while view 2 would still be monitoring and displaying live data and vice versa. While user is on view 2, view 1 should still be monitoring and displaying any changes in the table content.
I guess its like having two view controllers present at the same time and switching between them.
What is the easiest or the most standard way to accomplish this? I dont mind if its all done programatically.
It's a little hard to tell what you're asking here. First, views shouldn't be processing data at all -- they should only be displaying it. It sounds like what you're describing is having a background process that updates to your second view. That process could certainly be running while your table is on screen, and when you switch to the second view, you can update it using this running process. Exactly how you would do this depends on the details of what you're trying to do. So, I think we could help you better if you provide more context on what kind of process you want going on that updates your second view, and how choosing a row in your table affects that process.
After Edit:
You can certainly do what you want to do. I think the main thing is that you need to have a property (typed strong) in your first view controller that points to your second view controller, so that when you go back to the second controller a second time, it goes back to the same instance. Based on the selection from the table, you can start whatever process you need to populate your text view, and that process can keep running even after you go back to the table view, since that controller won't get deallocated when it's view goes off screen (due to the strong reference you have). You would just have to have some sort of if clause in your second view controller to know whether the user has selected the same row again, and if so, just show the updated text view, rather than starting a new process.
That's about as specific as I can be without more detail from you.
what you have is a problem where you need a custom parentviewcontroller
look into splitviews as one example :: SplitView like Facebook app on iPhone
cool intros of how to do custom container view controllers :: Container View Controller Examples

Retain View Controller when popped from Navigation Controller using ARC

I have two table views and a detail view being managed by a UINavigationController. When a row is selected on the second table, it pops to a detailed view allowing changes specific data represented by the row. I need to be able to switch between the UITableView and the UIViewController without losing any of the data that might have been changed in the UIViewControllers (button selections, text values entered in fields, etc).
Basically, once the UIViewController is presented, one should be able to switch back and forth between the table and detail view without losing any data.
The problem is, when a UIViewController is popped from the navigation controller, that memory is automatically released, and since I'm using ARC, I can't just keep a pointer to that with a retain command in the UITableView.
I know that I could manually rebuild the view each time its corresponding table row is selected, but I feel that might be a messy solution. Another option I've thought of is keeping an array of pushed UIViewControllers and checking if the selected table row corresponds with an existing value before a new one is created, but that might also get messy.
Any suggestions?
Your final wish in this back and forth of view is what you stated in your question: you want to switch between view controllers without losing any information of the actions performed in these controllers.
But if you think at how MVC pattern works, you should consider a view controller as the glue logic between the view and the model. The view is not persistent, that's why it is legitimate for ARC to get rid of the owning view controller when the view is no more needed. Instead what you should persist while your app is working is the model data only: the model data will be shared between the involved view controllers, the view controllers will be recreated each time and the corresponding views will be updated based on the model data. The only reason why the view controller should be kept alive is when its alloc-init-loadView takes too much (e.g.: the view is OpenGL backed) but in such case I would suggest you to keep a strong reference to it in the AppDelegate and ask it to refresh the content when the model data is replaced.
So basically what you should do is:
- select the table
- extract the model data associated to the table, including all information relevant for the view controller
- push the view controller; save all view modifications to the model
- when the view controller is popped, the model data will be returned only
- next time, when you push the view controller again, you will restore the model and re-init the view controller.
This approach is not complicated and gives you the possibility to structure the app in a clean way. Tomorrow you can change your view controller structure (that its view and the logic) without any impact in the communication with the other view controllers as this managed by the model passing only.
There are a couple of solutions to this, just like you suggested.
The array solution is highly inefficient because of memory issues.
The second solution you proposed is a lot more elegant. Just write your own init method in that view controller and init the view controller with data from a plist file
If I'm reading the question correctly, you've got a tableView and a detailView that are driven by the same model data. When changes to the model data are made in the detail view, you want those changes to persist.
If you update the model based on the state of the controls when the detail view is popped, then those changes will persist and the changes will be visible the next time you drill back down into the detail view.
You don't mention what form the table data takes, but let's assume it's an NSArray of NSMutableDictionaries. When you tap the row, the didSelectRowAtIndexPath: method will need to hand the dictionary from that array index to the detail view controller through a property on the detail controller. The detail view controller will update the dictionary values in the method that dismisses it.
The way to think of this is using the model-view-controller pattern. The table and detail view data is stored in the model; the views present the data; and the controllers are responsible for updating the model and navigating between views.

UIPageViewController optimization and possible solution

I am using a UIPageViewController in my app to display number of images (1024x768 size). Is it ok to make array of UIViewControllers each with his picture and in set appropriate for each page? Maybe if you get like 50 pictures it will crash? At the moment I store images in Documents folder so I can remove images from view controllers that are not on screen
This wouldn't be very efficient, you'd be much better off doing the same thing with UIImageViews. Even then you have to be careful. Probably the best way to handle this would be to using image views and deallocating them when they go more than one image width out of the screens bounds. Then of course reallocing when the image in question is the next image in line to be displayed in either direction.
EDIT: It looks like you can use the following UIPageViewController Datasource methods to set which view controller do basically have queued and waiting to the right/left. Using these you should be able to only allocate 3 view controllers at a time.
– pageViewController:viewControllerBeforeViewController:
– pageViewController:viewControllerAfterViewController:
Then you can use this to set the initial controller:
Set the initial view controller using UIPageViewController's
-setViewControllers:direction:animated:completion:
The sentence below is quoted from Apple's documentation and is leading me to believe that the controller may be able to only load the necessary view controllers into memory on its own.
View controllers are either provided one at a time (or two at a time,
depending upon the spine position and double-sided state) via the
setViewControllers:direction:animated:completion: method, or provided
as-needed by the data source. Gesture-based navigation is enabled only
when a data source is provided.

Loading UIViews in the background on application launch

I have a simple iPad application with 5 views. On the first view, the user is asked to make some selections and set some options. From this information, the other 4 views are programatically changed after an NSNotification message is sent to them. (i.e controls are added, updated).
My problem is that when the application is first loaded, the user sees View1, but View2, View3, View4 and View5 have never been opened yet, so any changes I make programatically to those views are not done and when the user navigates to them (via the tab bar) for the first time, no changes are shown.
[EDIT: I should point out that the code for making the changes to each view is contained within the ViewController itself, and is executed when the view observes the incoming NSNotification. When the view is not loaded, it understandably never received the incoming NSNotification.]
Only after the user looks at any of those screens at least once and then goes back to View1 and makes changes, are the other Views updated properly.
I thought I could get around this issue by actively loading Views 2,3,4 and 5 into memory on application start, so that they are ready to begin receiving notifications right away.
Is there an easy way to do this in iOS 5?
Why do the view changes straight away?
I would store an indicator of the changes needed when the users answers the questions on the first view and then apply the changes on -viewDidLoad of each view that needs to be changed.
Instead of trying to load the views into memory, I'd suggest you initialize these views with the options that the user set on the first view. What I usually do in such situations, when I have a global parameters that are used in many places, I create a utility class to keep the data, make it a singleton, then access the shared instance in the viewDidLoad in the views that use the data during initialization.