<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Sealyu

    --- 博客已遷移至: http://www.sealyu.com/blog

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      618 隨筆 :: 87 文章 :: 225 評(píng)論 :: 0 Trackbacks

    Core Data Tutorial: How To Preload/Import Existing Data

    Failed Banks Preloaded Data with Core Data

    Failed Banks Preloaded Data with Core Data

    This is the second part of a three part series to help get you up to speed with the basics of Core Data quickly.

    In the first part of the series, we created a visual data model for our objects, ran a quick and dirty test to make sure it works, and hooked it up to a table view so we could see a list of our objects.

    In this part of the series, we’re going to discuss how to import or preload existing data into Core Data so that we have some good default data when our app starts up.

    In the final part of the series, we’re going to discuss how we can optimize our app by using NSFetchedResultsController, to reduce memory overhead and improve response time.

    Preloading / Importing Existing Data

    So how do we preload data into a Core Data store, anyway? Well, there are two popular solutions to this problem:

    • Fill in Core Data on startup from external source. For this the app can start up, notice that the database hasn’t been imported yet, and start reading in data from an external source (such as an SQLite database or XML file) and then start inserting the data into Core Data.
    • Provide pre-filled in SQLite database. For this we’ll let Core Data create the database structure for us based on the model, and then we populate the database with a utility app. The utility app could be a Mac or iPhone app that uses Core Data to populate the database via Core Data APIs, or some kind of program that fills in the SQLite database directly. Once the database is populated, just include it with the app and make the app use it as the default database if no database already exists.

    We’re going to go with option 2 because it’s simple and more efficient. To populate the database, we’ll just extend our Python script a bit since we have that working already.

    Note that by using a Python script to import the data rather than working with a utility app that uses Core Data APIs, it’s more likely to break in the future because we’re kind of going under the hood here… but for this tutorial I thought a) it’s a better learning experience since we just covered SQLite and it shows how things are working more clearly, and b) it is simpler!

    So, let’s grab a copy of the sqlite database that was generated by our project. The easiest way to find the file is to set a breakpoint inside the application delegate, inside the persistentStoreCoordinator function, below the storeUrl line. You can examine the storeUrl variable to see a full path to where the sqlite backing file resides. So find this and copy it to the directory your Python script is in.

    Once you have the database, use sqlite3 to take a peek at how the database looks:

    sqlite3 FailedBanksCD.sqlite
    sqlite3> .schema
    CREATE TABLE ZFAILEDBANKDETAILS ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER,
    Z_OPT INTEGER, ZZIP INTEGER, ZINFO INTEGER, ZUPDATEDDATE TIMESTAMP,
    ZCLOSEDATE TIMESTAMP );
    CREATE TABLE ZFAILEDBANKINFO ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER,
    Z_OPT INTEGER, ZDETAILS INTEGER, ZNAME VARCHAR, ZSTATE VARCHAR,
    ZCITY VARCHAR );
    CREATE TABLE Z_METADATA (Z_VERSION INTEGER PRIMARY KEY,
    Z_UUID VARCHAR(255), Z_PLIST BLOB);
    CREATE TABLE Z_PRIMARYKEY (Z_ENT INTEGER PRIMARY KEY, Z_NAME VARCHAR,
    Z_SUPER INTEGER, Z_MAX INTEGER);
    CREATE INDEX ZFAILEDBANKDETAILS_ZINFO_INDEX ON ZFAILEDBANKDETAILS (ZINFO);
    CREATE INDEX ZFAILEDBANKINFO_ZDETAILS_INDEX ON ZFAILEDBANKINFO (ZDETAILS);
    sqlite> select * from ZFAILEDBANKINFO;
    1|2|1|1|Test Bank|Testland|Testville
    2|2|1|2|Test Bank|Testland|Testville
    3|2|1|3|Test Bank|Testland|Testville
    sqlite> select * from ZFAILEDBANKDETAILS;
    1|1|1|12345|1|292794835.855615|292794835.679693
    2|1|1|12345|2|292794875.943392|292794875.768675
    3|1|1|12345|3|292795809.375025|292795809.215297
    sqlite> select * from Z_PRIMARYKEY;
    1|FailedBankDetails|0|3
    2|FailedBankInfo|0|3
    

    Here’s a quick description of what’s in here. Z_METADATA contains some information about the Model that Core Data needs to function. Z_PRIMARYKEY contains (among other things) information on the max key that is currently used by each entity.

    As for ZFAILEDBANKINFO and ZFAILEDBANKDETAILS, those are our main data tables! Z_PK is the unique id for each, Z_ENT is their entity id (same as what’s listed in the Z_PRIMARYKEY table), and finally there are our normal fields.

    Now, let’s create a Python script to populate this database by reading in the contents of our old database, and creating the appropriate rows in the new database. Create a Python script like the following:

    import sqlite3;
                from datetime import datetime, date;
                import time
                 
                inConn = sqlite3.connect('banklist.sqlite3')
                outConn = sqlite3.connect('FailedBanksCD.sqlite')
                 
                inCursor = inConn.cursor()
                outCursor = outConn.cursor()
                 
                outConn.execute("DELETE FROM ZFAILEDBANKINFO")
                outConn.execute("DELETE FROM ZFAILEDBANKDETAILS")
                 
                maxId = 0
                inCursor.execute("select * from failed_banks")
                for row in inCursor:
                closeDate = datetime.strptime(row[5], "%Y-%m-%d %H:%M:%S")
                updatedDate = datetime.strptime(row[6], "%Y-%m-%d %H:%M:%S")
                closeDateSecs = time.mktime(closeDate.timetuple())
                updatedDateSecs = time.mktime(updatedDate.timetuple())
                 
                # Convert time references secs to NSDate reference
                deltaSecs = time.mktime((2001, 1, 1, 0, 0, 0, 0, 0, 0))
                closeDateSecs = closeDateSecs - deltaSecs
                updatedDateSecs = updatedDateSecs - deltaSecs
                 
                if row[0] > maxId:
                maxId = row[0]
                 
                # Create ZFAILEDBANKINFO entry
                vals = []
                vals.append(row[0]) # Z_PK
                vals.append(2) # Z_ENT
                vals.append(1) # Z_OPT
                vals.append(row[0]) # ZDETAILS
                vals.append(row[1]) # ZNAME
                vals.append(row[3]) # ZSTATE
                vals.append(row[2]) # ZCITY
                outConn.execute("insert into ZFAILEDBANKINFO values(?, ?, ?, ?, ?, ?, ?)", vals)
                 
                # Create ZFAILEDBANKDETAILS entry
                vals = []
                vals.append(row[0]) # Z_PK
                vals.append(1) # Z_ENT
                vals.append(1) # Z_OPT
                vals.append(row[4]) # ZZIP
                vals.append(row[0]) # ZINFO
                vals.append(closeDateSecs) # ZUPDATEDATE
                vals.append(updatedDateSecs) # ZCLOSEDATE
                outConn.execute("insert into ZFAILEDBANKDETAILS values(?, ?, ?, ?, ?, ?, ?)", vals)
                 
                outConn.execute("update Z_PRIMARYKEY set Z_MAX=?", [maxId])
                 
                outConn.commit()

    This should be pretty straightforward. The only tricky thing we needed to do here was to convert the dates from the format they were stored in our old database (a string) to the format they are stored in the new databaes (epoch seconds). Update: Jeff R. pointed out that NSDate uses a difference reference date than Python does so we have to convert that – see the comments section for more information.

    Give the Python script a whirl and if all works well you should be able to see your DB populated with data:

    python coreData.py
    sqlite3 FailedBanksCD.sqlite
    sqlite> select * from ZFAILEDBANKINFO limit 3;
    1|2|1|1|Desert Hills Bank|AZ|Phoenix
    2|2|1|2|Unity National Bank|GA|Cartersville
    3|2|1|3|Key West Bank|FL|Key West
    sqlite> select * from ZFAILEDBANKDETAILS limit 3;
    1|1|1|57060|1|1269576000|1269576000
    2|1|1|34678|2|1269576000|1269576000
    3|1|1|34684|3|1269576000|1269576000
    

    Once you’re satisfied the data is in the database correctly, drag the populated database file into your XCode project in the Resources folder. Then open up FailedBanksCDAppDelegate.m, navigate to the persistentStoreCoordinator function, and replace the storeUrl line with the following:

    NSString *storePath = [[self applicationDocumentsDirectory]
                stringByAppendingPathComponent: @"FailedBanksCD.sqlite"];
                NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
                 
                // Put down default db if it doesn't already exist
                NSFileManager *fileManager = [NSFileManager defaultManager];
                if (![fileManager fileExistsAtPath:storePath]) {
                NSString *defaultStorePath = [[NSBundle mainBundle]
                pathForResource:@"FailedBanksCD" ofType:@"sqlite"];
                if (defaultStorePath) {
                [fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];
                }
                }

    All this does is check to see if the sqlite file already exists in the documents directory, and if it doesn’t (i.e. it’s the first time the app has run) it copies the included database from the bundle into the documents directory. Then Core Data will start using the preloaded data and we’re good to go!

    Delete the old SQLITE3 file from the iPhone simulator directory (or click iPhone Simulator\Reset Contents and Settings to clear everything), and re-run your app. If all works, you should now see the prepopulated list of banks!

    Failed Banks App With Core Data

    Where to Go From Here?

    At this point, we have a detail view that works pretty much as efficiently as the way it did in our SQLite example. However, with Core Data, with just a couple more steps we can make it even more efficient. So next time we’re going to cover how to do that by using NSFetchedResultsController!

    posted on 2010-09-29 14:50 seal 閱讀(283) 評(píng)論(0)  編輯  收藏 所屬分類: iPhone
    主站蜘蛛池模板: 亚洲va久久久噜噜噜久久男同| 免费视频淫片aa毛片| 亚洲精品无码mv在线观看网站| 青青草97国产精品免费观看| 啊v在线免费观看| av片在线观看永久免费| 亚洲中文字幕无码专区| 在线观看片免费人成视频播放| 亚洲精品成人网站在线观看| 黄色片免费在线观看| 亚洲av无码一区二区三区不卡 | 免费a级毛片无码av| 亚洲第一成年网站视频| 免费一级毛片不卡在线播放| 美女视频黄a视频全免费网站一区| 四虎永久在线精品视频免费观看| 看一级毛片免费观看视频| 亚洲精品一级无码鲁丝片| 拍拍拍无挡免费视频网站| 日本久久久久亚洲中字幕| 国产无人区码卡二卡三卡免费 | 免费成人激情视频| 亚洲欧美国产日韩av野草社区| 在线免费观看视频你懂的| 深夜福利在线视频免费| 亚洲国产精品一区第二页| 无码日韩人妻av一区免费| 亚洲av日韩精品久久久久久a| 亚洲色图综合在线| 久久免费区一区二区三波多野| 亚洲一区无码中文字幕乱码| 亚洲 自拍 另类小说综合图区 | 亚洲VA中文字幕无码毛片| 日韩视频在线精品视频免费观看| 国产亚洲欧美在线观看| 亚洲国产精品无码一线岛国| 亚色九九九全国免费视频| 人成午夜免费大片在线观看| 18亚洲男同志videos网站| 免费大香伊蕉在人线国产 | 久久亚洲私人国产精品vA|