howto resolve UIDocumentStateSavingError and UIDocumentStateClosed - objective-c

I have an iPhone-iCloud app. Now one document has the state UIDocumentStateSavingError and UIDocumentStateClosed. I can see the file on developers.icloud.com with the status "file upload is pending". But i don't know what to do now
When i try to delete the file with the code:
NSFileCoordinator* fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
[fileCoordinator coordinateWritingItemAtURL:fileURL options:NSFileCoordinatorWritingForDeleting error:nil byAccessor:^(NSURL* writingURL) {
NSFileManager* fileManager = [[NSFileManager alloc] init];
[fileManager removeItemAtURL:writingURL error:nil];
}];
the file is still there. I tried to delete the app on all devices but nothing changed. How can I delete this file or resolve the problem?

It's long ago but still unanswered, so if your problem persists:
For me it works to prepend the [fileManager removeItemAtURL:...] with a [fileManager setUbiquitous:NO...] on the file and then let the fileManager delete the local copy.
Take care to use NSError and boolean result handling of the fileManager actions to be sure it really works. So if you get back an NSError you could see the reason why it failed. That's always good practice.
I stumbled into your question because I get the message "File upload is Pending" after such a deleted file is re-created even if it's some hours between deletion and creation.

Related

Xcode 5 [NSString writeToFile] without absolute path

I've checked out a few other posts about this topic, but I am still left with some doubt on whether or not [NSString writeToFile] is writing to the relative path.
NSError *error = nil;
BOOL success = [str writeToFile:#"someFile.txt"
atomically:YES
encoding:NSUTF8StringEncoding
error:&error];
NSString *status = success ? #"Success" : #"Failure";
if(success){
NSLog(#"Done Writing: %#",status);
}
else{
NSLog(#"Done Writing: %#",status);
NSLog(#"Error: %#",[error localizedDescription]);
}
writeToFile works when given the path to a certain folder and by NSLogging the error, I can see what kind of error occurs. However, when running the above code, no error occurs and after having done a thorough search, I think I can safely say that a file was never created. What's going on behind the scenes?
Well it's certainly working, which you confirm yourself as your code traps and reports errors very nicely. Your only issue is that you don't know where the file is being written to, and in this case, as no path has been specified it will be to the current working directory, which is a concept in pretty much all operating systems (even Windows!).
I must admit that I don't know what the default current working directory is under iOS, but you can find out yourself with:
NSString *cwd = [[NSFileManager defaultManager] currentDirectoryPath];
NSLog(#"cwd='%#'", cwd);

setUbiquitous:itemAtURL:destinationURL:error: does not remove the item from iCloud

If I send the message
[[NSFileManager defaultManager] setUbiquitous:NO
itemAtURL:url
destinationURL:iCloudURL
error:&err]
to remove an item from iCloud, it doesn't actually delete the file on the Ubiquitous Container. Is this the expected behaviour?
The method returns NO and the error object contains
Error Domain=NSCocoaErrorDomain Code=512 "The operation couldn’t be
completed. (Cocoa error 512.)"
UserInfo=0x20870970
{NSURL=file://localhost/var/mobile/Applications/168EE8CD-4CDF-49BE-AD88-1DC7DD9CF25F/Documents/test.txt,
NSUnderlyingError=0x20863a00 "The operation couldn’t be completed.
(LibrarianErrorDomain error 2 - Cannot disable syncing on a unsynced
item.)"}
The error is pretty clear. You're trying to delete an item from iCloud that's not in iCloud. When you want to delete an item from iCloud using setUbiquitous:..., the item URL (itemAtURL:) should be the iCloud URL. The destination URL can be something local (but is ignored if ubiquitous is set to NO).
When specifying the "setubiquitous" parameter to "no", your destinationURL needs to be the local url, not the iCloud one. You have your URLs switched
To delete an item on iCloud, you can try this code:
NSError *err;
NSFileCoordinator* fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
[fileCoordinator coordinateWritingItemAtURL:_url
options:NSFileCoordinatorWritingForDeleting
error:&err
byAccessor:^(NSURL* writingURL) {
NSFileManager* fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtURL:writingURL error:nil];
}];
[fileCoordinator autorelease];
Good luck!

Update read-only Core Data sqlite in main bundle

I am using a read-only Core Data sqlite from the Main Bundle, works well. When i add a new version of the database (more read-only data) to the main bundle it still reads the "Old" version of the database.
Anyone that can help me understand why and what to do to get the new database version the current one when a current user download an update with the new version of the database?
This is part of trying to solve the problem in this post: Same problem when accessing updated database from documents directory
===SOLUTION====
I solved this by changing the name of the new database in the "new" main bundle and it works like a dream. Also, if this is an update i delete the old database in the documents directory to clean up.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
//===READ DATABASE FROM MAIN BUNDLE===//
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *storeUrl = [[NSBundle mainBundle] URLForResource:kNewDB withExtension:#"sqlite"];
//=== IF THE OLD DATABASE STILL EXIST DELETE IT FROM DOCUMENT DIRECTORY ===//
NSURL *oldDatabasePathURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"database.sqlite"];
NSString *oldDatabasePath = [oldDatabasePathURL path];
if ([fileManager fileExistsAtPath:oldDatabasePath]) {
//Remove old database from Documents Directory
[fileManager removeItemAtURL:oldDatabasePathURL error:nil];
}
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
NSError *error;
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
// Update to handle the error appropriately.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1); // Fail
}
return persistentStoreCoordinator;
}
You must have a place in your code where you check to see if a copy of the database file exists in some writable directory (possibly your Documents directory) and if not, then you copy it there. This is a very common approach to take when you need to make changes to your database. The problem is, when you update your app, the file already exists, so it is never copied over again.
There are two approaches to take to fix your problem:
(Preferable): Don't copy the database in the first place. Since it is read only, you don't need to, and it just takes up extra space on the device. Simply open the database using the path of the file that is in the main bundle.
Instead of checking to see if a file exists in the writable directory, check to see if it is newer than the one in the main bundle. (not by using the date, since they could have installed the program and created the file after your update was submitted to the app store for approval, which would result in the new one not being copied over. You need to check the version of the database, possibly by storing another file in your app bundle which stores the version info, or determining it with version specific code). If not, then copy it over again.
PeterK, I was having the same issue when using the tutorial at http://www.raywenderlich.com/12170/core-data-tutorial-how-to-preloadimport-existing-data-updated to use a read-only sqlite database by Core Data. All was fine, until I had to update my database and re-release my target app. As you know, the proposed code in that tutorial only copies in the new database if no database exists in the Application's Documents directory.
I did not think that renaming my database (and updating the copying code) was a good design approach, so I got my design working by following Inafziger's preferred advise and reading up on iOS file structure. I provide the below only to show how to implement Inafziger's proposal. And of note is that this approach likely only works if your app does not change the contents of the Core Data information as it is read in as read-only.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
// Updated processing to now just have the NRPersistentStoreCoordinator point to the sqlite db in the
// application's Bundle and not by copying that db to the app's Documents directory and then using
// the db in the Documents directory.
NSURL *refactoredStoreURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#“NameOfYourDatabase ofType:#"sqlite"]];
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
// Added to ensure the NSPersistentStoreCoordinator reads the Bundle's db file as read-only since
// it is not appropriate to allow the app to modify anything in the Bundle
NSDictionary *readOnlyOptions = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSReadOnlyPersistentStoreOption, nil];
// Use the URL that points to the Bundle's db file and used the ReadOnly options
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:refactoredStoreURL options:readOnlyOptions error:&error]) {
// Your logic if there is an error
}
return _persistentStoreCoordinator;
}
I hope this helps the next reader of this question.

