简体   繁体   English

在iPhone中从数据库检索图像花费的时间太长

[英]Retrieving images form database is taking too long in iphone

I am new to iOS programming. 我是iOS编程的新手。

By using below code I am retrieving images from database and storing it in array then displaying those images in thumbnail. 通过使用以下代码,我将从数据库中检索图像并将其存储在数组中,然后以缩略图形式显示这些图像。

By using below code everything is working fine. 通过使用以下代码,一切正常。 But I have 2 problem 但是我有两个问题

  1. retrieving images form database is taking too long. 从数据库检索图像花费的时间太长。
  2. I store more than 8 images means its not displaying images,it is terminating the application.If I take below 8 images its displaying images in thumbnail. 我存储了8张以上的图像,这表示它不显示图像,正在终止该应用程序。如果我拍摄的8张以下的图像,其显示图像为缩略图。

Can any body tell me, What is mistake in this code? 谁能告诉我,这段代码有什么错误?

NSString *docsDir;
NSArray *dirPaths;

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

docsDir = [dirPaths objectAtIndex:0];
array=[[NSMutableArray alloc]init];
array1=[[NSMutableArray alloc]init];

// Build the path to the database file
databasePath =  [docsDir stringByAppendingPathComponent: @"Taukydataaa.db"];

NSFileManager *fn=[NSFileManager defaultManager];
NSError *error;
BOOL success=[fn fileExistsAtPath:databasePath];

if(!success)
{    
    NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Taukydataaa.db"];
    success = [fn copyItemAtPath:defaultDBPath toPath:databasePath error:&error];
}

const char *dbpath = [databasePath UTF8String];

sqlite3_stmt    *statement;

if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
{
    NSString *querySQL = [NSString stringWithFormat: @"select * from tauky"];

    const char *query_stmt = [querySQL UTF8String];

    if (sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
    {
        while(sqlite3_step(statement) == SQLITE_ROW)
        {

            NSString* email_idField = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement,1)];
            NSString* email_idField1 = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement,0)];
            [array addObject:email_idField];
            [array1 addObject:email_idField1];

            blaukypath =[[NSMutableArray alloc]init];

            for (NSString* path in array)
            {
                [blaukypath addObject:[UIImage imageWithContentsOfFile:path]];
            }

            myScrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0.0, 0.0, 320.0, 840.0)];
            myScrollView.delegate = self;
            myScrollView.contentSize = CGSizeMake(320.0, 840.0);
            myScrollView.backgroundColor = [UIColor whiteColor];

            [self.view addSubview:myScrollView];

            float horizontal = 8.0;
            float vertical = 8.0;

            for(int i=0; i<[blaukypath count]; i++)
            {
                if((i%4) == 0 && i!=0)
                {
                    horizontal = 8.0;
                    vertical = vertical + 70.0 + 8.0;
                }

                buttonImage = [UIButton buttonWithType:UIButtonTypeCustom];

                [buttonImage setFrame:CGRectMake(horizontal, vertical, 70.0, 70.0)];
                [buttonImage setTag:i];

                [buttonImage setImage:[blaukypath objectAtIndex:i] forState:UIControlStateNormal];
                [buttonImage addTarget:self action:@selector(buttonImagePressed:) forControlEvents:UIControlEventTouchUpInside];
                [buttonImage setImage:[UIImage imageNamed:@"play.png"] forState:UIControlStateSelected];

                [myScrollView addSubview:buttonImage];

                horizontal = horizontal + 70.0 + 8.0;
            }

            [myScrollView setContentSize:CGSizeMake(320.0, vertical + 78.0)];

            // Do any additional setup after loading the view, typically from a nib.
            self.navigationItem.leftBarButtonItem = self.editButtonItem;

            UIBarButtonItem *done = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(insertNewObject:)];

            self.navigationItem.rightBarButtonItem = done;

            [self.myScrollView addSubview:image];
        }

        sqlite3_finalize(statement);
    }

    sqlite3_close(contactDB);
}

A couple of observations: 一些观察:

  • You've put your building of the scrollview inside the loop where you're reading data from your table. 您已将滚动视图的构建放入要从表中读取数据的循环内。 If you had, for examples, nine rows in your database, you'll have 9 scrollviews, the first with one image, the second with two, the third with three, etc., for a total of 45 images. 例如,如果数据库中有九行,则将有9个滚动视图,第一个具有一个图像,第二个具有两个图像,第三个具有三个图像,等等,总共有45个图像。 I really doubt that's what you meant to do. 我真的怀疑那是你的意思。

  • You should have one loop that reads the strings from the database (do not create the image at this point ... just store the image path) and populates your array. 您应该有一个循环,该循环从数据库中读取字符串(此时创建图像...仅存储图像路径)并填充数组。 You can then have a separate loop (ideally, a completely separate routine) that builds your UI. 然后,您可以使用一个单独的循环(最好是一个完全独立的例程)来构建您的UI。 You really should isolate the the UI from the database interaction. 您确实应该将UI与数据库交互隔离。 And anything that consists of arrays of image objects will be problematic: Only maintain arrays of image paths. 任何由图像对象数组组成的东西都会出现问题:仅维护图像路径数组。

