1

私のシミュレーターは問題なく高速に動作します。データベースを作成して入力しようとしている部分で、iPhone がフリーズしているようです。ただし、ユーザーがデータベースを再作成する必要がないように、シミュレーターのデータベースを使用してそれを iPhone に配置することを好みます。私が知りたいのは、フォルダーに追加されたデータベースからどのようにロードできるかです。

私はたくさん検索しましたが、それは時代遅れであるか、私が望むものとは異なります. データベースファイルをファインダーからxcodeプロジェクトに追加しました。私が正しければ、_databasePath を変更して、ファイルがどこにあるかを指すようにする必要があります。正しいですか?

もしそうなら、コードからのものはここにあります: /var/mobile/Applications/65B5541A-1E73-46F6-AB5A-C5988003103E/Documents/paths.db しかし、それは私が xcode にドラッグしたものではありません。また、オーガナイザーを見て、そこにdocuments/paths.dbが表示されますが、他のファイルが見つからないため、それはdbが作成されたコードであり、ドラッグされたものではないと想定しています。削除しようとしましたが、選択できませんそれ。

誰かが助けることができますか?

ヘッダー内:

@property (strong, nonatomic) NSString *databasePath;
@property (nonatomic) sqlite3 *pathDB;

.m:

- (void) createDataBaseIfNotExist {

    NSString *docsDir;
    NSArray *dirPaths;

    // Get the documents directory
    dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    docsDir = dirPaths[0];

    // Build the path to the database file
    _databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent:@"paths.db"]];

    NSLog(@"databasePath: %@", _databasePath);

    NSFileManager *filemgr = [NSFileManager defaultManager];

    if ([filemgr fileExistsAtPath: _databasePath] == NO) {

        const char *dbpath = [_databasePath UTF8String];

        if(sqlite3_open(dbpath, &_pathDB) == SQLITE_OK) {
            char *errMsg;
            const char *sql_stmt =
            "CREATE TABLE IF NOT EXISTS Paths (ID INTEGER PRIMARY KEY AUTOINCREMENT, START INTEGER, END INTEGER, DISTANCE REAL, NODES TEXT)";

            if (sqlite3_exec(_pathDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
            {
                //_status.text = @"Failed to create table";
                NSLog(@"Failed to create table");

            }
            sqlite3_close(_pathDB);
        } else {
            // _status.text = @"Failed to open/create database";
            NSLog(@"Failed to open/create database");
        }
    }

}
4

1 に答える 1

1

だから、いくつかのこと:

  1. createDatabaseIfNotExistに見つからない場合は、最初に をバンドルからコピーするように変更する必要がありますDocuments

    - (void) createDataBaseIfNotExist {
    
        // Get the documents database path
        NSString *docsDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
        self.databasePath = [docsDir stringByAppendingPathComponent:@"paths.db"]; // always use setter when setting property's value
    
        NSFileManager *fileManager = [NSFileManager defaultManager];
    
        if ([fileManager fileExistsAtPath:_databasePath] == NO) {
    
            // if the database doesn't exist in documents, look for it in the bundle and copy it if found
    
            // get the bundle database path
            NSString *bundleDatabasePath = [[NSBundle mainBundle] pathForResource:@"paths" ofType:@"db"];
    
            if (bundleDatabasePath) {
                // if we successfully copied from bundle, then quit
    
                if ([fileManager copyItemAtPath:bundleDatabasePath toPath:self.databasePath error:nil])
                    return;
            }
    
            // otherwise, let's proceed with creating the database
    
            if(sqlite3_open([_databasePath UTF8String], &_pathDB) == SQLITE_OK) {
                char *errMsg;
                const char *sql_stmt = "CREATE TABLE IF NOT EXISTS Paths (ID INTEGER PRIMARY KEY AUTOINCREMENT, START INTEGER, END INTEGER, DISTANCE REAL, NODES TEXT)";
    
                if (sqlite3_exec(_pathDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK) {
                    //_status.text = @"Failed to create table";
                    NSLog(@"Failed to create table, %s", errMsg);
                    sqlite3_free(errMsg); // if you're going to use that fifth parameter, you must free it when you're done
                }
                sqlite3_close(_pathDB);
            } else {
                // _status.text = @"Failed to open/create database";
                NSLog(@"Failed to open/create database");
            }
        }
    }
    
  2. 次に、シミュレーターでこれを 1 回実行したら、シミュレーターのDocumentsフォルダーで Xcode プロジェクトのデータベースを見つけます。シミュレーターのファイルは次の場所にあります。

    ~/ライブラリ/Application Support/iPhone Simulator/6.1/Applications/XXX/Documents

    XXX暗号識別子です (例: 85206BA6-9D03-4F18-BB0A-3B8C25B552C4)。デフォルトでは、Libraryフォルダーは非表示になっているため、ターミナルのコマンド ラインに移動し、次のコマンドを入力して表示します。

    chflags nohidden ライブラリ
    
  3. その後、Finder から Xcode のファイル ナビゲーター ウィンドウにドラッグして、データベースをプロジェクトに戻すことができます。その時点で、次のようなウィンドウが表示されます。

    ここに画像の説明を入力

    強調表示された 2 つのチェックマークをオンにして、データベースがバンドルに含まれていることを確認してください。

2 つの最終的な観察:

  • 「必要に応じてバンドルからコピーするロジック」ができたので、コードでテーブルを作成する必要があるかどうかは興味深い質問です。個人的には、私はいつも Mac の優れたグラフィカルな SQLite ツールを使用してデータベースを作成し、それを自分のプロジェクトにコピーしています。プログラムでテーブルを作成するのは、(a) 新しい/変更されたテーブルを含む更新をデプロイするときだけです。(b) ユーザーのデータベースには、バンドルのデータベースと単純に置き換えたくない重要なデータが含まれている可能性があります。

  • 私は個人的に常に、configuration列の 1 つがデータベースのバージョンである単一の行を含むテーブルをアプリに含めます。したがって、私のアプリはドキュメントからデータベースを開き、バージョン番号を確認し、古い場合は (ユーザーがアプリを最近アップグレードしたばかりであるため)、データベースを更新します。この「データベースのバージョン番号」ロジックは、アプリのバージョン 1.0 の一部として実装する必要があるものです。

于 2013-05-04T15:38:55.487 に答える