0
votes

I am starting to learn Objective-C and to help me doing so, I am using "Head First iPhone Development". Now I am learning about SQLite databases and to get these to work I am told that the SQLite file needs to be in the Documents folder of the application and therefore I have to move the file.

I am using the example from the book but I can't seem to get it to work. Everytime I compile it my app crashes. I have the following warning: "Incompatible Objective-C types initializing 'struct NSURL *', expected 'struct NSString *'

Does anyone have a tip how to fix this?

EDIT:

The problem seems to be in these two lines with applicationDocumentsDirectory returning an NSURL but I tell it to return an NSString. I could tell it to return an NSURL but that gives me a problem on the next line where I use stringByAppendingPathComponent. Is there a way to fix this?

    NSString *documentsDirectory = [self applicationDocumentsDirectory];
    NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"iBountyHunter.sqlite"];

This is what the Debugger Console outputs when the app crashes:

2011-02-04 07:33:42.126 iBountyHunter[591:207] -[NSURL stringByAppendingPathComponent:]: unrecognized selector sent to instance 0x6043f80
2011-02-04 07:33:42.128 iBountyHunter[591:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSURL stringByAppendingPathComponent:]: unrecognized selector sent to instance 0x6043f80'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x00f87be9 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x010dc5c2 objc_exception_throw + 47
    2   CoreFoundation                      0x00f896fb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
    3   CoreFoundation                      0x00ef9366 ___forwarding___ + 966
    4   CoreFoundation                      0x00ef8f22 _CF_forwarding_prep_0 + 50
    5   iBountyHunter                       0x00001d8e -[iBountyHunterAppDelegate createEditableCopyOfDatabaseIfNeeded] + 107
    6   iBountyHunter                       0x00001f24 -[iBountyHunterAppDelegate application:didFinishLaunchingWithOptions:] + 37
    7   UIKit                               0x002ba1fa -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1163
    8   UIKit                               0x002bc55e -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 439
    9   UIKit                               0x002c6db2 -[UIApplication handleEvent:withNewEvent:] + 1533
    10  UIKit                               0x002bf202 -[UIApplication sendEvent:] + 71
    11  UIKit                               0x002c4732 _UIApplicationHandleEvent + 7576
    12  GraphicsServices                    0x018bda36 PurpleEventCallback + 1550
    13  CoreFoundation                      0x00f69064 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
    14  CoreFoundation                      0x00ec96f7 __CFRunLoopDoSource1 + 215
    15  CoreFoundation                      0x00ec6983 __CFRunLoopRun + 979
    16  CoreFoundation                      0x00ec6240 CFRunLoopRunSpecific + 208
    17  CoreFoundation                      0x00ec6161 CFRunLoopRunInMode + 97
    18  UIKit                               0x002bbfa8 -[UIApplication _run] + 636
    19  UIKit                               0x002c842e UIApplicationMain + 1160
    20  iBountyHunter                       0x00001cf8 main + 102
    21  iBountyHunter                       0x00001c89 start + 53
)
terminate called after throwing an instance of 'NSException'
4

4 Answers

1
votes

I am using the example from the book but I can't seem to get it to work. Everytime I compile it my app crashes. I have the following warning: "Incompatible Objective-C types initializing 'struct NSURL *', expected 'struct NSString *'

Fix the warning; you are assigning an NSURL instance to something that expects an NSString instance.

Or post the warning & line of code that causes it.

If your app is crashing, post the crash.


The problem seems to be in these two lines with applicationDocumentsDirectory returning an NSURL but I tell it to return an NSString. I could tell it to return an NSURL but that gives me a problem on the next line where I use stringByAppendingPathComponent. Is there a way to fix this?

You can't tell a method that returns an NSURL to return an NSString instead. Neither type casting the return value nor an assignment like the following will work:

NSString *documentsDirectory = [self applicationDocumentsDirectory];

The compiler is warning on that line because it is broken; you can't treat an NSURL like an NSString.

Something like the following should work:

NSString *documentsDirectory = [[self applicationDocumentsDirectory] path];
1
votes

If the application still doen't work in your simulator, do remember to delete the application from you simulator, then build and run the application again.

You delete the application from the simulator in the same way you do it with a real device.

0
votes

This will do the trick.

// Check the existence of database 
        NSFileManager *mngr = [[NSFileManager alloc] init];

        // If the database doesn't exist in our Document folder we copy it to Documents (this will be executed only the first time we launch the app).
        if (![mngr fileExistsAtPath:[NSString stringWithFormat:@"%@/Documents/db.sqlite", NSHomeDirectory()]]){
            NSString *filePath = [[NSBundle mainBundle] pathForResource:@"db.sqlite" ofType:nil];
            [mngr copyItemAtPath:filePath toPath:[NSString stringWithFormat:@"%@/Documents/db.sqlite", NSHomeDirectory()] error:NULL];
        }
        [mngr release];

here's another version of the applicationDocumentsDirectory method:

+ (NSString*)applicationDocumentsDirectory {

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    return documentsDirectory;
}
0
votes

I have the following warning: "Incompatible Objective-C types initializing 'struct NSURL *', expected 'struct NSString *'

The problem is that you are calling the apple supplied applicationDocumentsDirectory method, which returns an NSURL.