iOS mainBundle not loading resources

I had a working iOS project, and whilst working on a git branch, the project would suddenly not load any resources from the main Bundle...I'm loading an audio file for a simple AVAudioPlayer with:
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/nadamintrov1.aif", [[NSBundle mainBundle] resourcePath]]];
NSError *error;
NSLog(#"%#", url);
splashScreenAudioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
and in other ViewControllers I'm also loading other files such as:
patch = [PdBase openFile:#"klangfarbe6ep.pd" path:[[NSBundle mainBundle] resourcePath]];
if (!patch) {
NSLog(#"Failed to open patch!");
// Gracefully handle failure...
}
but whilst both those worked just fine before, now I get "couldn't initialise splash audio player" and for the patch:
open: /var/mobile/Applications/464B65AD-9E2C-42C9-8BBA-12AFD0D48393/Nadam.app/klangfarbe6ep.pd: No such file or directory
klangfarbe6ep.pd: No such file or directory
2012-02-26 12:07:17.332 Nadam[520:707] Failed to open patch!
which is weird...I mean the NSLog(#"%#", url); I put up for the AudioPlayer clearly returns:
2012-02-26 12:06:49.127 Nadam[520:707] file://localhost/var/mobile/Applications/464B65AD-9E2C-42C9-8BBA-12AFD0D48393/Nadam.app/nadamintrov1.aif
so why on earth isn't it loading it? Diff from git over the last few changes don't show anything in the project file that I can see as corruption...
anyone had that happen to them before? any way of debugging it? I read this thread:
What is the alternative of [NSBundle mainBundle] URLForResource:withExtension: in iOS 3 SDK
But can't understand why it was working before and not now with no project changes...
I don't know exactly what is the issue here. But it is the most common problem. In two situations such issue occurs. 1. file path is wrong. 2.File is not included in bundle.
After checking above file path shown by you I don't think it is the issue of file path. But you can check your file is included in target or not. Just right click on your file and select get info. Where check in target your current target is selected or not.

writeToFile doesn't change the content of the file xcode4 objective-c

I finished writing a little program, which is able to read and write a/into a .txt file.
When I execute the program, everything is running fine except that the content of the file doesn't change permanently. I got a writeToFile and "readFile" button and the content seems to change every time I press one of them, but when I open the file manually (while testing or after shutting down the program) theres still the origin content in it.
Doesn't the "real" file content change while just using the simulator? Or is it just me making some bad mistakes?
-(IBAction)buttonPressed { //The writeToFile Method
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"txt"];
NSString *writeData = enterText.text;
NSError *error;
BOOL ok = [writeData writeToFile:filePath atomically:NO encoding:NSUnicodeStringEncoding error:&error];
if (!ok)
{
NSLog(#"Error while writing file at %#/n%#",filePath,[error localizedFailureReason]);
}
testText.text =#"File saved!";
enterText.text = #"";
enterText.placeholder =#"Enter your text here";
}
testText = TextView for Output
enterText = TextField for Input
Your filePath variable is pointing to a file within the resource bundle of your app (which is not writable). What you need to do is locate the user's Documents folder, and create your file there.