CoreData - Problem accessing database on another machine - macos

I've got a problem with my CoreData, but I'm sure I'm doing something wrong conceptually.
I'm trying to access a CoreData sql file on one machine in my network from another machine. I'm trying to do this from a cluster-like application. Each machine has the same copy of the software and needs to point to the database on this one machine.
My model and context load fine for the machine that the database is on. The other machine, gives me error 13400 NSPersistentStoreInvalidTypeError
Here's the bit of code:
NSError *error = nil;
NSURL *mdlurl = [NSURL fileURLWithPath: [[NSBundle mainBundle] pathForResource:#"OsiriXDB_DataModel" ofType:#"mom"]];
_model = [[NSManagedObjectModel alloc] initWithContentsOfURL: url];
NSURL *dburl = [NSURL URLWithString:[NSString stringWithUTF8String:_DBPath.c_str()]];
// The dburl has a format like: file://192.168.0.2/Users/slate/Documents/OsiriX%20Data/Database.sql which addresses the machine the data sits on.
_storeCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: _model];
_context = [[NSManagedObjectContext alloc] init];
[_context setPersistentStoreCoordinator: _storeCoordinator];
if (![_storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:dburl options:nil error:&error]) {
NSLog(#"Error loading store: %#", error); // Error Shows up Here
NSLog(#"MOM: %#",_model); // Model looks OK. Lots of print outs, with the correct names and stuff. (so technical).
}
I confess to not knowing a ton about CoreData. Is it because it's on a different machine? I read this online but I don't think that's my issue. If it is, I have no idea how to fix it because I can't find any .xml files in my ~/Library/Application\ Support/ directory relating to either MyApp or OsiriX which is the program that created the database.
Am I doing the wrong thing to load CoreData across a network?
If not, what should I be doing?
Thanks,

The error indicates that persistent store coordinator thinks that the file is not the proper format for a NSSQLiteStoreType. That suggest that the file was found. If it couldn't locate the file or access the directory you would get another error.
I'm not sure what you problem is specifically but I can tell you in general that Core Data is not intended as a concurrent database. It's not even really a database at all. It's actually a runtime object graph management system intended to manage an app's model layer with persistence tacked on the side as an option. There are no Core Data options for controlling multiple instances of an app simultaneously accessing the same store. You might be able to do so by setting the store as readonly but I don't know for sure.
It sounds like you need a real database running on your server.

Related

iOS8: Sharing common files between apps

Two iOS: AppA and AppB
Both Apps are created by me and I would like to share one single file between both of the apps.
i.e. AppA launches on deviceA and the User saves data on fileA. Later the User launches AppB on the same (deviceA) and also saves data on fileA. Both apps are saving data on the same file.
I'm aware that I can use NSUserDefaults and share Keychain between apps, but that's not what I'm looking for.
I read up on document extensions provider and app groups, but I'm confused if I can use these for this scenario? Or is there any other way to accomplish this?
You can do it using Application Group Container Directory:
NSFileManager *fm = [NSFileManager defaultManager];
NSString *appGroupName = #"Z123456789.com.example.app-group"; /* For example */
NSURL *groupContainerURL = [fm containerURLForSecurityApplicationGroupIdentifier:appGroupName];
NSError* theError = nil;
if (![fm createDirectoryAtURL: groupContainerURL withIntermediateDirectories:YES attributes:nil error:&theError]) {
// Handle the error.
}
You could just upload the files after saving to your server and make both apps request updates for the file whenever they are launched.
Hope that helps :)

dismissGrantingAccessToURL of UIDocumentPickerExtensionViewController is not working

I am working on document provider extension for import mode.
URL of file is sitting inside the shared container shared by both extension & container app.
I got assertion failure saying that it should sit inside shared container/File Provider Storage directory.
So I copied file from original directory to File Provider Storage directory.
I have a file in original location & I got a file in new copied location also. I checked for data length of the file also, Its proper ,
But when I call [self dismissGrantingAccessToURL:toUrl];
Its not dismissing UIDocumentPickerExtensionViewController,
I am not facing any exceptions , but it wont dismiss and initiate the transfer, So user can still access the extension.
Below is my code, If anyone came across the same thing please leave your reply.
- (void)userChoosesEntityOfUrl:(NSURL *)url
{
NSURL *toUrl = [self.documentStorageURL URLByAppendingPathComponent:[url lastPathComponent]];
if ([[NSFileManager defaultManager] fileExistsAtPath:[toUrl path]]) {
[[NSFileManager defaultManager] removeItemAtPath:[toUrl path] error:nil];
}
if ([[NSFileManager defaultManager] copyItemAtURL:url toURL:toUrl error:nil]) {
NSLog(#"%#", [toUrl path]);
}
if (![[NSFileManager defaultManager] fileExistsAtPath:[toUrl path]]) {
NSLog(#"File Doesn't exists at this path");
return;
}
NSLog(#"Data Length %i",[[NSData dataWithContentsOfFile:[toUrl path]] length]);
[self dismissGrantingAccessToURL:toUrl];
}
When debugging your implementation of NSFileProviderExtension, you usually end up stopping/killing it using Xcode. After this, iOS often has problems restarting your file extension. This results in your document picker not being dismissed after calling dismissGrantingAccessToURL:. This bug also affects your subclass of UIDocumentPickerExtensionViewController which sometimes won't start (you only see the navigation bar of the document picker but not the content).
The workaround is to reboot your device.
This will occur if you have a backing File Provider extension that has not been fully implemented. Remove the File Provider target from your embedded extension phase, set your document extension only support import/export modes in the Info.plist, and do a product -> Clean before building and running your extension.

how to make NSURL point to local dir?

reading Adium code today, found an interesting usage of NSURL:
NSURL *baseURL = [NSURL URLWithString:[NSString stringWithFormat:#"adium://%#/adium", [messageStyle.bundle bundleIdentifier]]];
[[webView mainFrame] loadHTMLString:[messageStyle baseTemplateForChat:chat] baseURL:baseURL];
I tried to log the url and got this adium://im.adium.Smooth Operator.style/adium, Then I created a blank project to see how to create such an NSURL but failed. When I sending loadHTMLString message to a webview's frame in my project, if the baseURL is nil, everything is fine, if not, I got a blank page in the view.
here is my code, the project name is webkit
NSURL *baseURL = [NSURL URLWithString:#"webkit://resource"];
//if baseURL is nil or [[NSBundle mainBundle] bundleURL], everything is fine
[[webView mainFrame] loadHTMLString:#"<html><head></head><body><div>helloworld</div></body></html>"
baseURL: baseURL];
[frameView setDocumentView:webView];
[[frameView documentView] setFrame:[frameView visibleRect]];
the question is how to make a self defined protocol instead of http://?
adium://%#/adium , first section is called protocol you can also register your protocol webkit: Take a look at How to map a custom protocol to an application on the Mac? and Launch Scripts from Webpage Links
[NSURLProtocol registerClass:[AIAdiumURLProtocol class]];
[ESWebView registerURLSchemeAsLocal:#"adium"];
I tried to find where did adium define the adium schema in the info.plist, unfortunately, there's nothing there, only some irc/xmpp protocols.
so I finally launched the debugger, and found the code above in the AIWebKitDelegate init method, anyway this is another way to register a self defined protocol~

checking app download completion from my own app

so what I'm trying to do here is the following: let's say the user has already installed my app, app "A", from the store. On certain conditions, app "A" will open an URL pointing to a specific app page,app "B", on the App Store passing a redemption code so the user of app A is able to download app "B" without paying any additional money. So here's what I'm doing:
NSString *urlBase = #"https://phobos.apple.com/WebObjects/MZFinance.woa/wa/freeProductCodeWizard?code=";
NSURL *urlRedemptionCode = [NSURL URLWithString:[urlBase stringByAppendingString:code]];
[[UIApplication sharedApplication] openURL:urlRedemptionCode];
This is working fine, so the question is: how do I know that the download of app "B" was completed correctly (or with errors) so I can take appropriate action in app "A"?
Thanks so much.
You could use NSURLConnection in combination with NSURLRequest and NSURLResponse instead of directly calling [[UIApplication sharedApplication] openURL:yourURL].
NSURLConnection will allow you to set a delegate that will be notified when:
Data is (partially) received
Connection failed
Download finished
etc.
Check Using NSURLConnection at the official documentation.

How to set up initial Core Data store in a Mac app?

I am an experienced iOS developer trying to make my first Mac app. I want to use Core data to store the data in my app. In my iOS apps, I generally have a pre-created SQLite file which is used as the initial state of the data store, and which is moved into place on the first time the app is run, like this:
NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"Datafile.sqlite"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:storePath]) {
NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:#"Datafile-DefaultData" ofType:#"sqlite"];
if (defaultStorePath) {
[fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];
}
}
I want to do something similar in the mac app, except put the data in the ~/Library/Application Support/MyApp directory. I can't seem to figure out how to do it. Any pointers?
In Xcode 4, the default Core Data project template, for some reason, uses the root ~/Library directory (ie ~/Library/Application to store your Core Data file. You should change this anyways (because it's a bad idea), but once you do that, it should work as you expect. I believe the default name on the Mac is storedata, and you should also note that you'll need to change the store type from XML, which is the default.

Resources