问题
How to get the total memory size in bytes of data present in core data store.And How to get the memory size for particular rows of data.
回答1:
On iOS 7 and above, older answers don't work anymore for SQLite-backed persistent stores, because of SQLite journal files. For each persistent store file you need to get the size of the SQLite file itself (e.g. Foo.sqlite
) and the sizes of the journal files (e.g. Foo.sqlite-wal
and Foo.sqlite-shm
) and add the sizes to get the total. This is really important because it's very likely that most of the data is actually in the journal files. You can use NSFileManager
to get this information for each file.
If you're using binary attributes in your model and you have "Allows External Storage" enabled for any of those attributes, it gets more complicated. In that case you need to find all of the external storage files and add up their sizes too. Their location is not documented but should be in a subdirectory of the directory where the SQLite file is found. For a SQLite file named Foo.sqlite
look for a directory named .Foo_SUPPORT/_EXTERNAL_DATA
, and the external binary files will be there. Since this is not documented, it may be subject to change without warning.
A better approach-- if it's not too late-- is to put the persistent store in its own subdirectory. Instead of putting it in the documents directory, create a new directory inside documents and put your SQLite file there. That is, create a directory called something like data
and put Foo.sqlite
in it. To add up the size, just recursively scan every file in data
and add up the sizes. Then you'll catch everything, even if journaling or external binaries or whatever change in future versions of iOS. A good way to do the scan would be with NSFileManager
's enumeratorAtPath:
or enumeratorAtURL:includingPropertiesForKeys:options:errorHandler:
methods.
Finding the memory size for a particular row of data is a very different question, and there's no general solution. There's the overhead of any object instance, plus your attributes, plus any internal undocumented objects NSManagedObject
might create (including instance vars and dynamically allocated memory). It's not even a fixed value since data can be allocated and released on the fly. Adding up the sizes of just your attributes is easy-- just run through them and add up the size of each (string length, data length, etc), but it's not the full picture.
回答2:
Using Swift 5, I came up with this answer. It not only gets the size of the store and files, but also formats the data size using Apples ByteCountFormatter.
public func getSqliteStoreSize(forPersistentContainerUrl storeUrl: URL) -> String {
do {
let size = try Data(contentsOf: storeUrl)
if size.count < 1 {
print("Size could not be determined.")
return ""
}
let bcf = ByteCountFormatter()
bcf.allowedUnits = [.useMB] // optional: restricts the units to MB only
bcf.countStyle = .file
let string = bcf.string(fromByteCount: Int64(size.count))
print(string)
return string
} catch {
print("Failed to get size of store: \(error)")
return ""
}
}
To use is as simple as:
// Get Core Data storage size:
guard let storeUrl = self.managedObjectContext!.persistentStoreCoordinator!.persistentStores.first?.url else {
print("There is no store url")
return
}
print("The size of the store is: \(self.getSqliteStoreSize(forPersistentContainerUrl: storeUrl))")
One minor detail here is to ensure you check that your moc
and persistentStoreCoordinator
actually have value - in my case I know that they do because of how I have initialised them.
Regarding the answer above that takes into account the wal
and shm
files, you can check these by appending a string to the URL:
let newFileName = storeUrl.absoluteString.appending("\("-wal")")
let newFileName2 = storeUrl.absoluteString.appending("\("-shm")")
print("The size of the wal is: \(self.getSqliteStoreSize(forPersistentContainerUrl: URL(string: newFileName)!))")
print("The size of the shm is: \(self.getSqliteStoreSize(forPersistentContainerUrl: URL(string: newFileName2)!))")
回答3:
- (void)reportFileSizeOfPersistentStores
{
NSArray *allStores = self.persistentStoreCoordinator.persistentStores;
NSFileManager *fileManager = [NSFileManager defaultManager];
for (NSPersistentStore *store in allStores)
{
NSString *filePath = store.URL.path;
NSDictionary *attributes = [fileManager attributesOfItemAtPath:filePath
error:nil];
NSString *fileSize = attributes[NSFileSize];
NSLog(@"FileSize:%@", fileSize);
}
}
来源:https://stackoverflow.com/questions/24178776/how-to-get-the-size-of-data-present-in-coredata-store