This problem, of creating lots of images that you don't need, would definitely slow down the app and consume memory. 创建大量不需要的图像的问题肯定会降低应用程序的速度并消耗内存。 Depending upon the size of the images, you could even be running out of memory and crashing. 根据图像的大小,您甚至可能耗尽内存并崩溃。

At the very minimum, you should address this issue. 至少,您应该解决此问题。

There are a couple of additional issues: 还有两个其他问题:

  • Another potential source of a crash would be if one of the image paths in your array didn't resolve itself to a path of an image. 崩溃的另一个潜在原因是,如果阵列中的图像路径之一没有将自身解析为图像路径。 Thus, the imageWithContentsOfFile would return nil , and any attempt to add nil to an array will crash. 因此, imageWithContentsOfFile将返回nil ,任何将nil添加到数组的尝试都将崩溃。 Make sure you test to see if you successfully found/loaded the image before you try to use it. 在尝试使用图像之前,请确保进行测试以查看是否成功找到/加载了图像。

  • You didn't say how big the images are, but if they're bigger than 140x140, you really want to contemplate creating screen-resolution renditions of them. 您没有说图像有多大,但是如果它们大于140x140,则您确实要考虑创建它们的屏幕分辨率副本。 If the images are very big, while it can render them at 70x70, you'll use up the memory for the full image. 如果图像很大,虽然可以70x70的分辨率渲染它们,那么您将用光整个图像的内存。 And when showing this many images at the same time, you'll quickly consume your memory if you're not careful about using screen-resolution images. 同时显示这么多图像时,如果您不小心使用屏幕分辨率图像,则会很快消耗内存。

  • Depending upon how many images you reference in your array, you might even contemplate a model where you handle the UIScrollViewDelegate method scrollViewDidScroll and only create UIImageView objects and populate their respective image properties as they scroll into view (and remove those that have scrolled out of view). 根据数组中引用的图像数量,您甚至可以构想一个模型,在该模型中处理UIScrollViewDelegate方法scrollViewDidScroll并仅创建UIImageView对象,并在它们滚动到视图时填充它们各自的image属性(并删除滚动到视图之外的image属性) )。 If targeting iOS 6, you can use a UICollectionView instead of your manually generated scrollview, and you'll get some of that functionality automatically (as long as your array is an array of image paths and not an array of image objects). 如果定位到iOS 6,则可以使用UICollectionView代替手动生成的滚动视图,并且会自动获得某些功能(只要您的数组是图像路径数组而不是图像对象数组)。

If you're still crashing, you should share with us the particulars of the crash (if you don't tell us what sort of exception/error you got, we're just guessing). 如果您仍然崩溃,则应与我们分享崩溃的详细信息(如果您不告诉我们您遇到了哪种异常/错误,我们只是在猜测)。 Also, if you haven't, implement a didReceiveMemoryWarning that, if nothing else, tells you when you have a memory warning so you can identify the issue and resolve it. 另外,如果还没有,请实施didReceiveMemoryWarning ,如果没有其他提示,它会在出现内存警告时告诉您,以便您识别问题并解决。 And make sure to test memory hungry apps like this on a device, as there are many memory related problems that won't manifest themselves on the simulator, but will rear their head on a device. 并确保在设备上测试像这样的内存匮乏的应用程序,因为存在许多与内存相关的问题,这些问题不会在模拟器上显现出来,但会在设备上引起关注。


While the above focuses on the crash issue, you also asked a performance question. 尽管以上内容着重于崩溃问题,但您也提出了性能问题。 Especially if you're not using the UICollectionView , but rather you're manually building your scrollview, then you might want to do this asynchronously. 特别是如果您不使用UICollectionView ,而是手动构建滚动视图,则可能需要异步执行此操作。 The basic idea would be that you would have a background operation that would create the UIImage object, and then dispatch the UI task of adding it to the scroll view in the main queue (as you never do UI stuff in a background queue). 基本思路是,您将有一个后台操作,该操作将创建UIImage对象,然后分派将其添加到主队列中滚动视图的UI任务(因为您从未在后台队列中执行UI事务)。 That way, though, the user can start using the app while the images are popping into place. 通过这种方式,尽管用户可以在图像弹出到适当位置时开始使用该应用程序。

There are a few subtle issues that you might want to think about here (doing db interaction on multiple threads requires some careful implementation; making sure UI updates happen on the main queue; etc.), but if you still have performance issues, this is the typical solution. 您可能需要在这里考虑一些细微的问题(在多个线程上进行数据库交互需要一些仔细的实现;确保UI更新在主队列中发生;等等),但是如果您仍然遇到性能问题,这是典型的解决方案。

Still, I'd focus on fixing the crash first, and deal with the performance issue second. 尽管如此,我还是会集中精力首先解决崩溃问题,然后再处理性能问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM