简体   繁体   中英

Memory Management Issue in iOS8, Objective C

So This code was working for me before iOS 8, I have tested it on 3000 Images download loop in iOS 7.1.

But recently some of my App user Compliant me about App Crash While Image Download Process.

Using this way now Just 200 Images are downloading and App Crashes.

I just figured Out On every Image download There is about 0.6 to 0.8 MB Memory is increasing and after about 200 Images App Crashes.

I have to Download Images Synchronously, Because when i try to download in Background Thread or Asynchronous mode or even try to Use dispatch_async(dispatch_get_main_queue() way. The Process Start after some seconds and till then the While loop i am using just reach to its end.

So Please help me on this issue. What should i do to resolve it.

My code for download Images is:

-(void) downloadImages
{
NSString *myDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
database = [dBName UTF8String];
if (sqlite3_open(database, &dbConnection) == SQLITE_OK)
{
    sqliteQuery = [NSString stringWithFormat: @"SELECT ProductID FROM ProductDetails WHERE ImageDownloadStatus = 0"];
    int i = 0;
    if (sqlite3_prepare_v2(dbConnection, [sqliteQuery UTF8String], -1, &sQLStatement, NULL) == SQLITE_OK)
    {
        while (sqlite3_step(sQLStatement) == SQLITE_ROW)
        {
            @autoreleasepool
            {
                temp = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(sQLStatement, 0)];
                NSString *imageURL = [NSString stringWithFormat:@"http://xxxxxxxxxxxxxxx.jpg",clientSite,temp];

                myImage = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]]];

                NSString *imagePath = [NSString stringWithFormat:@"%@/%@.jpg",myDirectory,temp];
                NSData *imageData = [NSData dataWithData:UIImageJPEGRepresentation(myImage, 1.0f)];
                [imageData writeToFile:imagePath atomically:YES];

                sqliteQuery2 = [NSString stringWithFormat: @"UPDATE ProductDetails SET ImageDownloadStatus = 1 WHERE ProductID = \'%@\'",temp];
                 if (sqlite3_prepare_v2(dbConnection, [sqliteQuery2 UTF8String], -1, &sQLStatement2, NULL) == SQLITE_OK)
                 {
                     if (sqlite3_step(sQLStatement2) == SQLITE_DONE)
                      sqlite3_finalize(sQLStatement2);
                 }

                [self performSelectorInBackground:@selector(updateUILabels) withObject:nil];
                 i = i + 1;   
            }
        }
        sqlite3_finalize(sQLStatement);
    }
    sqlite3_close(dbConnection);
 }
}

-(void) updateUILabels
{
@autoreleasepool
{
    progressCounter.hidden = NO;
    lblProgressStatus.hidden = NO;
    spinner.hidden = NO;
    [spinner startAnimating];

    lblProgressStatus.text = @"Synchronising Product Images...";
    lblProgressCounter.text = [NSString stringWithFormat:@"%d / %d”, i,total];       
}
}

You should execute the downloadImages method in the background and the updatedUILabels method in the main thread. You can use dispatch_async(dispatch_get_main_queue(), ^{ [self updateUILabels]; }); or [self performSelectorOnMainThread:@selector(updateUILabels:) withObject:nil waitUntilDone:NO]; the execute updatedUILabels in the main thread.

In general always execute long running operations in an background thread (either using GCD, NSOperations or blocks) and always execute functions that update your UI on the main thread.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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