coredata学习总结(十四)

来源:互联网 发布:软件项目评审表模板 编辑:程序博客网 时间:2024/05/16 04:49

Persistent Store Types and Behaviors

core data提供了一种内存持久化存储和三种磁盘存储持久化存储的方式。

注意:xml存储在ios是不支持的

Table 16-1Built-in persistent store types

Store type

Speed

Object graph in memory

Other factors

XML (atomic)

Slow

Whole

Externally parsable

Binary (atomic)

Fast

Whole

N/A

SQLite

Fast

Partial

N/A

In-memory

Fast

Whole

No on-disk storage required

Important

尽管core data支持sqlite作为一种存储类型,存储形式-像其它的native core data存储-是私有的。你不能使用native sqlite api来创建sqlite数据库。也不能直接通过core data来使用这个数据库。你也不能对现存的core data sqlite 存储使用native sqlite api。如果你有一个现存的sqlite数据库,你需要把他import到core data存储。

Limitations of Persistent Store Security

core data对于来源于不信任元数据的持久化存储是没有保护机制的。并且也不能侦测是否文件被恶意修改。sqlite较为安全,但也不是绝对的。为了安全考虑,应该使用encrypted加密等方式。

Fetch Predicates and Sort Descriptors

支持的排序selectors包含compare:caseInsensitiveCompare:,localizedCompare:,localizedCaseInsensitiveCompare:,和localizedStandardCompare:.后者推荐使用。你不能对sqlite存储的临时属性进行排序。

There are additional constraints on the predicates you can use with the SQLite store:

  • You cannot necessarily translate arbitrary SQL queries into predicates.

  • You can have only one to-many element in a key path in a predicate.

    For example, no toOne.toMany.toMany, ortoMany.toOne.toMany type constructions (they evaluate to sets of sets) are allowed. As a consequence, in any predicate sent to the SQL store, there may be only one operator (and one instance of that operator) fromALL, ANY, and IN.

CoreData supports a noindex: that can be used to drop indices in queries passed to SQLite. This is done primarily for performance reasons: SQLite uses a limited number of indices per query, and noindex: allows the user to preferentially specify which indexes should not be used. See NSPredicate documentation regarding function expressions.

SQLite-Supported File Systems

To summarize: Byte-range locking file systems have the best concurrent read/write support; these include HFS+, AFP, and NFS. File systems with simple file locking are also supported, but do not allow for as much concurrent read/write access by multiple processes. Simple file locking systems include SMB and DOS. The SQLite store doesnot support writing to WebDAV file-systems.

SQLite File Size and Record Deletion

Simply deleting a record from a SQLite store does not necessarily result in a reduction in the size of the file. If enough items are removed to free up a page in the database file, SQLite’s automatic database vacuuming will reduce the size of the file as it rearranges the data to remove that page. Similarly, the file size is reduced if you remove an item that itself occupies multiple pages (such as a thumbnail image).

An SQLite file is organized as a collection of pages. The data within those pages is managed through B-trees, not as simple fixed-length records. This format is more efficient for searching and for overall storage, because it allows SQLite to optimize how it stores both data and indexes in a single file. This format is also the foundation of SQLite’s data integrity (transaction and journaling) mechanism. However, the cost of this design is that some delete operations may leave holes in the file and impact read and write performance. If you delete some data and add other data, the holes left by the deleted data may be filled by the added data, or the file may be vacuumed to compact its data, whichever SQLite considers most appropriate based on the operations you’re performing.

Configuring Save Behavior for a SQLite Store

When Core Data saves a SQLite store, SQLite updates just part of the store file. Loss of that partial update would be catastrophic, so ensure that the file is written correctly before your application continues. Unfortunately, doing partial file updates means that in some situations saving even a small set of changes to a SQLite store can take considerably longer than saving to, say, an XML store. For example, where saving to an XML file might take less than a hundredth of a second, saving to a SQLite store may take almost half a second. This data loss risk is not an issue for XML or binary stores. Because writes to these stores are typically atomic, it is less likely that data loss involves corruption of the file, and the old file is not deleted until the new has been successfully written.

Important

In OS X the fsync command does not guarantee that bytes are written, so SQLite sends aF_FULLFSYNC request to the kernel to ensure that the bytes are actually written through to the drive platter. This request causes the kernel to flush all buffers to the drives and causes the drives to flush their track caches. Without this, there is a significantly large window of time within which data will reside in volatile memory. If system failure occurs you risk data corruption.

Changing a Store’s Type and Location

You can migrate a store from one type or location to another (for example, for a Save As operation) using theNSPersistentStoreCoordinator methodmigratePersistentStore:toURL:options:withType:error:. After invocation of this method, the original store is removed from the coordinator; thus the persistent store is no longer a useful reference. The method is illustrated in the following code fragment, which shows how you can migrate a store from one location to another. If the old store type is XML, then the example also converts the store to SQLite.

  1. NSPersistentStoreCoordinator *psc = [[selfmanagedObjectContext] persistentStoreCoordinator];
  2. NSURL *oldURL= <#URLidentifying the locationof the currentstore#>;
  3. NSURL *newURL= <#URLidentifying the locationof the new store#>;
  4. NSError *error= nil;
  5. NSPersistentStore *xmlStore = [psc persistentStoreForURL:oldURL];
  6. NSPersistentStore *sqLiteStore = [psc migratePersistentStore:xmlStore
  7.     toURL:newURL
  8.     options:nil
  9.     withType:NSSQLiteStoreType
  10.     error:&error];
  1. guard letpsc = managedObjectContext.persistentStoreCoordinatorelse {
  2. fatalError("Failed to load persistent store")
  3. }
  4. let oldURL =NSURL(fileURLWithPath: "oldURL")
  5. let newURL =NSURL(fileURLWithPath: "newURL")
  6. guard letxmlStore = psc.persistentStoreForURL(oldURL)else {
  7. fatalError("Failed to reference old store")
  8. }
  9. do {
  10. try psc.migratePersistentStore(xmlStore,toURL: newURL, options:nil,withType:NSSQLiteStoreType)
  11. } catch {
  12. fatalError("Failed to migrate store:\(error)")
  13. }

