Core Data is a great choice for storing and querying data in iOS and OSX applications. Not only can it reduce memory usage and improve performance, but it can also save you from writing a lot of unnecessary boilerplate code. In addition, the Core Data API is very flexible and can be used in a variety of applications, all of which have different data storage needs. However, this flexibility means that Core Data can sometimes be a little difficult to use. Even if you’re a Core Data expert, there are still common tasks you need to handle, and there are still many opportunities for mistakes. Fortunately, there are a lot of great tools out there to help you out and make Core Data easier to use. We’ve rounded up 10 tools and open source libraries you should know and love. Note: Even with all these great tools and libraries, you still need to have a good understanding of Core Data. If you need to get more experience with Core Data, download and check out our Getting Started Tutorial. Also note that this article is primarily written in Objective-C, since most of the Core Data library is written in Objective-C. If you want to learn how to use Core Data with Swift, you can download and check out our book Core Data by Tutorials, which has been completely updated for iOS 8 and Swift! #10. RestKit RestKit is an Objective-C framework for interacting with RESTful web services. It provides a Core Data entity mapping engine that maps serialized response objects directly to managed objects. The following code example shows how to set up RestKit to access the OpenWeatherMap API and map the JSON response from the /weather endpoint to a WFWeather managed object.
Code breakdown: 1. First, create an RKEntityMapping object to tell RestKit how to map the API response to the WFWeather attributes. 2. Here, RKResponseDescriptor links the above response from /data/2.5/weather to the RKEntityMapping instance. 3. RKManagedObjectRequestOperation defines the operation to be performed. In this example, you request the weather for Orlando from the OpenWeatherMap API and point the response to the RKResponseDescriptor instance mentioned above. 4. Finally, perform the operation with the required success and failure blocks. When RestKit sees a response back that matches the defined RKResponseDescriptor, it will map the data directly to the WFWeather instance. The above code requires no manual JSON parsing, checking for [NSNull null], manually creating Core Data entities, or anything else you have to do when connecting to an API. RestKit converts API responses into Core Data model objects with a simple mapping dictionary. It doesn’t get easier than this. To learn how to install and use RestKit, download and follow our RestKit Tutorial. #9. MMRecord MMRecord is a block-based integration library that uses Core Data model configuration to automatically create and populate complete object graphs from API responses. It makes generating local objects from web service requests as simple as possible while it creates, retrieves, and populates NSManagedObjects instances for you in the background. It makes generating local objects from web service requests as easy as it creates, retrieves, and populates NSManagedObjects instances in the background. The following code block shows how to use MMRecord to make the same Orlando weather call and data mapping that you did in the RestKit example above:
Without having to write any complex networking code, or manually parse JSON responses, you’ve called an API and populated a Core Data managed object with the response data in just a few lines of code. How does MMRecord know where to locate your object in the API response? Your managed object must be a subclass of MMRecord and then override keyPathForResponseObject as shown below:
keyPathForResponseObject returns a key path that specifies the location of the object relative to the root of the response object from the API. In this case, the key path is the main call to data/2.5/weather. The magic doesn't end there - MMRecord requires you to create a server class that knows how to make calls to the API you've integrated. Thankfully, MMRecord comes with an example server class based on AFNetworking. For information on configuring and using MMRecord, the documentation in the MMRecord Github repository is the best place to start. #8. Magical Record Inspired by Ruby on Rails' ActiveRecord system, it provides a set of classes and categories that support getting, inserting, and deleting a row of entities. The following is a view of MagicalRecord in action:
MagicalRecord makes it very easy to set up a Core Data stack. Instead of using many lines of boilerplate code, you can set up a complete Core Data stack with just one method call in your AppDelegate file as shown below.
In application:didFinishLaunchingWithOptions:, call setupCoreDataStackWithStoreNamed with the name of your SQLite file. This sets up instances of NSPersistentStoreCoordinator, NSManagedObjectModel, and NSManagedObjectContext so you’re ready to work with Core Data. For more information on how to install and use MagicalRecord, see our MagicalRecord Tutorial. #7. GDCoreDataConcurrencyDebugging Concurrency issues are the hardest thing to debug in Core Data. The performBlock API can help, but it’s still easy to make mistakes. You can add the open source project GDCoreDataConcurrencyDebugging to your own projects, which will alert you through console messages when NSManagedObjects are accessed on the wrong thread or dispatch queue. The following is an example of accessing an NSManagedObject instance in the wrong context:
In the above code, you are trying to read name from an object in context2, which was originally created in context1. If you run the above example using GDCoreDataConcurrencyDebugging, you will see the following console message informing you that a problem has occurred: 2014-06-17 13:20:24.530 SampleApp[24222:60b] CoreData concurrency failure Note: When uploading your app to the App Store, you should remove GDCoreDataConcurrencyDebugging, which adds a small amount of overhead that doesn’t need to be present in the released app. In iOS 8 and OS X Yosemite, Core Data now has the ability to detect concurrency issues. To enable this new feature, you can pass -com.apple.CoreData.ConcurrencyDebug 1 to your app at launch through Xcode’s Scheme Editor. However, until you phase out support for earlier OS versions, GDCoreDataConcurrencyDebugging will keep you informed of concurrency issues during development. The GDCoreDataConcurrencyDebugging README on Github is the best resource for installing and using this tool. #6. CoreData-hs CoreData-hs generates class methods to perform common fetch requests for all entities and attributes in your Core Data model. Creating these methods is not difficult, but it is time-consuming—and every bit of time saved when coding is valuable! For example, if your weather app has a view for viewing the weather forecast and uses a WFForecast entity with timeStamp, temp and summary properties to simulate a daily forecast, CoreData-hs will create the following classes for you:
#p# As you can see, a lot of methods were generated! Here is the generated implementation of tempIsGreaterThan:inContext:sortDescriptors: error: :
Once the methods are generated, you can use them to get requests based on specific conditions. For example, to get all WFForecast objects with a temperature greater than 70°, you can call tempIsGreaterThan:inContext:sortDescriptors:error: and simply pass the target temperature, as shown below:
You will get back a matching object with the data. CoreData-hs is a lightweight tool that can save you time if you tend to generate a lot of these types of requests manually. For installation and usage instructions, see the README on Github. #5. Core Data Editor You can view and edit your app's Core Data-based data model in the Core Data Editor GUI, which supports XML, binary, and SQLite persistence storage types. In addition to editing basic properties, you can also edit and visualize data relationships. You can also use the Mogenerator tool (discussed in item #2) to create model code while using the Core Data Editor. Core Data Editor follows Apple's pattern of displaying data without the Z prefix, which you might be familiar with if you've ever seen a SQL file generated by Core Data. You can browse the contents of your application's database in a nice tabular format. It also supports previewing binary data, such as images, and in-line editing of data with a standard date picker. If you want to create a seed file or just want to import data, Core Data Editor can generate a CSV file and convert it into a persistent object in Core Data, as shown below: To install Core Data Editor, download a free trial from the Thermal Core website. Unzip the downloaded ZIP archive and move the Core Data Editor.app file to your Applications directory. The author of this app recently made it open source, so you can check it out if you want to learn how it works and improve yourself. The first time you launch the app, it will walk you through a brief setup process. This process is optional, but it will speed things up if you at least specify the iPhone Simulator directory and the directory for your Xcode archive data. Note: Because you have to choose the exported data and simulator directories in the GUI, you may have problems using the OS X Lion default settings, which hide your Library folder. In Mavericks OS X, you can correct this by going to the Finder's home directory, selecting View / Show View Options and checking Show Library Folder. In Lion and Mountain Lion OS X, the same thing can be accomplished by typing chflags nohidden ~/Library/ in Terminal. More details about Core Data can be found on Thermal Core's website. #4. SQLite3 Sometimes when debugging a tricky data problem, it helps to execute SQL queries directly on the underlying Core Data SQLite database. If you don’t have extensive database experience, this may not be for you. To use SQLite3, first open Terminal and navigate to your app's Documents directory. Depending on your installation, the Documents directory will be something like ~/Library/Application Support/iPhone Simulator/7.1-64/Applications/{your app's ID}/Documents. Change the 7.1-64 in the naming above to match the version of the simulator you are using. {your app's ID} is automatically generated by Xcode and uniquely identifies an installation of your app. There is no easy way to find out which ID is yours. You can add logging when you create the Core Data stack, or you can look for the directory that has been modified most recently - this will be the app you are currently working on. The documents directory will contain a file with the extension sqlite. This is your application's database file. For applications using Apple's Core Data template, the file name should match the name of your application. Open this file with the SQLite3 program as shown below (the example application here is called AddressBook, your file name will be different):
You will see the following prompt in the console:
Now you are ready to execute standard SQL queries against the database. For example, to see the schema used by Core Data, execute the following command:
SQLite responds to your query with a list of text lists in the schema, like this:
All the Z prefixes in the list columns are part of the underlying SQLite used by Core Data. For the purpose of analysis, you can ignore them. Note: You cannot write directly to a SQLite Core Data database. Apple can modify the underlying structure at any time. If you really need to manipulate SQLite data directly in a production application, you should abandon Core Data and use raw SQL access. There are several popular frameworks that can help you manage the SQL implementation in your application, including FMDB and FCModel. If you are just analyzing data, it is okay to access the SQLite database file everywhere - as long as you do not modify its contents. An example of using SQL directly to analyze data is to group and calculate different attributes to understand the differences in the attributes. For example, if you have an address book application and want to know how many contacts live in each city, you can execute the following command at the SQLite3 prompt:
SQLite would respond with data for each of the different cities in the address book database, as shown in the following example:
To exit the SQLite3 terminal program, simply execute the following command:
To learn more about SQLite3, open a terminal to view the man page and execute the man sqlite3 command. #3. MDMCoreData MDMCoreData (disclaimer - I wrote this library!) is a collection of open source classes that make working with Core Data easier. It does not try to hide or abstract Core Data, but rather enforces best practices and reduces the amount of boilerplate code required. It is a much better alternative to the Xcode Core Data templates. MDMCoreData consists of the following four classes:
One of the best features of MDMCoreData is that it comes with a Core Data-backed table data source - so you don't have to worry about implementing it yourself. #p# Instead of implementing all the methods required by the UITableViewDataSource and NSFetchedResultsControllerDelegate protocols, you can just set the table data source of the MDMFetchedResultsTableDataSource instance. When instantiating the MDMFetchedResultsTableDataSource object, you simply pass in the table view and get a results controller:
MDMFetchedResultsTableDataSource has a delegate with two methods that must be implemented. One method configures the cells for your table:
The second method handles the deletion:
Implementing the two required MDMFetchedResultsTableDataSource methods is much simpler than implementing all the required methods of the table data source and obtaining the results controller protocols. You can find more information about MDMCoreData in the MDMCoreData Github repository. #2. Mogenerator Because Core Data fully supports key/value coding (KVC) and key/value observing (KVO), there is no need to implement a custom NSManagedObject class. You can use setValue:forKey: and setValue:forKey: when reading and writing entities to your classes. But this often becomes complicated and difficult to debug because strings cannot be checked for correctness at compile time. For example, if you have a Core Data entity called person, you can read and write properties like this:
The person object above is an NSManagedObject instance with a property called firstName. To read firstName, you use firstName as the valueForKey: keyword. Similarly, you can set the first name of a person object using setValue:forKey:. A better approach is to use standard accessor methods or dot syntax. However, to do this you must implement a custom subclass of NSManagedObject for your entity. You can add model logic such as fetch requests and validation. You may use Xcode's Create NSManagedObjectSubclass feature to quickly subclass a single entity. Although this is a shortcut, it adds extra overhead if your data model is large and can cause problems when changing the model. Re-subclassing means clearing out all your custom model logic - which means you should create logic outside of your custom models. It fits into the general pattern of creating custom subclasses with managed object properties and custom model logic classes. The command line tool Mogenerator automates these exact tasks. Two classes are generated for each Core Data entity. The first class is generated for machine consumption and is constantly overwritten when the model changes. The second class is generated for all your custom logic and is never overwritten. Mogenerator has a range of other benefits, including the following:
Mogenerator can be installed from the DMG file available on the Mogenerator website, or by installing Mogenerator via Homebrew, open a terminal and execute the following command:
Once installed, use the cd command to change to your application's directory, then run Mogenerator from the terminal, like this:
In the command above, you invoke Mogenerator with the -m option, followed by the location of the model. You can also specify the location of the generated classes with the -O option. When using ARC, you need to pass the --template-var arc=true option. You can have Xcode run Mogenerator by creating a Run Script Build Phase. Build Phases are descriptions of tasks that Xcode must perform during a build. To add a Build Phase, first select the target, select the Build Phases tab, and then select Editor / Add Build Phase / Add Run Script Build Phase from the menu. Add the following code to the Shell script text area under the new Run Script, making sure to modify the mogenerator parameters to suit your project: The above run script will make Xcode run Mogenerator every time you run a debug build command. If the model has not changed, Mogenerator will do nothing and then exit. Now that you have incorporated Mogenerator into your workflow for rapid subclassing, you should take advantage of its other features. For example, instead of unwrapping the raw values each time, you can just add the Value suffix to them, as shown in the following code snippet:
Because bools are stored as NSNumbers in Core Data, you must call boolValue on the person object before checking if the value is true. With Mogenerator, there is no extra step required because you can simply call isFriendValue. If Mogenerator looks like a useful addition to your toolbox, you can find out more about Mogenerator in its Github repository. #1. Instruments Instruments is the go-to tool for investigating nearly any performance and memory issue in OS X and iOS—including Core Data issues. The other tools on this list provide a lot of automation and convenience, but Instruments is usually the first stop for investigating any problem or performance tweak. The following figure shows the Time Profiler and Core Data templates, which are most useful for Core Data configuration. The default Core Data template adds the optional Faults Instrument feature to help you tune and monitor your app’s performance by providing the following capabilities:
This is a typical instruments profile for a Core Data application. You can see when fetch requests occur and how long they take, when and how save operations occur, and when the failure light appears. To get more information about Instruments, download our tutorial: How to Use Instruments in Xcode. Next step Core Data is a very powerful framework, but it will have a lot of development overhead, but the tools and libraries in this article provide some methods to help you solve the overhead problem efficiently and effectively. |
<<: Java Thread Interview Questions
>>: O2O companies face capital winter, 99% of angel investors face investment failure
Recently the tree has turned green again, and its...
Introduction to Wall Street Master-level Python Q...
35 fires in 6 days! Why are California wildfires ...
Recently, iFixit, a well-known foreign repair org...
Meiyijia Enterprise Account helps every store own...
As early as last year, many manufacturers had see...
In response to the phenomenon that posters are th...
Mini programs provide convenience for publicity a...
The overall investment promotion of Bengbu Tea Mi...
Recently, a personal safety accident occurred on ...
This article will start from the perspective of B...
In recent years, “Two Weibo and One Douyin” can b...
November 26, 1901, Frankfurt, Germany. A young cl...
Since being introduced into China in 2014, Jiangx...
As people's living standards continue to impr...