Getting wrong available memory of ipad? - iphone

I am getting available memory from below method:
static void print_free_memory () {
float totalSpace = 0.0f;
NSError *error = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error: &error];
if (dictionary) {
NSNumber *fileSystemSizeInBytes = [dictionary objectForKey: NSFileSystemSize];
totalSpace = [fileSystemSizeInBytes floatValue];
NSLog(#"Total memory:%f",totalSpace);
freeMemAvailable = [[dictionary objectForKey:NSFileSystemFreeSize] floatValue];
NSLog(#"Free Memory:%f",freeMemAvailable);
} else {
NSLog(#"Error Obtaining File System Info: Domain = %#, Code = %#", [error domain], [error code]);
}
}
Above method returns = 9139.650391 mb ~ 9.14 GB
AND on Device memory displayed on the Device = 8.4 GB
Approximately, 700 MB difference. Why is it so? Any suggestions.
The path that I used to view the device memory on device is as follows.
Go to :- Settings -> General -> About -> Available

Your calculations are not precise the function return the size in bytes so assume the returned value was 9139650391 you will need to divide it bu (1024*1024*1024) = 1073741824
so 9139650391/1073741824 equals approximately 8.5 GB and not 9.14 GB
about the 100 MB difference, there is still a difference but not as big as 700MB

Related

Issue With selecting multiple images

How to detect total available/free disk space on the iPhone/iPad device?
I assume that clicking that "done" button would invoke cancelling the picker; in which case you can try did you try implementing the delegate method:
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[self dismissViewControllerAnimated:YES completion:^(void) {
NSLog(#"Cancelled pick");
};
}
Also it looks like you're calling release -- any reason you're not using ARC?
If I had to guess, I'd say perhaps the alert dismiss is in fact calling something like
[imagePicker.delegate imagePickerControllerDidCancel:imagePicker];
but it's already released so you're seeing this "lock-up" issue. Maybe step through in the debugger and make sure those objects still exist.
Edit:
While it doesn't solve your original issue, you could do a check for available space prior to launching the image picker, possibly with something like this so post suggests:
- (uint64_t)freeDiskspace
{
uint64_t totalSpace = 0;
uint64_t totalFreeSpace = 0;
__autoreleasing NSError *error = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error: &error];
if (dictionary) {
NSNumber *fileSystemSizeInBytes = [dictionary objectForKey: NSFileSystemSize];
NSNumber *freeFileSystemSizeInBytes = [dictionary objectForKey:NSFileSystemFreeSize];
totalSpace = [fileSystemSizeInBytes unsignedLongLongValue];
totalFreeSpace = [freeFileSystemSizeInBytes unsignedLongLongValue];
NSLog(#"Memory Capacity of %llu MiB with %llu MiB Free memory available.", ((totalSpace/1024ll)/1024ll), ((totalFreeSpace/1024ll)/1024ll));
} else {
NSLog(#"Error Obtaining System Memory Info: Domain = %#, Code = %d", [error domain], [error code]);
}
return totalFreeSpace;
}

unable to omit #".DS_Store" file while fetching contents of Document Drectory

I am working on storing a list of audio files into my document directory and then fetching them.
It gives me a list of audio files along with this it gives me a file with name #".DS_Store". While fetching content I want to leave this file of documents directory.
Is there any way I can get rid of this while fetching the audio list other than removing this from array or apply a #".DS_Store" check.
What exactly is the reason for this.?
#pragma mark - Saving Audio in Document Directory
-(void)saveAudioinDocumentDirectory:(ASIHTTPRequest *)theRequest
{
/*save the Audio file in Document Directory */
NSFileManager *fileManager=[NSFileManager defaultManager];
NSLog(#"GOT THE SIZe OF AUDIO %d",[[theRequest responseData] length]);
NSLog(#"AUDIO ID IS %#",[[theRequest userInfo] valueForKey:#"audioIndex"]);
/*Get the Path to Application Documents Directory*/
NSArray *docDir=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
/*append the neccessary file extension */
NSString *filepathStr=[NSString stringWithFormat:#"/%#/%#.mp3",docDir,[NSString stringWithFormat:#"%#",[[theRequest userInfo] valueForKey:#"audioIndex"]]];
/*Check if my crrent file exists in the Documents Directory*/
if(![fileManager fileExistsAtPath:filepathStr])
{
/* file doesnt exists */
/*create a NSdata of File*/
NSData *data=[NSData dataWithData:[theRequest responseData]];
NSLog(#"%#",filepathStr);
if ([data length] >0 ){
/*write the File at the Location in Documents Directory */
[data writeToFile:filepathStr atomically:YES];
NSLog(#"Successfully saved the file to %#", filepathStr);
}
else if([data length] == 0)
{
NSLog(#"Nothing was downloaded.");
}
}
/*After saving fetch the path til documents Directory*/
NSArray *folders = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
/*Get the Path for Files */
NSString *s=[folders objectAtIndex:0];
/*Fetch the list of Files stored in Documents Directory*/
NSArray *contents = [fileManager contentsOfDirectoryAtPath:s error:NULL];
NSLog(#"TOTAL NUMBER OF AUDIO FILES %d %#",[contents count],[contents objectAtIndex:0]);
if([Audiolistforstr isEqualToString:#"AudioListForIntro"])
{
// NSLog(#"Audiolistforstr#"IntroThirdRow" in reading audio from document Intro IS %#",Audiolistforstr);
/*Intro*/
[AudioListArrForIntro removeAllObjects];
[AudioListArrForIntro addObjectsFromArray:contents];
if([AudioListArrForIntro containsObject:#".DS_Store"])
{
[AudioListArrForIntro removeObject:#".DS_Store"];
}
NSLog(#"FINAL LIST %#",AudioListArrForIntro);
}
else if([Audiolistforstr isEqualToString:#"AudioListForCredits"])
{
// NSLog(#"Audiolistforstr#"IntroThirdRow" in reading audio from document credit IS %#",Audiolistforstr);
/*credits*/
[AudioListArrForCredits removeAllObjects];
[AudioListArrForCredits addObjectsFromArray:contents];
if([AudioListArrForCredits containsObject:#".DS_Store"])
{
[AudioListArrForCredits removeObject:#".DS_Store"];
}
NSLog(#"FINAL LIST %#",AudioListArrForCredits);
}
/* Did we find anything? */
if([Audiolistforstr isEqualToString:#"AudioListForIntro"])
{
// NSLog(#"Audiolistforstr#"IntroThirdRow" in reading audio fromRELOADNG TABLE Intro IS %#",Audiolistforstr);
/*Intro*/
if ([AudioListArrForIntro count] == 0)
{
}
else
{
UIView *vw=(UIView *)[self.view viewWithTag:ViewAddAudioIntroTag];
[(UITableView *)[vw viewWithTag:tblIntroAudioListTag] reloadData];
}
}
else if([Audiolistforstr isEqualToString:#"AudioListForCredits"])
{
// NSLog(#"Audiolistforstr#"IntroThirdRow" in reading audio fromRELOADNG TABLE Intro IS %#",Audiolistforstr);
/*Credits*/
if ([AudioListArrForCredits count] == 0)
{
}
else
{
/*AudioListForCredits*/
UIView *vw=(UIView *)[self.view viewWithTag:ViewAddAudioCreditsTag];
[(UITableView *)[vw viewWithTag:tblCreditsAudioListTag] reloadData];
}
}
}
Any help would be appreciated.
Thanks
Vikas
You can check for .DS_Store after NSArray *docDir=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; line........that is,
NSMutableArray * dirContents = [[NSMutableArray alloc] initWithArray:docDir];
if([docDir containsObject:#".DS_Store"])
{
[dirContents removeObject:#".DS_Store"];
}
By this, dirContents removes the entry of .DS_Store.
Filter your document directory contents. For example, if you are having audio files with extension of .mp3, then you can get all the mp3 files as below:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSArray *directoryContent = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:NULL];
directoryContent = [directoryContent filteredArrayUsingPredicate:
[NSPredicate predicateWithFormat:#"pathExtension ==[c] %#", #"mp3"]];
This will omit all other files than the mp3 files..
All the best!!!
The API you're using:
NSArray *contents = [fileManager contentsOfDirectoryAtPath:s error:NULL];
returns all files found at the path, which would include the ".DS_Store" file.
I'd recommend assigning "contents" to a mutable array, e.g.:
NSMutableArray * contents =
[[NSMutableArray alloc] initWithArray: [fileManager contentsOfDirectoryAtPath:s error:NULL]];`
and iterate through the array to find and removing any and all files that don't have ".mp3" as a path extension.
I'd also recommend not starting any variable with an upper case letter (e.g. instead of "Audiolistforstr", use "audiolistforstr" or even better, "arrayofAudioFiles"). Objective C best practice is to start all variables and methods with lower case letters.
Its Working well..
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSFileManager *manager = [NSFileManager defaultManager];
NSArray *imageFilenames = [manager contentsOfDirectoryAtPath:documentsDirectory error:nil];
for (int i = 0; i < [imageFilenames count]; i++)
{
NSString *imageName = [NSString stringWithFormat:#"%#/%#",documentsDirectory,[imageFilenames objectAtIndex:i] ];
if (![[imageFilenames objectAtIndex:i]isEqualToString:#".DS_Store"])
{
UIImage *myimage = [UIImage imageWithContentsOfFile:imageName];
UIImageView *imageView = [[UIImageView alloc] initWithImage:_myimage];
}
}

Got wrong value while detecting available disk space on iphone

I follow http://kdbdallas.com/2008/12/27/maciphone-show-availble-useable-diskspace/
and how do i find out iphone Disk Space?
to detect the available disk space. However, seem that the result is not correct
I tested on iphone 4 ios 4.2.1.
in Setting,
Capacity is 29.1 G
Availability is 24.2 G
I want to get 24.2 G value. So I followed the tutorial I mentioned above.
int main(int argc, char *argv[]) {
.....
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSLog(#"path %#", paths);
struct statfs tStats;
statfs([[paths lastObject] UTF8String], &tStats);
NSString *sizeType;
float total_space = (float)(tStats.f_blocks * tStats.f_bsize);
NSLog(#"total space: %f", total_space);
NSLog(#"total space: %#", convertUnit(total_space));
float free_space = (float)(tStats.f_bfree * tStats.f_bsize);
NSLog(#"free space: %f", free_space);
NSLog(#"free space: %#", convertUnit(free_space));
float free_space2 = (float)(tStats.f_bavail * tStats.f_bsize);
NSLog(#"free blocks avail to non-superuser: %f", free_space2);
NSLog(#"free blocks avail to non-superuser: %#", convertUnit(free_space2));
uint32_t block_size = (tStats.f_bsize);
NSLog(#"block size: %d", block_size);
NSLog(#"block size: %#", convertUnit(block_size));
.....
}
NSString* convertUnit (float value) {
NSString *sizeType;
if (value > 1024)
{
//Kilobytes
value = value / 1024;
sizeType = #" KB";
}
if (value > 1024)
{
//Megabytes
value = value / 1024;
sizeType = #" MB";
}
if (value > 1024)
{
//Gigabytes
value = value / 1024;
sizeType = #" GB";
}
return [[#"Available Disk Space: " stringByAppendingFormat:#"%.2f", value] stringByAppendingString:sizeType];
}
RESULT:
total space: 17363854862722269184.000000
total space: Available Disk Space: 16171350016.00 GB
free space: 17743592094095638528.000000
free space: Available Disk Space: 16525007872.00 GB
free blocks avail to non-superuser: 17432956969504735232.00000
free blocks avail to non-superuser: Available Disk Space: 16235706368.00 GB
block size: 803203484
block size: Available Disk Space: 765.99 MB
After do more search about file system of iphone, I found that iphone has 2 partitions: one for os and another for user data. The values I got is the attributes of OS partitions. So I changed the path to be 'private/var' which is the path of data partition. As a result, I got the correct value for free disk space.
Try this code
-(uint64_t)getFreeDiskspace {
uint64_t totalSpace = 0;
uint64_t totalFreeSpace = 0;
NSError *error = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error: &error];
if (dictionary) {
NSNumber *fileSystemSizeInBytes = [dictionary objectForKey: NSFileSystemSize];
NSNumber *freeFileSystemSizeInBytes = [dictionary objectForKey:NSFileSystemFreeSize];
totalSpace = [fileSystemSizeInBytes unsignedLongLongValue];
totalFreeSpace = [freeFileSystemSizeInBytes unsignedLongLongValue];
NSLog(#"Memory Capacity of %llu MiB with %llu MiB Free memory available.", ((totalSpace/1024ll)/1024ll), ((totalFreeSpace/1024ll)/1024ll));
} else {
NSLog(#"Error Obtaining System Memory Info: Domain = %#, Code = %#", [error domain], [error code]);
}
return ((totalFreeSpace/1024ll)/1024ll);
}
This will give you total free Space in MB

Problem with CGImageDestination and file naming

I am capturing images from the camera, using AVCapture as I have need of speed and the standard kit stuff is way too slow.
I have problem whereby the file that is being output (an animated GIF) is having it's file name mangles by the CGImageDestination functions...
When I output the NSURL (cast to a CFURLRef) to the log I get the path/filename I intended:
2011-09-04 20:40:25.914 Mover[3558:707] Path as string:.../Documents/91B2C5E8-F925-47F3-B539-15185F640828-3558-000003327A227485.gif
However, once the file is created and saved it actually lists the filename as this:
2011-09-04 20:40:25.960 Mover[3558:707] file: .91B2C5E8-F925-47F3-B539-15185F640828-3558-000003327A227485.gif-TtNT
See the difference? the period at the start and the 4 character suffix?
Whats really wierd is that it doesn't always do it, about 40% of the time it works OK. However it's preventing the code working further down the line where I'm listing them with previews in a table view.
Does anyone know why and how to stop it doing this?
Here's the code:
- (void)exportAnimatedGif{
NSString *guidPath = [[NSProcessInfo processInfo] globallyUniqueString];
NSString *tmpPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:guidPath];
NSString *path = [tmpPath stringByAppendingPathExtension:#"gif"];
NSLog(#"Path as string:%#", path);
CGImageDestinationRef destination = CGImageDestinationCreateWithURL((CFURLRef)[NSURL fileURLWithPath:path], kUTTypeGIF, [captureArray count], NULL);
NSDictionary *frameProperties = [NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:testDisplay3.displayValue] forKey:(NSString *)kCGImagePropertyGIFDelayTime]
forKey:(NSString *)kCGImagePropertyGIFDictionary];
NSDictionary *gifProperties = [NSDictionary dictionaryWithObject:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:2], (NSString *)kCGImagePropertyGIFLoopCount,
[NSNumber numberWithFloat:testDisplay3.displayValue], (NSString*)kCGImagePropertyGIFDelayTime,
[NSNumber numberWithFloat:testDisplay3.displayValue], (NSString*)kCGImagePropertyGIFUnclampedDelayTime,
nil]
forKey:(NSString *)kCGImagePropertyGIFDictionary];
for (int ii = 0; ii < [captureArray count]; ii++)
{
UIImage *tmpImg = [[UIImage alloc] init];
tmpImg = [captureArray objectAtIndex:ii];
CGImageDestinationAddImage(destination, tmpImg.CGImage, (CFDictionaryRef)frameProperties);
}
CGImageDestinationSetProperties(destination, (CFDictionaryRef)gifProperties);
CGImageDestinationFinalize(destination);
CFRelease(destination);
//TEST OUTPUT GENERATED FILES
NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] error:nil];
for (int xx = 0; xx < [contents count]; xx++)
{
NSLog(#"file: %#", [contents objectAtIndex:xx]);
}
//END TEST CODE
[captureArray removeAllObjects];
}
AFAIK this is a temporary file that CGImageDestinationFinalize makes, the reason you see them is that CGImageDestinationFinalize failed. I think that if you check the file sizes you'll see that the ones with mangled names have a file size of 0.
I started check for succes after I got these files :)
bool success = CGImageDestinationFinalize(destination);
CFRelease(destination);
if (success) {
NSLog(#"animated GIF file created at %#", path);
} else {
NSLog(#"failed to create gif at %#", path);
}

Writing an NSMutableArray to my documents directory fails

I am attempting to cache a web request. Basically I have an app that uses a facebook user's friend list but I don't want to grab it every single time they log in. Maybe refresh once per month. Caching the friend list in a plist in the documents directory seems to make sense for this functionality. I do this as follows:
- (void)writeToDisk {
NSLog(#"writing cache to disk, where cache = %#", cache);
BOOL res = [cache writeToFile:[FriendCache persistentPath] atomically:YES];
NSLog(#"reading cache from disk immediately after writing, res = %d", res);
NSMutableArray *temp = [[NSMutableArray alloc] initWithContentsOfFile:[FriendCache persistentPath]];
NSLog(#"cache read in = %#", temp);
}
+ (NSString *)persistentPath {
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:#"FriendCache.plist"];
}
These are members of a FriendCache singleton I am using which basically wraps an NSMutableArray. I have verified that the peristentPath method is returning a valid path. As you you can see in the writeToDisk method, I verify there is data in the cache and then I print the result of the write and check if any data could be read back in. There is never data read back in, because the result of the file write is 0.
The output of the cache print is very long, but here is the abbreviated version:
2010-12-28 13:35:23.006 AppName[51607:207] writing cache to disk, where cache = (
{
birthday = "<null>";
name = "Some Name1";
pic = "http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs1324.snc4/7846385648654.jpg";
"pic_big" = "http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs442.snc4/784365789465746.jpg";
"pic_square" = "http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs1324.snc4/7846357896547.jpg";
sex = female;
status = "<null>";
uid = 892374897165;
},
{
birthday = "<null>";
name = "Some Name2";
pic = "http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs625.ash1/54636536547_s.jpg";
"pic_big" = "http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs170.ash2/65465656365666_n.jpg";
"pic_square" = "http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs625.ash1/654635656547_q.jpg";
sex = female;
status = "<null>";
uid = 7658436;
},
...
One thing I checked out is when using writeToFile, I must make sure the object I am writing has valid plist objects. I did check this and here is how I construct the cache object:
- (void)request:(FBRequest*)request didLoad:(id)result{
NSMutableArray *friendsInfo = [[[NSMutableArray alloc] init] autorelease];
for (NSDictionary *info in result) {
NSString *friend_id = [NSString stringWithString:[[info objectForKey:#"uid"] stringValue]];
NSString *friend_name = nil;
NSString *friend_sex = nil;
NSString *friend_relationship_status = nil;
NSString *friend_current_location = nil;
if ([info objectForKey:#"name"] != [NSNull null]) {
friend_name = [NSString stringWithString:[info objectForKey:#"name"]];
}
if ([info objectForKey:#"relationship_status"] != [NSNull null]) {
friend_relationship_status = [NSString stringWithString:[info objectForKey:#"relationship_status"]];
}
if ([info objectForKey:#"sex"] != [NSNull null]) {
friend_sex = [NSString stringWithString:[info objectForKey:#"sex"]];
}
if ([info objectForKey:#"current_location"] != [NSNull null]) {
friend_current_location = [[info objectForKey:#"current_location"] objectForKey:#"name"];
}
NSString *friend_pic_square = [info objectForKey:#"pic_square"];
NSString *friend_status = [info objectForKey:#"status"];
NSString *friend_pic = [info objectForKey:#"pic"];
NSString *friend_pic_big = [info objectForKey:#"pic_big"];
NSString *friend_birthday = [info objectForKey:#"birthday"];
NSDictionary *friend_info = [NSDictionary dictionaryWithObjectsAndKeys:
friend_id,#"uid",
friend_name, #"name",
friend_pic_square, #"pic_square",
friend_status, #"status",
friend_sex, #"sex",
friend_pic, #"pic",
friend_pic_big, #"pic_big",
friend_birthday, #"birthday",
friend_relationship_status, #"relationship_status",
friend_current_location, #"current_location",
nil];
// If the friend qualifies as a single of your gender, add to the friend cache
if ( [AppHelpers friendQualifies:friend_info] == YES) {
[[FriendCache sharedInstance] push:friend_info];
}
}
[[FriendCache sharedInstance] writeToDisk];
}
My push method just wraps the NSMutableArray push:
- (void)push:(id)o {
[cache addObject:o];
}
Can you think of any reason why the write would fail?
Thanks!
So as we already pointed out, it's because of the usage of the NSNull objects.
The best way to avoid this is to create an object Friend, with all of the needed properties. Then you can easily set nil values, something not possible with NSDictionary objects (well, you'd have to remove the key, which is not very good practice).
Then, by implementing the NSCoding protocol, you can easily archive (serialize) your custom object.
This is a much better way of handling your data, and it will become MUCH easier in the future. You'll be able to call messages on the Friend objects, something not possible with NSDictionary.
Use NSError-aware API for NSPropertyListSerialization to get the data and the NSData NSError aware write API so you get a meaningful error helping you understand what your problem might be.