how do i remove coredata from iphone - iphone

You know how you can Reset the coredata store on an iPhone simulator when you've changed your entity structure?
Do I need to perform a similar process when I've created a new version of my core data store that is different from what I last ran on my iPhone? If so, how, please?
Thanks

Just for convenience, until you code a way to remove the persistent store through your app, you can just delete the app off the phone. (Hold your finger on the home screen until icons get wiggly, then click the x on your app.) Then with your phone connected to your Mac, choose Product > Run in XCode and it will reinstall your app on the phone, but with empty data directories.
For deployment, of course, you need to come up with a way to do it without deleting the app, if you will ever change your data model after deployment (assume you will). Data migration is the best option, but if all else fails delete the persistent store file. It would be preferable to prompt for the user's approval before doing that. If they have important data they can decline and maybe get the old version of your app back to view the data and migrate it by hand, or they can wait until you release version 2.0.1 that fixes your data migration bug.

Here is the routine I use to reset my App content. It erases the store and any other file stored.
- (void) resetContent
{
NSFileManager *localFileManager = [[NSFileManager alloc] init];
NSString * rootDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSURL *rootURL = [NSURL fileURLWithPath:rootDir isDirectory:YES];
NSArray *content = [localFileManager contentsOfDirectoryAtURL:rootURL includingPropertiesForKeys:nil options:NSDirectoryEnumerationSkipsSubdirectoryDescendants error:NULL];
for (NSURL *itemURL in content) {
[localFileManager removeItemAtURL:itemURL error:NULL];
}
[localFileManager release];
}
If you only want to erase the store, since you know its file name, you can refrain from enumerating the document directory content:
- (void) resetContent
{
NSFileManager *localFileManager = [[NSFileManager alloc] init];
NSString * rootDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSURL *rootURL = [NSURL fileURLWithPath:rootDir isDirectory:YES];
NSURL *storeURL = [rootURL URLByAppendingPathComponent:#"myStore.sqlite"];
[localFileManager removeItemAtURL:storeURL error:NULL];
[localFileManager release];
}
But please note that in many cases, its better to migrate your store when you change your model, rather than to delete it.

locate your app in /Users/username/Library/Application Support/iPhone Simulator/4.3.2 (iOS Version may be different) and delete the .sqlite file

You can look at the path that is being sent to the persistentStoreCoordinator on setup, and remove that file. Usually the approach I have taken is that I set up the store to auto migrate, and if that fails I delete the store and attempt one more time to create the persistentStoreCoordinator which will use the now empty path.
Don't forget you may need to repopulate anything stored in the old database.

Related

Sqlite Prepare Failed: no such table<tablename>

I have created sqlite database.
I add this sqlite file in my application but when I run the app in the simulator and check the sqlite file's path in document directory and I open the sqlite file on document directory's path at that time the table which I have created does not appear.
In local copy I can see the table also in my project folder I can see the table but on the path of simulator I am not able to see the table
so in my console it shows me the error:
Sqlite Prepare failed: no such table
My response below assumes that your database is properly formatted and functional. You could test easily via the command line. In my own apps, all tab bar controllers apps, I place the db access code in the app delegate. The two methods in the app delegate are as follows:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions (NSDictionary *)launchOptions {
[self createEditableCopyOfDatabaseIfNeeded];
[self.window setRootViewController:rootController];
[window makeKeyAndVisible];
return YES;
}
Also:
- (void)createEditableCopyOfDatabaseIfNeeded {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *dbPath =[documentsDir stringByAppendingPathComponent:#"dbName.sqlite"];
BOOL success = [fileManager fileExistsAtPath:dbPath];
if(!success)
{
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"dbName.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if (!success)
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
If you've tried everything and are still getting this error.. even if you've tried resetting the iOS Simulator. Try installing the app in the iOS simulator and then manually uninstalling it (select Home and long select the app icon and delete it) and then reset the simulator.
I don't know why but I tried everything else, spent hours banging my head against the wall. Then this worked.
You can put the sqlite file in your xcode project and locate it like so:
NSString *pathToSQL = [[NSBundle mainBundle]
pathForResource:#"sqlname" ofType:#"sql"];
Make sure the "Target Membership" of the sql file is set properly, so that the project "sees" it:
1) click on the sql file in the left-pane of Xcode
2) open/show the File Inspector (right pane)
3) Under "Target Membership", make sure the "check" is "checked"
That's it. Hope, this is what you're looking for. Any concern get back to me.

programmatically clearing secondary cache on iPhone

I have created an application , where i ll be downloading the images from server and storing it locally on the iPhone's file system. Its happening fine. Now the problem is , i want to clear the locally cached images on iPhone when ever i quit my application.
How do i delete those cached images on iPhone. it's using Secondary memory on iPhone, how do i access it programmatically ?
Thank You in advance.
Suse.
Clean them up in your applicationWillTerminate method.
- (void)applicationWillTerminate:(UIApplication *)application
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *imagesFiles = [fileManager contentsOfDirectoryAtPath:saveDirectory error:&error];
for (NSString *file in imagesFiles) {
error = nil;
[fileManager removeItemAtPath:[saveDirectory stringByAppendingPathComponent:file] error:&error];
/* do error handling here */
}
}
My answer would be as per Kirky Todds, but don't use applicationWillTerminate -- it's not a good strategy on iOS4+ with multitasking, because this method often won't get called -- an app will be background, and then can be dumped from memory if other apps are run (or the phone is turned off/restarted), without applicationWillTerminate getting called. (OR it will be foregrounded again. Either way, your cache doesn't get cleared.)
Instead, consider either clearing at startup (applicationDidFinishLaunching), or in applicationWillEnterForeground. The latter will tend to get called more frequently, because the former is only called on an actual proper app lauch (and not on a resume from being backgrounded).
For more info on backgrounding and the events generated, see:
http://www.cocoanetics.com/2010/07/understanding-ios-4-backgrounding-and-delegate-messaging/

