0

我在特定的视图控制器上生成了一个(可能)非常缓慢且效率低下的拼贴画。加载需要很长时间,所以我正在寻找可以加快我的 SQLite 查询(它正在搜索已保存图像的 BLOB)或导致在视图控制器加载调用 SQL 查询方法的建议,然后我将放置一个活动加载时的指示器。

这是代码片段。

viewDidLoad

- (void)viewDidLoad
{
    //generate photo collage
    wineryName = theWineOfCurrentWinery.winery;
    [self obtainImagesForWines:wineryName];

    //lots of other stuff
}

obtainImagesForWines功能。这是控制显示在 16 个 UIImageViews 之一中的照片,其中有一个 4x4 块:

- (void) obtainImagesForWines:(NSString *)theWineryName {

sqlite3_stmt *stmt=nil;
sqlite3 *cruddb;

//sql command
const char *sql = "SELECT photo FROM wines WHERE winery=? AND photo NOT NULL ORDER BY RANDOM() LIMIT 16";

//Open db
sqlite3_open([path UTF8String], &cruddb);

int j=0;
if(sqlite3_prepare_v2(cruddb, sql, -1, &stmt, NULL) == SQLITE_OK) { 
    sqlite3_bind_text(stmt, 1, [theWineryName UTF8String], -1, SQLITE_TRANSIENT);
    while(sqlite3_step(stmt) == SQLITE_ROW) {
        UIImage *winePhoto;

        NSData *data = [[NSData alloc] initWithBytes:sqlite3_column_blob(stmt, 0) length:sqlite3_column_bytes(stmt, 0)];            

        if (data) {
            winePhoto = [UIImage imageWithData:data];
        }

        switch (j) {
            case 0:
                image1.image = winePhoto;
                break;
            case 1:
                image2.image = winePhoto;
                break;
            case 2:
                image3.image = winePhoto;
                break;
            case 3:
                image4.image = winePhoto;
                break;
            case 4:
                image5.image = winePhoto;
                break;
            case 5:
                image6.image = winePhoto;
                break;
            case 6:
                image7.image = winePhoto;
                break;
            case 7:
                image8.image = winePhoto;
                break;
            case 8:
                image9.image = winePhoto;
                break;
            case 9:
                image10.image = winePhoto;
                break;
            case 10:
                image11.image = winePhoto;
                break;
            case 11:
                image12.image = winePhoto;
                break;
            case 12:
                image13.image = winePhoto;
                break;
            case 13:
                image14.image = winePhoto;
                break;
            case 14:
                image15.image = winePhoto;
                break;
            case 15:
                image16.image = winePhoto;
                break;
            default:
                NSLog(@"wtf?");
        }
        j++;
    }
}
else {
    printf("I can't get the wine photo by ID!!: %s\n", sqlite3_errmsg(cruddb));
}
sqlite3_finalize(stmt);
sqlite3_close(cruddb);
}
4

3 回答 3

1

您应该将需要一些时间的代码添加到另一个方法中,ViewDidAppear 或者请在后台运行它,这会在您尝试从后台线程更新 UI 时造成更多麻烦。所以我会选择第一个选项并将代码添加到ViewDidAppear函数中。

如果您愿意,我可以发布代码以在后台运行它,但我会误导您,因为我会将您推向一个轨道,这将迫使您对代码进行更多修改。

于 2012-08-16T13:44:14.610 回答
1

您可以在显示/存储图像时尝试缩小图像尺寸。我不确定,但我认为你在你的图像视图中显示了一个相当大的图像。我相信您正在尝试显示 16 图像缩略图。如果是这样,请尝试压缩图像。

一个可能更好的选择是,当您存储图像时,您可以将实际图像与缩略图版本一起存储,因此当您显示较小的图像时,请使用较小的图像。等等。

UIImageJPEGRepresentation(image,compressionRatio);

这应该允许您压缩图像。或者,如果您想像这样调整它们的大小:

UIImage *yourImage = [UIImage imageWithData:yourdata];
UIImageView *imageView = [[UIImageView alloc] initWithImage:yourImage];
UIImageView.frame = CGRectMake(0, 0, yourImage.size.width / 2, yourImage.size.height / 2);

希望这有帮助!!

更新:

关于使用 sqlite BLOB 存储图像的 stackoverflow 似乎有很多争论,并且这里涉及到一个巨大的性能问题。这里有一个这样的例子。

我自己有多个场景,我必须保存图像。我所做的(我的所有解决方案)是将图像保存到文档文件夹,然后让核心数据(或 sqlite,如果您愿意)存储对图像位置和名称的引用。这样,从 DB 中读取的时间减少了,时间也减少了。

我使用以下函数作为获取文档位置的通用方法:

- (NSString *)getFileLocation {
    // Get all available file system paths for the user
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    // Get the "Documents" directory path - it's the one and only on iPhone OS
    NSString *documentsPath = [paths objectAtIndex:0];

    // Specify the file name, appending it to documentsPath above
    NSString *savedFileName = [documentsPath stringByAppendingPathComponent:@"Location.plist"];

    // We're done
    return savedFileName;
}

然后将文件位置作为字符串保存到数据库中。我建议使用 Core Data 以获得更好的性能。

于 2012-08-15T15:36:13.917 回答
0

为了在后台运行此方法(换句话说,“在视图加载后”),我使用了以下代码viewDidLoad

[self performSelectorInBackground:@selector(obtainImagesForWines) withObject:nil];
于 2012-08-15T23:45:24.550 回答