iOS6 app state save and restoration - iphone

My app's minimum support iOS version is iOS5. And I didn't do any state save and restoration.
It works well on my self iphone4, but some users complain the app is reset when they pick up a phone call or change to other app and back.
So, I take state restoration more serious, and I want to add it into my app.
However, I have image album function, so I call ALAssetLibrary.
I need to create the exact the same thumbnail view as it was.
I have some background Operations in operationQueue, so I need to know their state and add the unfinished background operations. It's a little complicated.
Here're my questions.
1. I didn't find useful sample code, project. (session208 in WWDC2012, but they didn't release code in WWDC sample code release), Do you know any?
2. what's the best way to do it ? follow iOS6 or make it by myself?
what's the difference.
3. For ALAssetlibrary, image thumbnail viewing, how could I achieve state save and restoration?

Definitely use Apple's APIs, don't reinvent the wheel. The WWDC 2012 session about this used the WWDC 2012 app as the example to show off the feature, there was never any demo project to share to developers. However they have since (recently) released a demo to demonstrate it, you can find it here: http://developer.apple.com/library/ios/#samplecode/StateRestore/Introduction/Intro.html
It sounds like your state is complex, and I'm not sure you really want to be restoring those background operations. You probably will find it better to restore the user to a more stable part of your app.
For your ALAssetlibrary question, you would save an ID to the current image in your encodeRestorableStateWithCoder: implementation of your view controller, make sure you read up on the documentation, you'll need to conform to a protocol, set a restoration class if you're in code or using xibs (not using storyboard)... you would save the ID doing something like this:
NSString * const ImageReferenceIDKey = #"ImageReferenceID";
- (void)encodeRestorableStateWithCoder:(NSCoder *)coder
{
NSString *objectID = nil; // get some ID that can relocate your image
[coder encodeObject:objectID forKey:ImageReferenceIDKey];
[super encodeRestorableStateWithCoder:coder];
}
- (void)decodeRestorableStateWithCoder:(NSCoder *)coder
{
[super decodeRestorableStateWithCoder:coder];
NSString *objectID = [coder objectForKey:ImageReferenceIDKey];
// get into the ALAssetlibrary and use the objectID to restore which image you had.
}
Notice I call super last in the encode method, but first in the decode method.
You should be very careful about the user having changed the privacy of your access to their photos, don't crash on them, if you try to restore a photo make sure you still have permissions to do so, or you might crash.

Related

Where to use and initialize UIManagedDocument

