2

VegQuantity と呼ばれるビュー コントローラーがあり、totalcost=(数量 * 料理のコスト) を実行し、itemname、quantity、totalcost を FINALORDER と呼ばれるデータベース名 FinalOrder と呼ばれるテーブルに挿入します。

sqlite3_stmt    *statement;

const char *dbpath = [databasePath UTF8String];

if (sqlite3_open(dbpath, &FinalOrder) == SQLITE_OK)
{
    NSString *insertSQL = [NSString stringWithFormat: @"INSERT INTO FINALORDER (itemname, quantity, totalcost) VALUES (\"%@\", \"%@\", \"%@\")", itemName.text, input.text, output.text];

    const char *insert_stmt = [insertSQL UTF8String];

    sqlite3_prepare_v2(FinalOrder, insert_stmt, -1, &statement, NULL);
    if (sqlite3_step(statement) == SQLITE_DONE)
    {
        //  status.text = @"Contact added";
        //  name.text = @"";
        //  address.text = @"";
        //  phone.text = @"";
        NSLog(@"added");
    } else {
        NSLog(@"Couldnt add");
    }
    sqlite3_finalize(statement);
    sqlite3_close(FinalOrder);
}

Final View Controllerのviewdidloadメソッド

const char *dbpath = [databasePath UTF8String];
sqlite3_stmt    *statement;

if (sqlite3_open(dbpath, &FinalOrder) == SQLITE_OK)
{
    NSString *querySQL = [NSString stringWithFormat: @"SELECT * FROM FINALORDER"];

    const char *query_stmt = [querySQL UTF8String];

    if (sqlite3_prepare_v2(FinalOrder, query_stmt, -1, &statement, NULL) == SQLITE_OK)
    {
        if (sqlite3_step(statement) == SQLITE_ROW)
        {
            NSString *itemname = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
            item.text = itemname;

            NSString *qua = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
            quantity.text = qua;

            NSString *total = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)];
            totalcost.text=total;
        }
        sqlite3_finalize(statement);
    }
    sqlite3_close(FinalOrder);
}

しかし、FinalOrderの前にexpected expressionと呼ばれるこのエラーが発生し続けています.viewdidload内にこのコードを書くのは正しいですか? Final View Controllerにはボタンがありません。Restaurantと呼ばれるView Controllerにorderというボタンがあり、実際にFinal View Controllerが表示されます..Final View Controllerでdbファイルを再度検索することになっていますが、申し訳ありませんが質問漠然としているようですが、簡単に言えば、VegQuantityビューコントローラーに挿入したデータを最終的なビューコントローラーに取得して表示する方法を知りたいだけです

4

1 に答える 1

0

問題はFinalOrder、エラーメッセージに基づいて、sqlite3 *変数としてではなくクラスとして定義されているように見える定義にあると思います。データベースの使用範囲がこれら 2 つの方法に限定されていることを考えると、その範囲sqlite3 *内で を定義し、次のように使用することをお勧めします。

- (void)saveRecord
{
    sqlite3      *database;
    sqlite3_stmt *statement;
    const char   *dbpath = [databasePath UTF8String];

    if (sqlite3_open(dbpath, &database) == SQLITE_OK)
    {
        [self purgeTable:database];

        NSString *insertSQL = @"INSERT INTO FINALORDER (itemname, quantity, totalcost) VALUES (?, ?, ?)";

        if (sqlite3_prepare_v2(database, [insertSQL UTF8String], -1, &statement, NULL) == SQLITE_OK)
        {
            sqlite3_bind_text(statement, 1, [itemName.text UTF8String], -1, NULL);
            sqlite3_bind_int(statement, 2, [input.text intValue]);
            sqlite3_bind_double(statement, 3, [output.text doubleValue]);

            if (sqlite3_step(statement) == SQLITE_DONE)
            {
                //  status.text = @"Contact added";
                //  name.text = @"";
                //  address.text = @"";
                //  phone.text = @"";
                NSLog(@"added");
            } else {
                NSLog(@"%s Couldn't add; errmsg='%s'", __FUNCTION__, sqlite3_errmsg(database));
            }
            sqlite3_finalize(statement);
        } else {
            NSLog(@"%s Couldn't prepare; errmsg='%s'", __FUNCTION__, sqlite3_errmsg(database));
        }

        sqlite3_close(database);
    }
}

