加载视图控制器后如何加载 UIImageView
Posted
技术标签:
【中文标题】加载视图控制器后如何加载 UIImageView【英文标题】:How to load a UIImageView after loading the view controller 【发布时间】:2012-08-15 15:23:34 【问题描述】:我在特定的视图控制器上生成了一个(可能)非常缓慢且效率低下的拼贴画。加载需要很长时间,因此我正在寻找可以加快我的 SQLite 查询(它正在搜索保存的图像的 BLOB)或导致在视图控制器加载之后调用 SQL 查询方法的建议,并且然后我会在它加载时放置一个活动指示器。
这里是代码 sn-ps。
viewDidLoad
:
- (void)viewDidLoad
//generate photo collage
wineryName = theWineOfCurrentWinery.winery;
[self obtainImagesForWines:wineryName];
//lots of other stuff
obtainImagesForWines
函数。这是控制在 16 个 UIImageView 之一中显示的照片,其中有一个 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);
【问题讨论】:
【参考方案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 存储图像的 *** 似乎存在很多争论,并且这里涉及到一个巨大的性能问题。一个这样的例子here。
我自己有多个场景,我必须保存图像。我所做的(我的所有解决方案)是将图像保存到文档文件夹,然后让核心数据(或 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 以获得更好的性能。
【讨论】:
我认为这不一定是图像的大小问题,因为即使在加载此视图控制器时,如果在 winery=? 中保存了 0 张照片,我也会有很长的延迟。当有 0 张图片和有 16 张图片时加载所需的时间一样长。我确信压缩图片是个好主意,但如果有 1000 张图片,它们在一定程度上是大是小都没有关系。 【参考方案2】:您应该将需要一些时间的代码添加到另一个方法中,例如ViewDidAppear
或者请在后台运行它,这会在您尝试从后台线程更新 UI 时造成更多麻烦。所以我会选择第一个选项并将代码添加到ViewDidAppear
函数中。
如果您愿意,我可以发布代码以在后台运行它,但我会误导您,因为我会将您推向一个轨道,迫使您对代码进行更多修改。
【讨论】:
【参考方案3】:为了在后台运行这个方法(换句话说“在视图加载后”),我在viewDidLoad
中使用了以下代码:
[self performSelectorInBackground:@selector(obtainImagesForWines) withObject:nil];
【讨论】:
实际上不,这个方法的作用是,它开始在后台线程中加载图像,这样主GUI就不会被阻塞。这就是为什么它看起来是在 viewDidLoad 之后执行的,但实际上它是在 viewDidLoad 之后执行的。另外,我不认为将它们作为 blob 是一个好主意,因为您无法利用它们作为资产,例如获得令人难以置信的快速缩略图视图来创建您的拼贴画。 您有其他解决方案吗? 除非您以其他方式存储图像,否则这将适用于您的情况。因为您也不需要对其执行方式进行太多控制。以上是关于加载视图控制器后如何加载 UIImageView的主要内容,如果未能解决你的问题,请参考以下文章