iOS11.2 NSFileManager API behivour is different than previous iOS versions - ios

I am using below piece of code to calculate a checksum for files I added in a "temp" folder for app bundle. I am getting different checksum values in iOS11.2 compared to all lower iOS version. I was wondering what has changed among these versions? Is some changes in File system in iOS 11.2 is reason for the difference? Can somebody please throw light on the issue or faced similar issues? Below is the piece of code I used.
NSString* bundleRootDir;
bundleRootDir = [[NSBundle mainBundle] bundlePath];
NSLog(#"bundleRootDir %# ",bundleRootDir );
NSString *tmpDir = [bundleRootDir stringByAppendingPathComponent:#"temp"];
NSLog(#"tmpDir %# ",tmpDir);
NSFileManager *fileManager1=[[NSFileManager alloc] init];
NSDirectoryEnumerator *dirEnum = [fileManager1 enumeratorAtPath:tmpDir];
// NSFileManager *fileManager1 = [NSFileManager defaultManager];
//NSArray *filePathsArray1 = [fileManager1 subpathsOfDirectoryAtPath:tmpDir error:nil];
NSMutableData *allFilesData1 = [NSMutableData new];
uLong crc1 = crc32(0L, Z_NULL, 0);
NSInteger filecount1=0;
//for (NSString *file1 in filePathsArray1) {
NSString *file1;
while ((file1 = [dirEnum nextObject])) {
NSString *fullPathToFile1 = [tmpDir stringByAppendingPathComponent:file1];
BOOL isDirectory1;
if ([fileManager1 fileExistsAtPath:fullPathToFile1 isDirectory:&isDirectory1] && isDirectory1 ) {
// ignore directories...
continue;
}
else {
NSData *myData1 = [NSData dataWithContentsOfFile:fullPathToFile1];
[allFilesData1 appendData:myData1];
NSLog(#"Checksum files included %# , %d",fullPathToFile1,filecount1);
}
filecount1++;
}
NSLog(#"Checksum cal : length of data %lu",[allFilesData1 length]);
NSString *strData = [[NSString alloc]initWithData:allFilesData1 encoding:NSUTF8StringEncoding];
NSLog(#"All Data for checksum %#",strData);
crc1 = crc32(crc, [allFilesData1 bytes], [allFilesData1 length]);
NSLog(#"WL_INIT_PACKAGE - testWebResourcesChecksum crc32 output %lu",crc1);
NSString *checksum1 = [NSString stringWithFormat:#"%lu", crc1];
NSLog(#"WL_INIT_PACKAGE - testWebResourcesChecksum crc32 output %#",checksum1);

Related

Cant write data to plist file in - objective c

I'm trying to read and write data to my plist file, While the reading part goes well, the writing part does nothing.
I might be mistaken for the writing part - i can't see any changes in my file under my bundle - it is still empty after my changes, and when i close the app and open it again - i still see empty email address line.
The code for writing (and placing the plist in the document folder for future writings)
NSFileManager *fileManger=[NSFileManager defaultManager];
NSError *error;
NSArray *pathsArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *doumentDirectoryPath=[pathsArray objectAtIndex:0];
NSString *destinationPath= [doumentDirectoryPath stringByAppendingPathComponent:#"userData.plist"];
NSLog(#"plist path %#",destinationPath);
if ([fileManger fileExistsAtPath:destinationPath]){
NSLog(#"database localtion %#",destinationPath);
//return;
}
NSString *sourcePath = [[[NSBundle mainBundle] resourcePath]stringByAppendingPathComponent:#"userData.plist"];
[fileManger copyItemAtPath:sourcePath toPath:destinationPath error:&error];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile: sourcePath];
NSString *emailAddress = (NSString *)[dict objectForKey: #"emailAddress"];
if([emailAddress isEqualToString:#""])
{
// Do stuff
}
And for writing
NSArray *pathsArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *doumentDirectoryPath =[pathsArray objectAtIndex:0];
NSString *destinationPath = [doumentDirectoryPath stringByAppendingPathComponent:#"userData.plist"];
NSMutableDictionary *plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile: destinationPath];
[plistDict setValue:#"myEmail#gmail.com" forKey:#"emailAddress"];
[plistDict writeToFile:destinationPath atomically: YES];
But as i said, nothing is changed in the file itself, and not even when i save, close the app and open it again (the string is always empty on my reading part)
Any help will be more than welcomed.

NSTask not working for file path with special characters

I am using NStask to get the folder size.Its working fine for normal file paths like home/ABC/Users/testUser/Documents. But it is not showing any output for file path like home/ABC/Users/testUser/Ω≈ç∂√√√∂ƒ∂.However I am getting proper output for the same file path on terminal. Any suggestion?
NSString* userName = #"test123_test123";
NSString* password = #"test";
NSString* serverIP = #"200.144.172.210";
NSString* sizeFolderPath = [[NSBundle mainBundle] pathForResource:#"demoUtilities" ofType:nil];
NSString* xml= #"--test";
NSString* passwordArg = [NSString stringWithFormat:#"--pwd-=%#",password];
NSString *filePath = #"UsersMac/Users/test/Ω≈ç∂√√√∂ƒ∂";
NSString* address = [NSString stringWithFormat:#"%##%#::home/%#", userName, serverIP,filePath];
NSArray* arguments = [NSMutableArray arrayWithObjects:xml,passwordArg,address,nil];
TestCommandExcecuter *cmExec = [[TestCommandExcecuter alloc]init];
[cmExec setCommandString:sizeFolderPath];
[cmExec setCommandArguments:arguments];
I am using this code:
Depricated from 2.0
NSDictionary *fileDictionary = [[NSFileManager defaultManager]
fileAttributesAtPath:filePath traverseLink:YES];
long long size = [fileDictionary fileSize];
NSLog(#"size :: %lld",size);
Latest :
NSDictionary *fileDictionary = [[NSFileManager defaultManager]
attributesOfItemAtPath:filePath error:nil];
long long size = [fileDictionary fileSize];
NSLog(#"size :: %lld",size);
Here is the reference link :
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/Reference/Reference.html#//apple_ref/occ/instm/NSFileManager/attributesOfItemAtPath%3aerror%3a

iOS release not working as expected

I am using this code to get book names from a config.plist file. However my memory management is problematic. The '[dict release]' breaks the app completely and it exits.
The code works when the '[dict release]' is removed but it causes memory leaks as far as I can tell.
bnames is a global NSMutableArray
What am I doing wrong?
- (NSString *)loadBookname: (NSInteger) bookToLoad {
bookToLoad = [self bookOrder:bookToLoad];
//---get the path to the property list file---
plistFileNameConf = [[self documentsPath] stringByAppendingPathComponent:#"Config.plist"];
//---if the property list file can be found---
if ([[NSFileManager defaultManager] fileExistsAtPath:plistFileNameConf]) {
//---load the content of the property list file into a NSDictionary object---
dict = [[NSDictionary alloc] initWithContentsOfFile:plistFileNameConf];
bnames = [dict valueForKey:#"BookNames"];
[dict release];
}
else {
//---load the property list from the Resources folder---
NSString *pListPath = [[NSBundle mainBundle] pathForResource:#"Config" ofType:#"plist"];
dict = [[NSDictionary alloc] initWithContentsOfFile:pListPath];
bnames = [dict valueForKey:#"BookNames"];
[dict release];
}
plistFileNameConf = nil;
NSString *bookNameTemp;
bookNameTemp = [bnames objectAtIndex:bookToLoad - 1];
NSLog(#"bookName: %#", bookNameTemp);
return bookNameTemp;
}
You need to allocate your array properly:
bnames = [[NSArray alloc] initWithArray:[dict valueForKey:#"BookNames"]];
Double check that your dict returns the right data type.
There does not appear to be anything wrong with the way you allocate NSDictionary (although you could also use the [NSDictionary dictionaryWithContentsOfFile:] and save yourself having to worry about the release.
Either way I would suggest the issue is not with the [release] but probably the line BEFORE release:
bnames = [dict valueForKey:#"BookNames"];
a) Where is that allocated. I don't see an allocation or declaration of it anywhere?
b) What type of value do you expect back?
Put a break point on it and make sure your getting what you expect or anything.
If dict is not already a strong property, make it one. Then, use self.dict when assigning to it (and keep the release).
I've found what appears to be a better solution to the issue. This lets iOS manage the memory.
//---finds the path to the application's Documents directory---
- (NSString *) documentsPath {
NSLog(#"Start documentsPath");
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
// NSLog(#"Found documentsPath 40");
NSLog(#"End documentsPath");
return documentsDir;
}
- (NSString *) configPath {
NSLog(#"Start configPath");
NSString *plistFileNameConf = [[self documentsPath] stringByAppendingPathComponent:#"Config.plist"];
if (![[NSFileManager defaultManager] fileExistsAtPath:plistFileNameConf]) {
plistFileNameConf = [[NSBundle mainBundle] pathForResource:#"Config" ofType:#"plist"];
}
NSLog(#"plistFile: %#",plistFileNameConf);
NSLog(#"End configPath");
return plistFileNameConf;
}
The following calls the above code as necessary:
NSString *Choice;
NSArray *properties;
NSString *errorDesc = nil;
NSPropertyListFormat format;
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:[self configPath]];
NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc];
if (!temp) {
NSLog(#"Error reading plist: %#, format: %d", errorDesc, format);
}
Choice = [temp objectForKey:#"Choice"];
properties = [temp objectForKey:Choice];

Storing and reading files from Documents directory iOS 5

In my game, when a level is completed the app stores a "1" in a file in the Documents directory of the app. When the game then loads, a player can only play a level if the previous level has been completed. When I test the game via Xcode and on a device the app works properly and a level cannot be played until the previous level has been completed. However, when the app was approved and released on the App Store, the app behaves as if each level has been completed (no locked levels). I can't figure this one out and would appreciate someone's help! The devices I'm testing on are all iOs 5.0 or higher.
Below is the code that saves the completed level in the Documents directory:
NSMutableData* data = [[NSMutableData alloc] init];
NSKeyedArchiver* coder = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
NSString *levelString = [NSString stringWithFormat:#"Level%d",level];
[coder encodeInteger:1 forKey:levelString];
[coder finishEncoding];
NSString *levelString2 = [NSString stringWithFormat:#"Level%d.save",level];
///
NSFileManager *filemgr;
NSString *dataFile;
NSString *docsDir;
NSArray *dirPaths;
filemgr = [NSFileManager defaultManager];
// Identify the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
// Build the path to the data file
dataFile = [docsDir stringByAppendingPathComponent:levelString2];
// Check if the file already exists
if ([filemgr fileExistsAtPath: dataFile])
{
[[NSFileManager defaultManager] removeItemAtPath:dataFile error:nil];
}
[data writeToFile:dataFile atomically:YES];
[coder release];
[data release];
}
#catch (NSException* ex)
{
CCLOG(#"level save failed: %#", ex);
}
Below is the code that reads the Document directory to see if the level has been completed:
if ([self loadCompletedLevels:6] == 1) { //// level gets unlocked **** }
-(int) loadCompletedLevels:(int)theLevel; {
int isLevelCompleted; //1 = completed
NSString* kSaveFile = [NSString stringWithFormat:#"Level%d.save",theLevel];
NSString *levelString = [NSString stringWithFormat:#"Level%d",theLevel];
#try
{
NSFileManager *filemgr;
NSString *dataFile;
NSString *docsDir;
NSArray *dirPaths;
filemgr = [NSFileManager defaultManager];
// Identify the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
// Build the path to the data file
dataFile = [docsDir stringByAppendingPathComponent:kSaveFile];
if ([[NSFileManager defaultManager] fileExistsAtPath:dataFile])
{
NSData* data = [[NSData alloc] initWithContentsOfFile:dataFile];
if (data && [data length] > 0)
{
NSKeyedUnarchiver* decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
isLevelCompleted = [decoder decodeIntForKey:levelString];
[decoder release];
}
[data release];
}
if (isLevelCompleted == 1) {
levelCompleted = YES;
}
}
#catch (NSException* ex)
{
levelCompleted = NO;
}
return isLevelCompleted; }
You should probably use a different approach for storing your data, but the real problem is that you are not initializing the return value, isLevelCompleted. It is on the stack, and does not have a default value. It starts out with whatever happens to be at that stack location.
So, if you don't set it, it will have an arbitrary value.
Also, you should probably use BOOL for a boolean value, but if you make this:
int isLevelCompleted = 0; //1 = completed
you will initialize it to "false" so it must be explicitly changed to "true" by your code.

Log Accelerometer data to a file on Iphone IOS

Hi I am trying to write to a file from the accelerometer data. Here is my code:
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
//xax.text = [NSString stringWithFormat:#"X:[%2.6f]",acceleration.x];
//yax.text = [NSString stringWithFormat:#"Y:[%2.6f]",acceleration.y];
//zax.text = [NSString stringWithFormat:#"Z:[%2.6f]",acceleration.z];
NSString *acc_x = [[NSString alloc] initWithFormat:#"X:[%2.6f]",acceleration.x];
NSString *acc_y = [[NSString alloc] initWithFormat:#"Y:[%2.6f]",acceleration.y];
NSString *acc_z = [[NSString alloc] initWithFormat:#"Z:[%2.6f]",acceleration.z];
xax.text = acc_x;
yax.text = acc_y;
zax.text = acc_z;
[acc_x release];
[acc_y release];
[acc_z release];
//wfm == 2 //Initialization of Appending to the file
if (wfm == 2)
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *txtFileName = [[NSString alloc] initWithFormat:#"tmp/%#.txt",txtName.text];
NSString *fileName = [NSHomeDirectory() stringByAppendingPathComponent:txtFileName];
//NSString *fileName = [NSHomeDirectory() stringByAppendingPathComponent:#"tmp/acc_w_trial2.txt"];
//Current Contents of the file
NSString *fileCurrent = [[NSString alloc] initWithContentsOfFile:fileName];
//Date and Time of each Accelerometer Data
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd 'at' HH:mm:ss:SSS"];
NSDate *date = [NSDate date];
NSString *formattedDateString = [dateFormatter stringFromDate:date];
NSString *msg = [[NSString alloc] initWithFormat:#"%#%# %#%#%# \n",fileCurrent,formattedDateString,xax.text,yax.text,zax.text];
//Convert NSstring to NSData
NSData* data=[msg dataUsingEncoding: [NSString defaultCStringEncoding]];
//bool fileCreationSuccess = [fileManager createFileAtPath:fileName contents:data attributes:nil];
[fileManager createFileAtPath:fileName contents:data attributes:nil];
[msg release];
[dateFormatter release];
[fileCurrent release];
[txtFileName release];
}
}
I get the warning level 1 and level 2. Is there a way I can release the NSFileManager memory to prevent this from locking up?
Your handler method to collect accelerometer data seems not very performant. You are allocating the resources (memory, file) everytime which can take a long time.
You should allocate the needed resources only once (i.e. use dispatch_once) and keep the file open. Use a NSFileHandle (method fileHandleForWritingAtPath) in order to append the data at the end of the file.
Furthermore NSHomeDirectory() is not where you're supposed to save user data, as iOS apps are sandboxed.
Either use NSTemporaryDirectory() or write in the Documents or Library Folder. The following is from Apple's sample code, usually in application delegate class:
- (NSString *)applicationDocumentsDirectory {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}
You can try using an Autorelease Pool.

Resources