Как запустить поток в фоновом режиме приложения, который не повлияет на пользовательский интерфейс моего приложения

Я сделал приложение для IOS, в котором я использую базу данных sqlite, база данных является локальной в приложении. Теперь я дал функциональность, чтобы приложение загружало данные из Интернета, помещало их в локальную базу данных и показывало пользователю. Я дал эту функциональность на - (void)viewDidLoad, так что, когда приложение загружает данные, оно перестает работать до тех пор, пока не завершит загрузку части, поскольку этому пользователю нужно подождать, чтобы взаимодействовать с приложением.

Теперь я хочу, чтобы поток работал в фоновом режиме приложения, которое будет подключаться к Интернету и обновлять приложение, не мешая пользователю. пожалуйста, помогите мне.

Мой код загрузки и сохранения изображения таков:

 -(void)Download_save_images:(NSString *)imagesURLPath :(NSString *)image_name   
   {                              

      NSMutableString *theString = [NSMutableString string];

    // Get an image from the URL below    
      UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:NSURL  URLWithString:imagesURLPath]]];        
      NSLog(@"%f,%f",image.size.width,image.size.height);        
     NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];

    // If you go to the folder below, you will find those pictures
     NSLog(@"%@",docDir);    
    [theString appendString:@"%@/"];
    [theString appendString:image_name];
    NSLog(@"%@",theString);
    NSLog(@"saving png");
    NSString *pngFilePath = [NSString stringWithFormat:theString,docDir];
    NSData *data1 = [NSData dataWithData:UIImagePNGRepresentation(image)];
    [data1 writeToFile:pngFilePath atomically:YES];  

    NSLog(@"saving image done");

    [image release];
   // [theString release];
}

когда я отлаживаю приложение, я вижу, что мое приложение занимает больше времени в строке ниже:

UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:NSURL  URLWithString:imagesURLPath]]];

person Anupam Mishra    schedule 25.04.2013    source источник
comment
Вам нужен GCD, это легко, как только вы его освоите   -  person amar    schedule 25.04.2013


Ответы (5)


Вы также можете использовать NSOperationQueue и NSBlockOperation, если вам сложно выполнить GCD.

NSBlockOperation *operation=[[NSBlockOperation alloc] init];

[operation addExecutionBlock:^{
    //Your code goes here

}];

NSOperationQueue *queue=[[NSOperationQueue alloc] init];
[queue addOperation:operation];

В GCD вы можете добиться того же, используя

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
   //Your Code to download goes here

    dispatch_async(dispatch_get_main_queue(), ^{
       //your code to update UI if any goes here

    });
});

Используйте любой из API в зависимости от ваших потребностей. Проверьте эту ветку, в которой обсуждается NSOperationQueue против GCD для получения дополнительной информации.

person Shahzin KS    schedule 25.04.2013
comment
Я использую GCD, как вы указали, но во время загрузки изображений мое приложение будет зависать до тех пор, пока изображения не закончат загрузку. пожалуйста, предложите мне путь. - person Anupam Mishra; 25.04.2013

Подобные вопросы задавались уже сотни раз. Я предлагаю вам сделать быстрый поиск по этому вопросу. Также в документации Apple есть тема, подробно описывающая эту область. здесь

В основном вы можете сделать это с очередями операций или очередями отправки. Есть несколько фрагментов кода, приведенных выше Avi & Amar.

Я хотел бы добавить кое-что, так как вы, кажется, не знакомы с этой темой, и вы упомянули, что задействованы веб-запросы.

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

    // Dont DIRECTLY request your NSURL Connection in this part because it will never return data to the delegate...
//  Remember your network requests like NSURLConnections must be invoked in mainqueue
// So what ever method you're invoking for NSURLConnection it should be on the main queue

        dispatch_async(dispatch_get_main_queue(), ^{
                // this will run in main thread. update your UI here.
        });
    });

Ниже я привел небольшой пример. вы можете обобщить идею в соответствии с вашими потребностями.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

        // Do your background work here

        // Your network request must be on main queue. this can be raw code like this or method. which ever it is same scenario. 
        NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com"]];
        dispatch_async(dispatch_get_main_queue(), ^{

            [NSURLConnection sendAsynchronousRequest:req queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *res, NSData *dat, NSError *err)
             {
                 // procress data

                 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

                     // back ground work after network data received

                     dispatch_async(dispatch_get_main_queue(), ^{

                         // finally update UI
                     });
                 });
             }];
        });
    });
person nsuinteger    schedule 25.04.2013
comment
на самом деле я использую облако parse.com (parse) для загрузки данных. поэтому нет запроса URL, такого как NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:@google.com]]< /а>; - person Anupam Mishra; 25.04.2013

Вы можете использовать GCD, например:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    // put here your background code. This will run in background thread.

    dispatch_async(dispatch_get_main_queue(), ^{
            // this will run in main thread. update your UI here.
    });
})

Но вам нужно понять, как работают блоки, например. Попытайся.

person Avi Tsadok    schedule 25.04.2013
comment
Я использую GCD, как вы указали, но во время загрузки изображений мое приложение будет зависать до тех пор, пока изображения не закончат загрузку. пожалуйста, предложите мне путь. - person Anupam Mishra; 25.04.2013
comment
Не понял -› ты хочешь, чтобы его повесили? Вы хотите, чтобы пользовательский интерфейс был бесплатным для взаимодействия? Пожалуйста, добавьте свой код к вопросу. - person Avi Tsadok; 25.04.2013
comment
Я хочу, чтобы пользовательский интерфейс был свободен для взаимодействия. - person Anupam Mishra; 25.04.2013
comment
Итак, если вы запускаете весь тяжелый код, например загрузку изображений, в том месте, где я написал: «// поместите сюда свой фоновый код. Это будет работать в фоновом потоке». Пользовательский интерфейс будет бесплатным. - person Avi Tsadok; 25.04.2013

Использовать НОД

создайте свой объект отправки

dispatch_queue_t yourDispatch;
yourDispatch=dispatch_queue_create("makeSlideFast",nil);

затем используйте его

dispatch_async(yourDispatch,^{
//your code here

//use this to make uichanges on main thread
dispatch_async(dispatch_get_main_queue(), ^(void) {
});


});

Выполняйте пользовательский интерфейс в основном потоке только с помощью

dispatch_async(dispatch_get_main_queue(), ^(void) {
});

Затем отпустите его

dispatch_release(yourDispatch);

Вот руководство

person amar    schedule 25.04.2013
comment
Я использую GCD, как вы указали, но во время загрузки изображений мое приложение будет зависать до тех пор, пока изображения не закончат загрузку. пожалуйста, предложите мне путь. - person Anupam Mishra; 25.04.2013
comment
вам нужно загрузить в аасинхронном режиме, вы видели учебник? - person amar; 25.04.2013

Есть много способов:

1 . Grand Central Dispatch

dispatch_async(dispatch_get_global_queue(0, 0), ^{
  //Your code
});

2 . NSThread

[NSThread detachNewThreadSelector:@selector(yourMethod:) toTarget:self withObject:parameterArray];

3 . NSObject — PerformSelectorInBackground

[self performSelectorInBackground:@selector(yourMethod:) withObject:parameterArray];
person Midhun MP    schedule 25.04.2013
comment
Я использую GCD, как вы указали, но во время загрузки изображений мое приложение будет зависать до тех пор, пока изображения не закончат загрузку. пожалуйста, предложите мне путь. - person Anupam Mishra; 25.04.2013