How to download files to iPhone's filesystem?

i would like to download a bunch of pdf's from a website to the iPhone filesystem in my app.
Because i don't want to download the files everytime i start the app.
In the documentation i found a function called "dataWithContentsOfURL" but the sample code didn't help me. Is this the right way, or is there an easier solution?
Can someone give me a tip or two ? ;-)
greets max
I recommend using ASIHTTPRequest, it's well written, documented and easy to use, heres a quick example from one of my applications download class that downloads a JSON file using ASIHTTPRequest:
-(void)downloadJSONData:(NSString *)path destination:(NSString *)destination secure:(BOOL)secure {
if (![self queue]) {
[self setQueue:[[[NSOperationQueue alloc] init] autorelease]];
}
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtPath:destination error:NULL];
NSURL *url = [NSURL URLWithString:path];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
if(secure){
[request addRequestHeader:#"Authorization" value:[NSString stringWithFormat:#"Basic %#",[ASIHTTPRequest base64forData:[[NSString stringWithFormat:#"%#:%#",self.username,self.password] dataUsingEncoding:NSUTF8StringEncoding]]]];
}
[request setDelegate:self];
[request setDidFinishSelector:#selector(requestDone:)];
[request setDidFailSelector:#selector(requestWentWrong:)];
[request setDownloadDestinationPath:destination];
[[self queue] addOperation:request]; //queue is an NSOperationQueue
}
I would take a look at the how-to-use page as it contains everything you need to know.
You're on the right track
-(void)downloadURL:(NSURL *)theUrl toLocalFileURL:(NSURL *)localURL
{
NSData *dlData = [NSData dataWithContentsOfURL:theURL];
[dlData writeToURL:localURL atomically:YES];
}
So just research how NSURLs are created for local and remote objects and you're all set.
Yes you could download files only as you need(Lazy load).
When ever you want access the files. Check in the documents directory for the file. In the second answer it is being specified. Append file name with the douments path. Check If there is a readable file using NSFileManager's isReadableFileAtPath:instance method. if it returns false then initiate downloading the pdf from the website.
Please do care to create a class which downloads file asynchronously. You could use NSURLconnection to initiate the request and its delegate methods to process its content After downloading content write it to documents folder.
If you could create a class for asynchronous download , you could initiate parallel downloads and use maximum use of the bandwidth.
By making asynchronous downloads you could make sure that you application is responsive even while files are getting downloaded.
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/Reference/Reference.html
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html
Regards ,
Jackson Sunny Rodrigues
Do not use dataWithContentsOfURL: unless you're executing it somewhere other than the main thread. It is a blocking API as well as one that accesses the network. That is a recipe for bad user experience.
Think about this: You use a blocking API to access the network, but the network is down or really slow. The main thread is now blocked, so your user interface is not responding to user interaction. The user gets frustrated and tries to cancel the download using the handy button you put on the UI, but "OH NO!" it doesn't work because the UI is blocked.
Do not use blocking APIs on the main thread.
You should look at the documentation for NSURLConnection and it's asynchronous loading methods for downloading data.
You should use
NSData* pdf_data = [NSData dataWithContentsOfFile: #"file_path"];
where file_path is the path where you've saved your file (it is usually Documents or Library directories).
To save data there use:
[pdf_data writeToFile: #"file_path" atomically: YES];
To get path to your documents directory you can use:
- (NSString *)applicationDocumentsDirectory {
NSArray *paths =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}

Finding list of installed apps on iphone

Is it possible to programatically find out name of all apps installed on my iOS device ?
Is there any API available for same ?
Thanks for the help
No, on iOS applications has no access to information of/about other applications due to sandboxed environment.
Yes it is possible to get list of all installed app
-(void) allInstalledApp
{
NSDictionary *cacheDict;
NSDictionary *user;
static NSString *const cacheFileName = #"com.apple.mobile.installation.plist";
NSString *relativeCachePath = [[#"Library" stringByAppendingPathComponent: #"Caches"] stringByAppendingPathComponent: cacheFileName];
NSString *path = [[NSHomeDirectory() stringByAppendingPathComponent: #"../.."] stringByAppendingPathComponent: relativeCachePath];
cacheDict = [NSDictionary dictionaryWithContentsOfFile: path];
user = [cacheDict objectForKey: #"User"];
NSDictionary *systemApp=[cacheDict objectForKey:#"System"];
}
systemApp Dictionary contains the list of all system related app
and user Dictionary contains other app information.
Not from the device. However, from the desktop you could peek into the iTunes library.
There are ways to do this without a jailbroken device and not get your app rejected.
1. get a list of currently running processes see this SO answer. You will need to translate from process name to app name.
2. Check to see if any apps have registered a unique URL scheme with UIApplicationDelegate canOpenURL. There are a few sites cataloging known url schemes, this is the best one.
If an app is not currently running and does not register a custom url scheme then it will not be detected by these methods. I am interested in hearing a method that will be allowed in the app store that works better than this.
try this, it will work even with non-jailbroken devices:
#include <objc/runtime.h>
Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
SEL selector=NSSelectorFromString(#"defaultWorkspace");
NSObject* workspace = [LSApplicationWorkspace_class performSelector:selector];
SEL selectorALL = NSSelectorFromString(#"allApplications");
NSLog(#"apps: %#", [workspace performSelector:selectorALL]);//will give you all **Bundle IDS** of user's all installed apps
You can do it by checking whether an application is installed or not by using canOpenURL method or by checking the background processes and matching them with the name of the app you are interested in.
You can use runtime objective c to get the list of all installed apps. It will give you an array of LSApplicationProxy objects.
Following is a code snippet that prints Name of all applications installed in your device.
Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
NSObject* workspace = [LSApplicationWorkspace_class performSelector:NSSelectorFromString(#"defaultWorkspace")];
NSMutableArray *array = [workspace performSelector:NSSelectorFromString(#"allApplications")];
NSMutableArray *mutableArray = [[NSMutableArray alloc] init];
for (id lsApplicationProxy in array) {
if(nil != [lsApplicationProxy performSelector:NSSelectorFromString(#"itemName")]){
[mutableArray addObject:[lsApplicationProxy performSelector:NSSelectorFromString(#"itemName")]];
}
}
NSLog(#"********* Applications List ************* : \n %#",mutableArray);
Don't forget to include <objc/runtime.h> .

Where should I store an image selected on the iPhone?

I want to take a picture or select an existing picture from the users existing photos. What is the best way to do this?
Specifically I am concerned where I should to store the image. The storage location should be private to the application. I need to be able to reuse the image as a background every time the application opens. Thanks!
You should use the UIImagePickerController to retrieve images from the library or the camera. You can persist the picture in the App's Documents folder. This folder is private to your app and is writeable.
You can get the path to the documents folder like so
NSArray *sysPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *docDirectory = [sysPaths objectAtIndex:0];
And to save a file there.
NSString *filePath = [NSString stringWithFormat:#"%#whatever.jpg",docDirectory];
NSData *toSave = UIImageJPEGRepresentation(image,1.0); //image is a UIImage
[toSave writeToFile:filePath atomically:YES];