For the first question, the code below would work. But I don't know if this method conforms Apple's API usage.
// Get block size on user partition.
struct statfs *mntbufp = NULL;
getmntinfo(&mntbufp, 0);
int i, count = 0;
unsigned int blockSize;
count = getmntinfo(&mntbufp, 0);
for (i = 0; i < count; ++i)
{
// Find users partition.
if (strcmp(mntbufp[i].f_mntonname, "/private/var") == 0) {
blockSize = mntbufp[i].f_bsize;
break;
}
}
//get full pathname of bundle directory
NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
//get paths of all of the contained subdirectories
NSArray *bundleArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:bundlePath error:nil];
//to access each object in array
NSEnumerator *filesEnumerator = [bundleArray objectEnumerator];
NSString *fileName;
unsigned long long int fileSize = 0;
unsigned long long int filesSize = 0;
unsigned long long int sizeOnDisk = 0;
NSError *error = nil;
//return next object from enumerator
while (fileName = [filesEnumerator nextObject]) {
NSDictionary *fileDictionary = [[NSFileManager defaultManager] attributesOfItemAtPath:[bundlePath stringByAppendingPathComponent:fileName] error:&error];
fileSize = [fileDictionary fileSize];
// File size is sum of all file sizes.
filesSize += fileSize;
// Calculate size on disk.
sizeOnDisk += ceil((double)fileSize / blockSize) * blockSize;
}
// Find sandbox path.
NSString *sandboxPath = NSHomeDirectory();
NSArray *sandboxArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:sandboxPath error:nil];
filesEnumerator = [sandboxArray objectEnumerator];
while (fileName = [filesEnumerator nextObject]) {
NSDictionary *fileDictionary = [[NSFileManager defaultManager] attributesOfItemAtPath:[sandboxPath stringByAppendingPathComponent:fileName] error:&error];
fileSize = [fileDictionary fileSize];
filesSize += fileSize;
sizeOnDisk += ceil((double)fileSize / blockSize) * blockSize;
}
//converts a byte count value into a textual representation that is formatted with the appropriate byte modifier (KB, MB, GB and so on)
NSString *fileSizeStr = [NSByteCountFormatter stringFromByteCount:filesSize countStyle:NSByteCountFormatterCountStyleBinary];
NSString *sizeOnDiskStr = [NSByteCountFormatter stringFromByteCount:sizeOnDisk countStyle:NSByteCountFormatterCountStyleBinary];`
This calculates the size of the whole bundle. Part of the credit goes to 1218GG in this stackoverflow question. But his method does not count in binary format (iOS uses binary system; Mac OS 10.6 and later uses base 10 system. See this article), and does not count in size of sandbox files. I've modified/added the corresponding code.
Here is comparison between file size iOS app calculates and the one Mac finder displays (Finder Display vs. App Calculation):
61,801 B vs. 61 KB; 668 KB (637,472 B) vs. 623 KB; 13.5 MB (13,520,085 B) vs. 13.4 MB
There are some variations. May due to the difference between how Mac OS calculates file size and iOS calculates the file size. On iPhone runnig iOS 9, system shows 204 KB, while my method counts 208 KB. When app size is larger than 10 MB, the variation could be ignored.