To migrate a store, Core Data:

  1. Creates a temporary persistence stack.

  2. Mounts the old and new stores.

  3. Loads all objects from the old store.

  4. Migrates the objects to the new store.

    The objects are given temporary IDs, then assigned to the new store. The new store then saves the newly assigned objects (committing them to the external repository).

  5. Informs other stacks that the object IDs have changed (from the old to the new stores), which keeps the stack running after a migration.

  6. Unmounts the old store.

  7. Returns the new store.

An error can occur if:

  • You provide invalid parameters to the method

  • Core Data cannot add the new store

  • Core Data cannot remove the old store

In the latter two cases, you get the same errors that you would get if you calledaddPersistentStore: or removePersistentStore: directly. If an error occurs when the store is being added or removed, treat this as an exception, because the persistence stack is likely to be in an inconsistent state.

If a failure occurs during the migration itself, instead of an error you get an exception. In these cases, Core Data unwinds cleanly and there should be no repair work necessary. You can examine the exception description to determine what went wrong — possible errors range widely from "disk is full" and "permissions problems" to "The SQLite store became corrupted" and "Core Data does not support cross store relationships".

Associating Metadata with a Store

A store’s metadata provides additional information about the store that is not directly associated with any of the entities in the store.

The metadata is represented by a dictionary. Core Data automatically sets key-value pairs to indicate the store type and its UUID. You can create additional custom keys for your application, or provide a standard set of keys such askMDItemKeywords to support Spotlight indexing (if you also write a suitable importer).

Be careful about what information you put into metadata. Spotlight imposes a limit to the size of metadata and replicating an entire document in metadata is probably not useful. However, if you create a URL to identify a particular object in a store (using URIRepresentation), the URL may be useful to include as metadata.

Getting the Metadata

There are two ways to get the metadata for a store:

  • Given an instance of a persistent store, get its metadata using theNSPersistentStoreCoordinator instance methodmetadataForPersistentStore:.

  • Retrieve metadata from a store without the overhead of creating a persistence stack by using theNSPersistentStoreCoordinator class method,metadataForPersistentStoreOfType:URL:error:.

There is an important difference between these approaches. The instance method,metadataForPersistentStore:, returns the metadata as it currently is in your program, including any changes that may have been made since the store was last saved. The class method,metadataForPersistentStoreOfType:URL:error:, returns the metadata as it is currently represented in the store itself. If there are pending changes to the store, the returned value may therefore be out of sync.

Setting the Metadata

There are two ways you can set the metadata for a store:

  • Given an instance of a persistent store, set its metadata using theNSPersistentStoreCoordinator instance method,setMetadata:forPersistentStore:.

  • Set the metadata without the overhead of creating a persistence stack by using theNSPersistentStoreCoordinator class method,setMetadata:forPersistentStoreOfType:URL:error:.

There is again an important difference between these approaches. If you usesetMetadata:forPersistentStore:, you must save the store (through a managed object context) before the new metadata is saved. If you usesetMetadata:forPersistentStoreOfType:URL:error:, however, the metadata is updated immediately, and the last-modified date of the file is changed.

This difference has particular implications if you use NSPersistentDocument on OS X. If you update the metadata usingsetMetadata:forPersistentStoreOfType:URL:error: while you are actively working on the persistent store (that is, while there are unsaved changes), then when you save the document you will see a warning, “This document's file has been changed by another application since you opened or saved it.” To avoid this, you should instead usesetMetadata:forPersistentStore:. To find the document’s persistent store, you typically ask the persistent store coordinator for its persistent stores (persistentStores), and use the first item in the returned array to set the metadata. When you use setMetadata:forPersistentStoreOfType:URL:error: the action is treated as if the change occurred externally to your Core Data stack.

Because Core Data manages the values for NSStoreTypeKey andNSStoreUUIDKey in the same metadata, make a mutable copy of any existing metadata before setting your own keys and values, as illustrated in the following code fragment:

  1. NSURL *url= [NSURL fileURLWithPath:@"url to store"];
  2. NSPersistentStore *store = [self.managedObjectContext.persistentStoreCoordinatorpersistentStoreForURL:url];
  3. NSMutableDictionary *metadata = [[store metadata]mutableCopy];
  4. metadata[@"MyKeyWord"]= @"MyStoredValue";
  5. [storesetMetadata:metadata];
  1. let url =NSURL(fileURLWithPath: "url to store")
  2. guard letstore = managedObjectContext.persistentStoreCoordinator?.persistentStoreForURL(url)else {
  3. fatalError("Failed to retrieve store from\(url)")
  4. }
  5. var metadata =store.metadata
  6. metadata["MyKeyWord"] ="MyStoredValue"
  7. store.metadata =metadata
0 0
原创粉丝点击