I am new to IOS and I am following CS193p Stanford's lecture to learn about Core Data and in the demo the Professor used a category with somehow similar to what actually to if we check core data application checkbox while creating application and it puts the core data stuff in appDelegate. That's what professor did in demo he created managedObjectContext in AppDelegate and used a Notification to Pass the Context to controller. Now for Assignment he asked to use UIManagedDocument but I am confused about where to put it. Should I declare it in the View Controller or in AppDelegate and pass context using Notification Centre. So I just want to know which one is better for UIManagedDocument. S
Best way I found is create a new project (just as a sample), check 'Use Core Data' when asked, and look inside the AppDelegate. Use that to see how it's done and possibly, copy the appropriate parts (some adjustments will be needed of course). But mostly, use it to learn how Apple recommends it to be used.
Create a custom class with a shared instance that has managedObjectContext property.
In your application didFinishLaunchingWithOptions in AppDelegate, create your sharedInstance and pass it the 'managedObjectContext`.
MyDataManager *dataManager = [MyDataManager sharedInstance];
dataManager.managedObjectContext = self.managedObjectContext;
Notice also that if you terminate the app by hitting the 'Stop' in Xcode, the data won't be saved (since it's done, as it should, when the AppDelegate is about to close the app properly).
Make sure to also have [self saveContext]; in applicationDidEnterBackground, it supposed to be inside applicationWillTerminate as well. It is a good practice to write the database to memory only when needed (and not at every change). In the AppDelegate, it also ask if the data has changed before committing.
Of course, you can also save manually if you have the managedObjectContext instance.
If you made changes to the database you might have to delete the app from the simulator before running again (otherwise app will crash since the older DB won't match the new one).
Edit: I can't remember where I read it, but the professor does not use CoreData as a database pre-se, only to manage data (images etc.).
You can initialize your UIManagedDocument where ever you want to initiate access to your database. When I did the assignment (last year), I put in the AppDelegate. In glancing back now I see there are two ViewControllers in a UITabBarController and they both need the context. So I used the NSNotification mechanism like Paul did in lecture.
The reasons he gives for using UIManagedDocument over "User Core Data" checkbox (when creating the project) was:
It was simpler for him to explain (UIManagedDocument takes care of lots of complexities)
UIManagedDocument puts you on a fast track to using iCloud
I was just reviewing this as well. If you want to hear from Paul, he talks about it in Lecture 12 (Fall 2013-14) at 14 minutes and 25 seconds (UIManagedContext) and at 14:50 he starts talking about the two ways to get the UIManagedContext -- being UIManagedDocument or the "Use Core Data" checkbox.
Here us a link to the course on iTunes: https://itunes.apple.com/us/course/developing-ios-7-apps-for/id733644550

How can we load image like apple is doing in his app store?

Hello guys how apple is loading table view cell image that
doesn't affect scrolling of
table view.How fast it is working. I want to make a table view like that which loads
image directly from URL and it doesn't effect scrolling of UITableview
Lazy Loading is the exact term, which you are referring to. (Apple Technologies uses LazyLoading wherever it can be applicable, whether it's iOS or Mac OS X -- and it gives best user experience, too, as user is not forced to wait)
Apple provides sample source code, which performs similar functionality -- Here is the sample code
Don't get confused with the ParseOperation Class. It is just the separate implementation of the XML Parsing functionality. Though, It is a better approach, You can write it in your own working class (from which you are invoking the connection request.)
Additionally -- Apple has updated this code to use Blocks (GCD).
Hope that will help you...
You dont need to look too far - Apple has this code in the Open - LazyTables.
If you want to know the magic sauce is the launching of bg thread to download images, after the downloads finish in background, then it updates the UI to show the image.

NSUndoManager not keeping the stack with redo/undo for an iPhone app for UnDo/Redo drawings

I am building an iPhone app with Objective C. In my app, I am drawing the strokes on image and want to implement the undo and redo functionalities.
I have used NSUndoManager for this. With this I am able to undo my drawing at one level down, but my requirement is to undo the drawing at its lowest possible level (or at least minimum 10 level down). I had already set the setLevelsOfUndo to 10 but it does not work.
I'm using the following code:
- (void)UnDoImage1:(UIImage*)image
{
if (capturedImage.image != image)
{
[self.managedObjectContext.undoManager undo];
[[self.managedObjectContext.undoManager prepareWithInvocationTarget:self] UnDoImage1:capturedImage.image];
[capturedImage release];
capturedImage.image = [image retain];
}
}
Please let me know where I am incorrect. I have already Googled for this for a long time but did not find the exact cause of failure of the functionality.
I do not believe that you can use prepareWithInvocationTarget: with an object as a Parameter. Its not going to Keep a copy of capturedImage.image around for the Undo/Redo Stack. So Since you are releasing it and setting it to the new image, the reference to the original is lost and you will just be calling UnDoImage1: with the current capturedImage.image
If thats the only thing you are looking to undo/redo, then I would look at registerUndoWithTarget:selector:object: it will hold onto a reference of capturedImage.image.
Scott<-

CoreData: Loading in an Initial Data Set from XML

I have a plain XCode CoreData enabled iPhone/iPad navigation application. In this I have modifed the data it initially defines to represent some categories in the table view with associated images. For example by modifying a Event to Category elsewhere, changing the .xcdatamodel file and altering this call in RootController.m:
- (void)configureCell:(DeliciousCategoryCell *)cell atIndexPath:(NSIndexPath *)indexPath {
NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.categoryLabel.text = [[managedObject valueForKey:#"name"] description];
NSString *filePath = [[NSBundle mainBundle] pathForResource:cell.categoryLabel.text ofType:#"tiff"];
cell.categoryImage.image = [[UIImage alloc] initWithContentsOfFile:filePath];
}
If I preload the data from an xml file by putting code in:
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
The data gets loaded in fine but the app subsequentially crashes with EXC_BAD_ACCESS. If I take that code out the app loads, my data is present and my categories display fine with the associated local images. I've tried moving the code in question elsewhere such as:
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
and checking to make sure the data is empty however it still crashes yet loads the data. I can't seem to track down the cause of the EXC_BAD_ACCESS via the debugger as the stack trace is void of useful information. What I would like to know is an answer to the following as I cannot find it in apples documentation:
1) When such a Core Data based application first starts where should the calls to load in an initial data set go? I would ideally do this via the web but am currently just opening a local xml file for testing.
2) Once core data has been loaded I would like to enable the user to update the core data information by merging. Where should such code reside?
I don't have a problem with the logic just the location of the necessary code afaict. If anyone would like a listing of what I'm doing I'll provide but it is rather verbose. The code as implemented is taken straight from two apple tutorials. The latter detailing how to load in data without undue fetches/selects on the data base, however said tutorial doesn't say anything about where it should reside.
I think you're to fixated on the location of the code being the problem.
Objective-C, Core Data and the general Apple API are all very encapsulated and modular. You can plug in needed functionality almost anywhere and activate it or not at almost any time. The only critical locations/times are app delegate methods related to the starting and stopping of the app. Everything else is flexible. In your case, you only need to load data before you use it and you only need to merge data after it has changed. The possible configurations of when and where are functionally infinite. Different apps do all this at different places and times.
You should be looking at a more prosaic cause of the EXC_BAD_ACCESS. Under normal conditions, the debugger will show you the line where the crash happens. If it shows nothing, then the debugger itself most likely crashed. More likely, you just missed the display of the crashed line because the line in your code that triggered it is scrolled off the screen of the stack trace. (A lot of beginners make that mistake.)
When you see EXC_BAD_ACCESS, you have over-released an object. Here is some troubleshooting advice.

iPhone: Custom UIImagePickerController?

It seems like the built in UIImagePickerController cannot accept sources other than its device camera Roll.
I would like to get the functionality of picking and enlarging pictures within my own app. Also I would like to allow the user to select the pictures and save it into their camera roll (so they can later use it as wall paper)
1) what is the recommended way of building a custom UIImagePickerController that supports what I need ? Is there another built in controller I am missing?
3) Is there a way to take a UIImage and save it to the desktop background of the device directly? Or is it a two step (first save to camera roll), then have the user load the picture from there to save as wallpaper
Thanks in advance!!
At this point, it seems that the only way to build a custom UIImagePickerController functionality is to subclass, and then muck with the view hierarchy directly. This allows you to move, hide, and replace UI elements and access the non-public classes that control the operation of the camera, but as you probably gather, this technique is both unsupported (in that it may, and probably will, break with future updates) and not recommended (in that it may, and probably will, get your app rejected from the App Store if detected).
As far as your second point (somehow numbered 3), John is right: there is no call in the public SDK to accomplish this. You could probably hack something together if you're clever, but remember the warnings in my first paragraph...
Regarding #3) there is no public call in the SDK to save an UIImage to the desktop.
I don't know about the rest of your questions though.
Just today I started a open source UIImagePickerController clone, it is not perfect but it works quite ok. Feel free to fork http://github.com/jeena/JPImagePickerController