Attempt to rename file in Documents directory has error "file:/..." - ios

Below is the code I have written to change the name of any file stored in an iOS device "Documents" directory.
When renaming the file using this code, the prefix resolves to...
"file:/localhost/private/var/mobile/Applications/.../Documents/"
instead of the correctly formatted...
"file://localhost/private/var/mobile/Applications/.../Documents/"
I am losing a slash, and so the rename method fails!!!
I have rewritten this for both NSString and NSURL formats, and both methods present the identical error. I have tested this using the iOS Simulator and on device, and both tests present the identical error.
I suspect I am overlooking something simple, but cannot figure what it is - any help please?
- (void)alterFileNameOrExtension {
NSError *errorMove = nil;
NSError __autoreleasing *error = nil;
//note below - entity attribute document.dStringURL has a data type NSString
NSString *file = [document.dStringURL lastPathComponent];
NSString *fileName = [file stringByDeletingPathExtension];
NSString *fileExtension = [file pathExtension];
NSString *fileNameNew = nil;
//note below - self.tempFileComponent, self.tempFileName & self.tempFileExtension
//note below - are set in the (IBAction) method textFieldDidEndEditing:
//note below - self.tempFileComponent determines whether the user is attempting to change the file name or the file extension
if (self.tempFileComponent == 1) {
fileNameNew = [[self.tempFileName stringByAppendingPathExtension:fileExtension] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
} else if (self.tempFileComponent == 2) {
fileNameNew = [fileName stringByAppendingPathExtension:self.tempFileExtension];
} else {
NSLog(#"%# - %# - attempt to determine tempFileComponent has (possible undefined) E~R~R~O~R: %#_", self.className, NSStringFromSelector(_cmd), error.localizedDescription);
}
NSString *filePath = [document.dStringURL stringByDeletingLastPathComponent];
NSString *filePathNew = [filePath stringByAppendingPathComponent:fileNameNew];
BOOL move = [[NSFileManager defaultManager] moveItemAtPath:document.dStringURL toPath:filePathNew error:&errorMove];
if (!move) {
//handle error
} else {
//complete process
}
}
#
With assistance from #Mario, I have adjusted my code and include the working version below for the benefit of others...
#
NSError *errorMove = nil;
NSError __autoreleasing *error = nil;
NSString *file = [document.dStringURL lastPathComponent];
NSString *fileName = [file stringByDeletingPathExtension];
NSString *fileExtension = [file pathExtension];
NSString *fileNameNew = nil;
if (self.tempFileComponent == 1) {
fileNameNew = [self.tempFileName stringByAppendingPathExtension:fileExtension];
} else if (self.tempFileComponent == 2) {
fileNameNew = [fileName stringByAppendingPathExtension:self.tempFileExtension];
} else {
NSLog(#"%# - %# - attempt to determine tempFileComponent has (possible undefined) E~R~R~O~R: %#_", self.className, NSStringFromSelector(_cmd), error.localizedDescription);
}
NSURL *fileURLOld = [NSURL URLWithString:document.dStringURL];
NSURL *fileURLPrefix = [fileURLOld URLByDeletingLastPathComponent];
NSURL *fileURLNew = [fileURLPrefix URLByAppendingPathComponent:fileNameNew];
BOOL move = [[NSFileManager defaultManager] moveItemAtURL:fileURLOld toURL:fileURLNew error:&errorMove];
if (!move) {
//handle error
} else {
//complete process
}

The NSString path manipulation methods like stringByAppendingPathComponent expects file paths not URLs. It will remove double slashes as this is not a valid file path (although it is a valid URL).

Related

how to add json file in ActionRequestHandler safari extinction

I am develop a add blocker app, so i want to add json file in my ActionRequestHandler class from document directory. In ActionRequestHandler class already have code that add blockerList.json which is in main bundle
actually main problem is this if i edit in blockerList.json then its not editable because of permission because this file is in main bundle so aap don't provide on editing in any file.So i generate a new file in document directory which is editable but i cant add it in safari extention. here is my code
- (void)beginRequestWithExtensionContext:(NSExtensionContext *)context {
NSItemProvider *attachment;
NSString *contentOfURL;
NSString *documentsFilePath = [self grabFilePath:#"Block.json"];
NSURL *documentsURL = [NSURL fileURLWithPath:documentsFilePath];
if ([documentsFilePath length] != 0) {
NSError *error;
// NSURL *url = [NSURL URLWithString:APP_DEFAULT_BLOCKS_URL];//[[NSURL alloc] initWithString:APP_DEFAULT_BLOCKS_URL]
contentOfURL = [NSString stringWithContentsOfURL:documentsURL encoding:NSUTF8StringEncoding error:&error];
if (error)
NSLog(#"Error reading remote json file: %#", error.localizedDescription);
}
if (contentOfURL != (id)[NSNull null] && contentOfURL.length != 0) {
attachment = [[NSItemProvider alloc] initWithItem:contentOfURL typeIdentifier:#"public.json"];
} else {
NSLog(#"URL not defined or accessible - using local JSON");
attachment = [[NSItemProvider alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:#"blockerList" withExtension:#"json"]];
}
NSExtensionItem *item = [[NSExtensionItem alloc] init];
item.attachments = #[attachment];
[context completeRequestReturningItems:#[item] completionHandler:nil];
}
- (NSString *)grabFilePath:(NSString *)fileName {
NSString *filePath = [[NSString alloc]initWithFormat:#"Documents/%#", fileName];
NSString *documentsFilePath = [NSHomeDirectory()stringByAppendingPathComponent:filePath];
return documentsFilePath;
}

Copying a realm-file seems to cause realm Migration-block call - why?

After copying a .realm-file from folder-location1 to folder-location2 (and also changing its name from location1.realm to location2.realm using NSFileManager) - it seems that after doing so, the first call to this new file causes a migration-block call! (i.e. setSchemaVersion). I wonder WHY ???
Prior calls to the "location1/location1.realm" File did not cause a migration-block call - however calls to "location2/location2.realm" do - and the files are identical in structure (at least in Realm-Browser there is no obvious difference) !!
Here is my code :
ApplicatonSuppPathHandler *ApplicationSupportPathHandler = [[ApplicatonSuppPathHandler alloc] init];
// creation of location where this directory shall be placed on the iPhone
// typically /library/Application Support/<bundleID_name>/RLMGeneralDatabasesFolderName/...
// = name of directory that the .realm-File finally should be placed in
NSString *RLMLocation1DirectoryName = folderName;
// if it does not exist already, create the RLMLocation_xyz-directory (.../library/Application Support/<bundleID_name>/RLMDatabasesFolderName)
if([ApplicationSupportPathHandler getURLToApplicationDirectoryWithSubDirectory:RLMLocation1DirectoryName] == nil) {
[ApplicationSupportPathHandler createSubDirectoryAtLocationToApplicationDirectory:RLMLocation1DirectoryName];
}
// get the name of entire directory just created
NSURL *RLMLocation1Directory = [ApplicationSupportPathHandler getURLToApplicationDirectoryWithSubDirectory:RLMLocation1DirectoryName];
// name of entire path-name (including filename !! ...needed for copy function below...)
NSString *RLMLocation1Path = [[RLMLocation1Directory path] stringByAppendingPathComponent:fileName];
// HERE IS WHERE THE MIGRATION BLOCK IS CALLED - WHY ?????
// *******************************************************
RLMRealm *realm_Location1 = [RLMRealm realmWithPath:RLMLocation1Path]; // pointing to realm file at path
// the rest does work after the migration-block call...
[realm_Location1 beginWriteTransaction];
[realm_Location1 deleteAllObjects];
[realm_Location1 addObject:RLMTopoRes];
[realm_Location1 commitWriteTransaction];
Below is the implementation of the used ApplicationSuppPathHandler class-methods:
#implementation ApplicatonSuppPathHandler
- (NSURL*)getURLToApplicationDirectoryWithSubDirectory:(NSString*)SubDirectoryName {
NSString* appBundleID = [[NSBundle mainBundle] bundleIdentifier];
NSFileManager*fm = [NSFileManager defaultManager];
NSURL* dirPath = nil;
// Find the application support directory in the home directory.
NSArray* appSupportDir = [fm URLsForDirectory:NSApplicationSupportDirectory
inDomains:NSUserDomainMask];
if ([appSupportDir count] > 0)
{
// Append the bundle ID and the location-Foldername to the URL for the Application Support directory
dirPath = [[[appSupportDir objectAtIndex:0] URLByAppendingPathComponent:appBundleID] URLByAppendingPathComponent:SubDirectoryName];
BOOL isDir;
BOOL exists = [fm fileExistsAtPath:[dirPath path] isDirectory:&isDir];
if (exists) {
/* file exists */
if (isDir) {
/* path exists */
return dirPath;
}
else {
NSLog(#"Directory does not exist");
return nil;
}
}
else {
/* file does not exist */
return nil;
}
}
return dirPath;
}
- (void)createSubDirectoryAtLocationToApplicationDirectory:(NSString*)SubDirectoryName {
NSString* appBundleID = [[NSBundle mainBundle] bundleIdentifier];
NSFileManager*fm = [NSFileManager defaultManager];
NSURL* dirPath = nil;
// Find the application support directory in the home directory.
NSArray* appSupportDir = [fm URLsForDirectory:NSApplicationSupportDirectory
inDomains:NSUserDomainMask];
if ([appSupportDir count] > 0)
{
// Append the bundle ID and the location-Foldername to the URL for the Application Support directory
dirPath = [[[appSupportDir objectAtIndex:0] URLByAppendingPathComponent:appBundleID] URLByAppendingPathComponent:SubDirectoryName];
// If the directory does not exist, this method creates it.
// This method call works in OS X 10.7 and later only.
NSError* theError = nil;
if (![fm createDirectoryAtURL:dirPath withIntermediateDirectories:YES attributes:nil error:&theError]) {
// Handle the error.
NSLog(#"%#", theError.localizedDescription);
}
else {
// Mark the directory as excluded from iCloud backups
if (![dirPath setResourceValue:#YES
forKey:NSURLIsExcludedFromBackupKey
error:&theError]) {
NSLog(#"Error excluding %# from iCloud backup %#", [dirPath lastPathComponent], theError.localizedDescription);
}
else {
// NSLog(#"Location Directory excluded from iClud backups");
}
}
}
}
There was previously a bug in Realm where new realm files would have their schema version set to 0 instead of the current schema version, which would trigger a migration in your case.
A fix for this was pushed to the master branch of Realm last week: https://github.com/realm/realm-cocoa/pull/1142
Building Realm from master should address the issue you're having. Realm v0.88.0 will be released shortly with this fix.
...hhm - seems that another method messed up !
The below code shows this method that loads data from a realm-file into a realm-wrapper-object.
Coming back to the original problem (location2/location2.realm file creating migraton-block):
Unfortunately, I was not aware that calling this "loadData_..."-method needed to be called with caution ! If it is called twice - once to location1/location1.realm and then a second time (to location2/location2.realm) - that is when things get messed up !
I tried to create a "wrapper" that loads and saves Realm-objects. But it seems more difficult with Realm than originally expected. Thanks for any comment on this !!
- (void) loadData_at_TopoNr_from_LocationRLM :(NSNumber *)TopoNr :(NSString *)folderName :(NSString *)fileName {
// realm-object calling "get_TopoResultRLM_FilePath" must be of same object-type, otherwise block-migration call !
RLMRealm *realm = [RLMRealm realmWithPath:[self get_TopoResultRLM_FilePath :folderName :fileName]];
RLMResults *resTopoResult = [RLMTopoResult allObjectsInRealm:realm];
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:#"TopoNrRLM == %d", [TopoNr intValue]];
RLMResults *resultTopoResult = [resTopoResult objectsWithPredicate:predicate1];
if ([resultTopoResult count] <= 1) {
if ([resultTopoResult count] == 1) {
// found one object
// data loading
self.TopoNrRLM = [resultTopoResult.firstObject TopoNrRLM];
self.nameAnamneserRLM = [resultTopoResult.firstObject nameAnamneserRLM];
self.anamneseDateRLM = [resultTopoResult.firstObject anamneseDateRLM];
self.NumberOfCriteriaRLM = [resultTopoResult.firstObject NumberOfCriteriaRLM];
self.BestMatchMethodRLM = [resultTopoResult.firstObject BestMatchMethodRLM];
self.RealmFrameworkVersionRLM = [resultTopoResult.firstObject RealmFrameworkVersionRLM];
self.BoundaryConditionVerionRLM = [resultTopoResult.firstObject BoundaryConditionVerionRLM];
self.CriteriaRLM = [resultTopoResult.firstObject CriteriaRLM];
self.imageNameRLM = [resultTopoResult.firstObject imageNameRLM];
self.imageDataRLM = [resultTopoResult.firstObject imageDataRLM];
}
else { ....
Here is the property definition of the wrapper-object-class :
// GUIData-RLM
#property (nonatomic) RLMGUIData *GUIDataRLM;
// Location-RLM
#property (nonatomic) RLMTopoResult *LocationRLM;
Here is the object creation and call of that loadData_at...-method :
RLMTopoResult *LocationRealm = [[RLMTopoResult alloc] init];
[self setLocationRLM:LocationRealm];
[LocationRealm loadData_at_TopoNr_from_LocationRLM :[NSNumber numberWithInt:[GUIDataRealm TopoNrRLM]] :[GUIDataRealm locationFolderNameRLM] :[NSString stringWithFormat:#"%#%s", [GUIDataRealm locationFolderNameRLM], ".realm"]];

Using block statement to detect failed file modification

I have a view controller with a tableview and each tableview cell has an editable UILabel in it. Each cell is also associated with an audio file. Whenever the label is edited, I call an NSObject subclass that handles my files to rename the audio file to whatever the label was changed to. I then return the NSURL absolute string to store in core data. My question is, if this process throws an error - such as "file path already exists", how can I get it to show a UIAlertView in my view controller and not my NSObject subclass. I'm guessing I need some type of block that returns either a NSString or an NSError. I don't have much experience with blocks and any help would be appreciated.
Method in my view controller that calls the NSObject subclass to rename the file
recording.audioURL = [self.managedDocument changeFileName:previousPath withNewComponent:textField.text];
This is the method in my NSObject subclass that renames the audio file
-(NSString*) changeFileName:(NSString*) previousPath withNewComponent:(NSString*)newComponenet
{
NSURL * oldURL = [self.url URLByAppendingPathComponent:#"audioFiles"];
oldURL = [oldURL URLByAppendingPathComponent:[previousPath lastPathComponent]];
NSString * trimmedString = [newComponenet stringByReplacingOccurrencesOfString:#" " withString:#""];
NSURL * newURL = [self.url URLByAppendingPathComponent:#"audioFiles"];
newURL = [newURL URLByAppendingPathComponent:trimmedString];
newURL = [newURL URLByAppendingPathExtension:#"m4a"];
NSFileManager * fileManager = [NSFileManager defaultManager];
NSError * err;
BOOL result = [fileManager moveItemAtURL:oldURL toURL:newURL error:&err];
if(!result)
{
NSLog(#"Error: %#", err);
}
return newURL.absoluteString;
}
The most straightforward approach is to follow the example of the NSFileManager method you're using. Output an NSError* pointer indirectly through a by-reference parameter and make the method's direct return value indicate success or failure:
-(NSString*) changeFileName:(NSString*) previousPath withNewComponent:(NSString*)newComponenet error:(NSError**)error
{
NSURL * oldURL = [self.url URLByAppendingPathComponent:#"audioFiles"];
oldURL = [oldURL URLByAppendingPathComponent:[previousPath lastPathComponent]];
NSString * trimmedString = [newComponenet stringByReplacingOccurrencesOfString:#" " withString:#""];
NSURL * newURL = [self.url URLByAppendingPathComponent:#"audioFiles"];
newURL = [newURL URLByAppendingPathComponent:trimmedString];
newURL = [newURL URLByAppendingPathExtension:#"m4a"];
NSFileManager * fileManager = [NSFileManager defaultManager];
BOOL result = [fileManager moveItemAtURL:oldURL toURL:newURL error:error];
if(!result)
return nil;
return newURL.absoluteString;
}
In the caller, check the return value to determine if it failed and, if so, present the error.

Song doesn't play when method called from another class

I'm trying to play a song in my application. When the the code to play a song is put right away in the controller it runs good.
But when i put the code in a class, call the class then call the method to play the song, nothing happens ? If someone have a clue please feel free to help.
here is the code to play a song
-(void)randomSound{
NSLog(#"sound");
NSString * path;
NSError * err;
NSString *name;
NSArray *names = [[NSArray alloc] initWithObjects:#"1up.wav", #"mario02.dsp.wav", #"mario04.dsp.wav", #"mario06.dsp.wav", #"mrf.dsp.wav", nil];
name = [names randomObject];
path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:name];
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
NSURL * url = [NSURL fileURLWithPath:path];
self.snd = [[AVAudioPlayer alloc] initWithContentsOfURL:url
error:&err] ;
if (! self.snd) {
NSLog(#"data named '%#' had error %#", name, [err localizedDescription]);
} else {
NSLog(#"playing");
[self.snd prepareToPlay];
[self.snd play];
}
} else {
NSLog(#"data file '%#' doesn't exist at '%#'", name, path);
}
}
The way i call the method
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"YAHOO"])
{
YahooViewController *YH = [[YahooViewController alloc] init];
[YH randomSound];
}
The random method in case someone would like to know whats in it
-(id)randomObject {
NSUInteger myCount = [self count];
if (myCount)
return [self objectAtIndex:arc4random_uniform(myCount)];
else
return nil;
}
After discussion in comments it was identified the issue was URL encoding.
Check out this question / answer which will show you how to URLEncode a string:
How do I URL encode a string

iOS - Check if file exists Dropbox Sync API iOS SDK

I'm new to iOS development, and working on an app that support Dropbox sync for text files.
Having followed tutorial on Dropbox site but I'm not be able to check if a file is exist.
As implemented:
NSString *dropboxFileExtension;
switch ([[NSUserDefaults standardUserDefaults] integerForKey:kFileExtension]) {
case txt:
dropboxFileExtension = [NSString stringWithFormat:#"%#.txt", titleString];
break;
case md:
dropboxFileExtension = [NSString stringWithFormat:#"%#.md", titleString];
break;
case markdown:
dropboxFileExtension = [NSString stringWithFormat:#"%#.markdown", titleString];
break;
default:
break;
}
DBPath *newPath = [[DBPath root] childPath:[NSString stringWithFormat:#"%#", dropboxFileExtension]];
DBFile *file = [[DBFilesystem sharedFilesystem] createFile:newPath error:nil];
[file writeString:self.note.contents error:nil];
If I update its contents, this will throws an error that file is exists.
So how can I check that file is exists and then perform appropriate action like overwriting file or updating file. Thank you!
EDIT / Working Solution: Logically, I just have to check whether if file info exists using DBFileInfo class (1). If (1) true -> we call openFile:error before writeString:error, else call createFile:error. As suggested by #rmaddy.
So...
DBPath *newPath = [[DBPath root] childPath:[NSString stringWithFormat:#"%#", dropboxFileExtension]];
DBError *error = nil;
DBFileInfo *info = [[DBFilesystem sharedFilesystem] fileInfoForPath:newPath error:&error];
if (info) {
// file exists
NSLog(#"size %lli byte(s), modified dated %#", info.size, info.modifiedTime);
_file = [[DBFilesystem sharedFilesystem] openFile:newPath
error:nil];
} else {
_file = [[DBFilesystem sharedFilesystem] createFile:newPath
error:nil];
}
[_file writeString:self.note.contents error:nil];
Try getting the DBFileInfo for the path:
DBError *error = nil;
DBFileInfo *info = [[DBFileSystem sharedFileSystem] fileInfoForPath:newPath error:&error];
if (info) {
// file exists
}

Resources