2014-11-02 2 views
1

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

Это заголовочный файл, tclass.h

#import <Foundation/Foundation.h> 

@interface tclass : NSObject 

- (void)returnIP; 
@property (nonatomic, strong) NSString *IP ; 

@end 

Это файл реализации, tclass.m

#import "tclass.h" 

@implementation tclass 

- (id)init { 
    self = [super init]; 
    return self; 
} 

- (void)returnIP { 
    NSURLSession *session = [NSURLSession sharedSession]; 
    [[session dataTaskWithURL:[NSURL URLWithString:@"http://icanhazip.com/"] 
    completionHandler:^(NSData *data, 
     NSURLResponse *response, 
     NSError *error) { 
     [self setIP:[NSString stringWithUTF8String:[data bytes]]]; 
    }] resume]; 
} 


@end 

В моем классе ViewController, я в первую очередь использовать метод returnIP для извлечения данных и хранения он в свойстве затем я обновляю пользовательский интерфейс, все это с помощью dispatch_async.

- (IBAction)butact:(id)sender { 
    tclass *t = [[tclass alloc]init]; 

    [_round setHidden:NO]; 
    [_round startAnimating]; 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 
     [t returnIP]; 
     dispatch_async(dispatch_get_main_queue(), ^{ 
     [_round stopAnimating]; 
     [_round setHidden:NO]; 
     [_lab setText:[t IP]]; 
     }); 
     }); 

} 

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

Как я могу выполнить этот процесс?

Является ли мой подход совершенно неправильным?

Благодарим за помощь.

+1

Используйте шаблон завершения блока параметров: http://stackoverflow.com/a/26174930/1271826 – Rob

ответ

0

Благодаря @Rob, который прокомментировал мое сообщение, я реализовал решение на основе блоков.

Вот обновленный класс заголовка

#import <Foundation/Foundation.h> 

@interface tclass : NSObject 

- (void)returnIP:(void (^)(NSString *ip))completionHandler; 

@end 

и реализация

#import "tclass.h" 

@implementation tclass 

- (id)init { 
    self = [super init]; 
    return self; 
} 

- (void)returnIP:(void (^)(NSString *ip))completionHandler { 

    NSURLSession *session = [NSURLSession sharedSession]; 
    [[session dataTaskWithURL:[NSURL URLWithString:@"http://icanhazip.com/"] 
      completionHandler:^(NSData *data, 
           NSURLResponse *response, 
           NSError *error) { 
       if(completionHandler) { 
        completionHandler([NSString stringWithUTF8String:[data bytes]]); 
       } 
      }] resume]; 
} 

@end 

Механизм, используемый для вызова этого метода немного изменился:

- (IBAction)butact:(id)sender { 
    tclass *t = [[tclass alloc]init]; 

    [_round setHidden:NO]; 
    [_round startAnimating]; 

    [t returnIP:^(NSString *ip) { 
     NSLog(@"%@", ip); 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [_round stopAnimating]; 
      [_round setHidden:YES]; 
      [_lab setText:ip]; 
     }); 
    }]; 

} 
+1

Было бы лучше включить способ передачи ошибка (если нужно) в вашем блоке. Вы можете либо изменить тип возвращаемого значения на id, либо проверить, является ли это строкой или объектом NSError, либо обработчик завершения возвращает строку и объект ошибки (один из которых будет равен нулю в любом возврате). – rdelmar

+0

Спасибо за ваш комментарий, я все еще учась управлять ошибками в Obj-C и возвращать как строку, так и объект ошибки, кажется, лучший выбор. – PeppeLaKappa

Смежные вопросы