2013-05-27 35 views
8

Tôi đang sử dụng FMDatabaseQueue trong ứng dụng iOS của mình. Tôi đang mắc kẹt trong sự hiểu biết làm thế nào để trả lại giá trị khi tạo hàng đợi. Đánh giá cao sự giúp đỡ của bạn!!FMDatabaseQueue Cách trả lại giá trị

FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath]; 

[queue inDatabase:^(FMDatabase *db) { 
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; 
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; 
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; 

FMResultSet *rs = [db executeQuery:@"select * from foo"]; 
while ([rs next]) { 
    ... 
} 
// I want value to be returned from here 
}]; 
+0

những gì bạn muốn quay trở lại? Một giá trị duy nhất, hoặc một tập hợp (hoặc mảng) các kết quả từ db (đó là những gì nó trông giống như bạn đang cố gắng thực hiện thông qua "' select * '" trên đó) ??? –

Trả lời

0

Bạn có thể vượt qua một điều trong phương pháp khối giống như ví dụ dưới đây

nếu bạn đọc trang FMDB's Github Page bạn có thể hiểu những điều làm việc

[queue inTransaction:^(FMDatabase *db, BOOL *rollback) { 
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; 
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; 
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; 

    if (whoopsSomethingWrongHappened) { 
     *rollback = YES; 
     return; 
    } 
    // etc… 
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]]; 
}]; 






FMDatabaseQueue will run the blocks on a serialized queue 
(hence the name of the class). So if you call FMDatabaseQueue's 
methods from multiple threads at the same time, they 
will be executed in the order they are received. 
This way queries and updates won't step on each other's toes, 
and every one is happy. 

    Note: The calls to FMDatabaseQueue's methods are blocking. So even though you are passing along blocks, they will not be run on another thread. 
+0

Tôi biết tôi đang hỏi một câu hỏi kỳ lạ, nhưng từ nơi bạn nhận được điều này "whoopsSomethingWrongHappened". Bạn đã tuyên bố trước đó ở đâu đó chưa? giúp đỡ sẽ được thực sự đánh giá cao. – Nik

+0

@Nik trên trang của FMDB github https://github.com/ccgus/fmdb –

15

Nó phụ thuộc vào những gì bạn đang cố gắng trở về. Nhưng điều có thể khiến bạn khó hiểu là nếu bạn phát hành câu lệnh return từ bên trong khối inDatabase, bạn sẽ trở về từ khối, bạn sẽ không trở về từ phương thức chứa khối inDatabase này.

Vì vậy, bạn chỉ đơn giản là không trả lại giá trị từ khối inDatabase, mà đúng hơn là bạn trả về các giá trị từ bên ngoài khối. Vì vậy, những gì bạn thường làm, bạn sẽ khai báo biến của mình để được trả về bên ngoài khối inDatabase, khối inDatabase của bạn sẽ cập nhật và sau đó, khi khối được thực hiện, đó là khi bạn trả lại kết quả (không phải từ trong khối inDatabase).

Một ví dụ phổ biến là nếu bạn đang xây dựng một NSMutableArray: Vì vậy, tạo ra các mảng có thể thay đổi bên ngoài của khối, và sau đó thêm giá trị từ bên trong khối, nhưng sau đó trả lại kết quả sau bạn thoát khỏi khối inDatabase:

NSMutableArray *results = [NSMutableArray array]; // declare this outside the block 

FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath]; 

[queue inDatabase:^(FMDatabase *db) { 

    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @(1)]; 
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @(2)]; 
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @(3)]; 

    FMResultSet *rs = [db executeQuery:@"select * from foo"]; 
    while ([rs next]) { 
     ... 
     [results addObject:result];     // add values inside the block 
    } 
    [rs close]; 
}]; 

return results;          // return the results outside the block 

hoặc, nếu bạn đang làm việc với một số loại hình cơ bản, giống như một NSInteger hoặc BOOL hoặc những gì có bạn, bạn muốn khai báo biến với khuôn khổ vòng loại __block. Ví dụ: tôi sẽ sử dụng điều này để trả về biến thành công của BOOL, ví dụ:

__block BOOL success;        // again, define outside the block 

NSMutableArray *results = [NSMutableArray array]; 
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath]; 

[queue inDatabase:^(FMDatabase *db) { 

    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @(1)]; 
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @(2)]; 
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @(3)]; 

    FMResultSet *rs = [db executeQuery:@"select * from foo"]; 
    if (!rs) 
    { 
     NSLog(@"%s: %@", __FUNCTION__, [db lastErrorMessage]); 
     success = NO;  // set the value inside the block 
     return;   // note, this doesn't exit the method; this exits this `inDatabase` block 
    } 

    while ([rs next]) { 
     ... 
    } 

    [rs close]; 
    success = YES;  // another example of setting that `success` variable 
}]; 

// so whether I successfully completed the block, or whether I hit the `return` 
// statement inside the block, I'll fall back here, at which point I'll return my 
// boolean `success` variable 

return success;   // don't return the value until after you exit the block 

Mặc dù điều này có vẻ khó hiểu khi lần đầu tiên bạn gặp phải, điều này rất hữu ích khi hiểu điều này. Khi bạn bắt đầu sử dụng khối GCD rất nhiều, mẫu này rất phổ biến. Khi bạn có một khối (được chỉ định bởi ký tự ^), bạn gần như phải nghĩ về nó như một hàm mà bạn đang xác định bên trong phương pháp chính của bạn. Khi bạn gặp một số return bên trong một khối, bạn sẽ quay lại phương thức chứa khối đó.

Đối với giới thiệu đến khối xem:

+0

Trong trường hợp của tôi để trả về một Bool nhanh chóng, nó trả về đầu tiên , thì hàm bên trong khối (đóng) thực thi sau. Vì vậy, nó luôn luôn trở lại sai. Bất kỳ ý tưởng? –

+1

Với FMDB? Phương thức 'inDatabase' chạy đồng bộ. Thời gian duy nhất bạn có vấn đề bạn mô tả là khi bạn đang làm một cái gì đó không đồng bộ. Nếu bạn đang làm một cái gì đó không đồng bộ, bạn sẽ (a) không cố gắng trả về giá trị ngay lập tức; nhưng đúng hơn là (b) triển khai mẫu xử lý hoàn thành của riêng bạn (ví dụ như được hiển thị trong [câu hỏi mạng không đồng bộ này] (http://stackoverflow.com/a/26569930/1271826)). Nhưng bạn không cần phải giải quyết điều đó trừ khi gửi đi một thứ gì đó không đồng bộ. – Rob

+0

Độc đáo giải thích, cảm ơn một tấn! – Rexb

Các vấn đề liên quan