I have a situation where lots of transactions have to uploaded to the server. I have made this job asynchronously using NSManagedObjectContext performBlock: method that performs block on the NSManagedObjectContext queue. So in the async-block how can I observe the low memory warning! Instead of observing I would like to determine if the device has enough free memory then only upload data. Otherwise if it has low-memory situation then wait till low-memory happens and then resume the upload job.
You can check free disk space of your iOS device before upload data to avoid low-memory situation.
+(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 = %ld", [error domain], (long)[error code]);
}
return totalFreeSpace;
}
Related
I've tried two implementations on iOS 12 to get the remaining free disk space.
"The Apple Way"
uint64_t get_disk_bytes_free()
{
uint64_t totalSpace = 0;
uint64_t totalFreeSpace = 0;
NSError *error = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, 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];
}
else
{
LOG_APP("Error Obtaining System Memory Info: Domain = %s, Code = %ld", [[error domain] UTF8String], (long)[error code]);
}
return totalFreeSpace;
}
"The Unix Way" - path is still the Library/Caches path.
struct statfs fs;
if(statfs(path.c_str(),&fs)==0)
{
if(out_total_space) *out_total_space = (xu64) fs.f_bsize * (xu64) fs.f_blocks;
if(out_free_space) *out_free_space = (xu64) fs.f_bsize * (xu64) fs.f_bfree ;
return err_code_ok;
}
The Apple Way returns 4GB free. The Unix Way returns about 10GB free. They both equally report 16GB total (which is correct) but this device has hardly NOTHING on it. Just a couple of apps.
If I go to iPhone Storage in the Settings to see, it shows 11.8GB of 16GB used....almost all of it is used by "System" at the very bottom (8.65GB).
This System usage seems to disappear if i reboot the device but it comes back eventually.
Can someone tell me if there's any good reason for the discrepancy between these two methods? Which one is more reliable/accurate?
In iOS 11, I am not able to get the correct free size of the device(disk space) from the Dictionary key NSFileSystemFreeSize. Instead giving 34.4 GB it gives 4 GB free space.
Below is the code I am using
pragma mark - Formatter
- (NSString *)memoryFormatter:(long long)diskSpace
{
NSString *formatted;
double bytes = 1.0 * diskSpace;
double megabytes = bytes / MB;
double gigabytes = bytes / GB;
if (gigabytes >= 1.0)
formatted = [NSString stringWithFormat:#"%.2f GB", gigabytes];
else if (megabytes >= 1.0)
formatted = [NSString stringWithFormat:#"%.2f MB", megabytes];
else
formatted = [NSString stringWithFormat:#"%.2f bytes", bytes];
return formatted;
}
#pragma mark - Methods
- (NSString *)totalDiskSpace {
long long space = [[[[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil] objectForKey:NSFileSystemSize] longLongValue];
return [self memoryFormatter:space];
}
- (NSString *)freeDiskSpace {
long long freeSpace = [[[[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil] objectForKey:NSFileSystemFreeSize] longLongValue];
return [self memoryFormatter:freeSpace];
}
- (NSString *)usedDiskSpace {
return [self memoryFormatter:[self usedDiskSpaceInBytes]];
}
- (CGFloat)totalDiskSpaceInBytes {
long long space = [[[[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil] objectForKey:NSFileSystemSize] longLongValue];
return space;
}
- (CGFloat)freeDiskSpaceInBytes {
long long freeSpace = [[[[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil] objectForKey:NSFileSystemFreeSize] longLongValue];
return freeSpace;
}
- (CGFloat)usedDiskSpaceInBytes {
long long usedSpace = [self totalDiskSpaceInBytes] - [self freeDiskSpaceInBytes];
return usedSpace;
}
OBJECTIVE C (converted)
- (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;
}
So if people have the problem of not getting the correct free size, use NSURL resourceValuesForKeys to get the free space.
[ fileURL resourceValuesForKeys:#[NSURLVolumeAvailableCapacityForImportantUsageKey ] error:&error];
double = availableSizeInBytes = [ results[NSURLVolumeAvailableCapacityForImportantUsageKey] doubleValue ];
Reference Why is `volumeAvailableCapacityForImportantUsage` zero?
Here's how I usually do it
func deviceRemainingFreeSpaceInBytes() -> Int64?
{
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last!
guard
let systemAttributes = try? FileManager.default.attributesOfFileSystem(forPath: documentDirectory),
let freeSize = systemAttributes[.systemFreeSize] as? NSNumber
else {
// handle failure
return nil
}
return freeSize.int64Value // this returns bytes - scales as required for MB / GB
}
SWIFT 4:
func getFreeDiskspace() -> UInt64
{
let totalSpace: UInt64 = 0
let totalFreeSpace: UInt64 = 0
var error: Error? = nil
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let dictionary = try? FileManager.default.attributesOfFileSystem(forPath: paths.last ?? "")
if dictionary
{
var fileSystemSizeInBytes = dictionary[.systemSize]
var freeFileSystemSizeInBytes = dictionary[.systemFreeSize]
totalSpace = fileSystemSizeInBytes as UInt64? ?? 0
totalFreeSpace = freeFileSystemSizeInBytes as UInt64? ?? 0
print("Memory Capacity of \((totalSpace / 1024) / 1024) MiB with \((totalFreeSpace / 1024) / 1024) MiB Free memory available.")
}
else
{
print("Error Obtaining System Memory Info: Domain = \((error as NSError?)?.domain), Code = \(Int(error.code))")
return totalFreeSpace
}
}
i am able to download audio files successfully.. i am able to get the device free space….but my requirement is before downloading file i want to check is there enough space on iPhone if yes then download and if not then user can see some alert message like “your device does not have enough memory space.”
plz guide me any body.. Thanks in advance.
- (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 = %ld", [error domain], (long)[error code]);
}
return totalFreeSpace;
}
You wouldn't download a 12.8MB audio file if you have 12.9MB free space. That's asking for trouble. Check for 100MB free space. Then check if an iPhone misbehaves or gives the user trouble with only 100MB free space, and increase the number if it does.
I am writing a small video that is only 100kb in size. My phone has about 20mb left on disk, but when I try create a recording using AVFoundation and AVCaptureMovieFileOutput, I get the error:
2014-06-15 10:40:19.511 wave[551:690b] ERROR:
Error Domain=AVFoundationErrorDomain
Code=-11807 "Operation Stopped" UserInfo=0x157cde20
{NSLocalizedRecoverySuggestion=There
is not enough available space to continue the file writing.
Make room by deleting existing videos or photos
I am setting the
self.movieFileOutput.minFreeDiskSpaceLimit = //space available in bytes
thinking it would override this default behavior, but it's not. Any idea how to continue allow for recording given the disk space parameters?
Update - here is the code I'm using to get free space:
-(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 = %#", error);
}
return totalFreeSpace;
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to get information about free memory and running processes in an App Store approved app? (Yes, there is one!)
How to get available memory in IOS ? I don't know..
I googled, then I know how can i get the physical memory, user memory and used mem, free mem in VM.
But. the memory size is different with which is Settings -> General -> About -> Avaliable.
I want to know "Avaliable" in Settings.
Have a nice day .
found this on here a few months back cant remember who originally posted. Is this what you are looking for?
- (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 = %#", [error domain], [error code]);
}
return totalFreeSpace;
}