sqlite3 *データベースに変数を使用することに加えて、これをもう少し堅牢にすることに注意してください。

  1. stringWithFormatSQL 挿入ステートメントを作成したINSERTステートメントを、?プレースホルダーを使用するステートメントに置き換えてsqlite3_bind_textから、値をそのステートメントにバインドするために使用します。このように、誰かが引用符を含む値を入力した場合でも、insert ステートメントは引き続き機能します (元の実装はクラッシュしたり、SQL インジェクション攻撃を受けやすくなります)。

  2. ステートメントも追加したsqlite3_errmsgので、何か問題が発生した場合、問題が何であったかがわかります。

  3. これら 3 つのフィールドをテキスト フィールドとして扱うのではなく、テーブルが として定義されていると想定しているCREATE TABLE IF NOT EXISTS FINALORDER (itemname TEXT, quantity INT, totalcost REAL);ため、text、int、および double bind ステートメントを使用します。

ちなみに、これはメソッドを呼び出すpurgeTableため、2 回実行すると、そこにある古いレコードが削除されます。

- (void)purgeTable:(sqlite3 *)database
{
    if (sqlite3_exec(database, "DELETE FROM FINALORDER;", NULL, NULL, NULL) != SQLITE_OK)
        NSLog(@"%s Couldn't purge table %s", __FUNCTION__, sqlite3_errmsg(database));
}

とにかく、次の方法でこのデータを読み取ることができます。

- (void)loadRecord
{
    sqlite3      *database;
    const char   *dbpath = [databasePath UTF8String];
    sqlite3_stmt *statement;

    if (sqlite3_open(dbpath, &database) == SQLITE_OK)
    {
        NSString *querySQL = @"SELECT * FROM FINALORDER";

        if (sqlite3_prepare_v2(database, [querySQL UTF8String], -1, &statement, NULL) == SQLITE_OK)
        {
            if (sqlite3_step(statement) == SQLITE_ROW)
            {
                NSString *itemname = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
                item.text = itemname;
                //[itemname release]; // if not ARC, uncomment this line

                int qua = sqlite3_column_int(statement, 1);
                quantity.text = [NSString stringWithFormat:@"%1d", qua];

                double total = sqlite3_column_double(statement, 2);
                totalcost.text = [NSString stringWithFormat:@"%1.2f", total];
            }
            sqlite3_finalize(statement);
        } else {
            NSLog(@"%s Couldn't prepare; errmsg='%s'", __FUNCTION__, sqlite3_errmsg(database));
        }
        sqlite3_close(database);
    }
}

ノート、

  1. sqlite3_errmsgが失敗した場合はログ ステートメントを追加し、 (何もフォーマットしていないため) をsqlite3_prepare廃止しました。stringWithFormat

  2. quantitywasINTtotalwasを考えると、 、、またはREALの適切なバリエーションを必要に応じて使用して値を取得しています。sqlite3_column_textsqlite3_column_intsqlite3_column_double

  3. ARC を使用していないため、 にはor[NSString alloc]が関連付けられている必要があります。releaseautorelease

最後に、私たちのチャットで、次のようなエラー メッセージ (おそらく「未定義のシンボル」メッセージ) を受け取ったと言っていました。

OBJC_CLASS_$"_FinalOrder"

これは、 のオブジェクト クラスを使用しようとしてFinalOrderいますが、そのクラスがどこにも定義されていないことを意味します。このエラーが報告されている .o ファイルを調べ、対応する .m ファイルを調べて、FinalOrderそこでクラスの使用を探します。明らかにFinalOrderクラス インターフェイスがどこかに定義されていますが、クラスの実装を定義していません。または、クラスの実装がある場合は、何らかの理由でターゲットの「ソースのコンパイル」リストに含まれていないため、ここにあることを再確認してください。

コンパイルソースを追加

最後に、データベースがDocumentsフォルダにあることを確認してください。プロジェクトのバンドルでデータベースのコピーを開こうとしないでください (読み取り専用であるため)。バンドルにデータベースのコピーがある場合は、フォルダーに既に存在するかどうかを確認し、Documents存在しない場合は、バンドルからDocumentsフォルダーにコピーします。

于 2012-08-27T17:35:26.070 に答える