Я хочу реализовать следующее: иметь собственный класс (чтобы я мог вызывать / использовать его из многих частей моего приложения), где с помощью AFNetworking я запрашиваю сервер и получаю ответ. Мой код внутри класса работает, но когда я вызываю его из других частей своего приложения, я получаю нулевое значение. Я верю в это из-за моего собственного класса. В любом случае вот мой код:

UDIDGen.h

#import <Foundation/NSString.h>
@interface NSString (UDIDGen)
+ (NSString *)getUDID;
@end

UDIDGen.m

#import "UDIDGen.h"
#import "AFHTTPClient.h"
#import "AFHTTPRequestOperation.h"

@implementation NSString (UDIDGen)

+ (NSString *)getUDID{
    __strong __block NSString *holder;

    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://domain.com/id.php"]];
    NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET"
                                                            path:@"http://domain.com/id.php"
                                                      parameters:nil];
    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    [httpClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        holder=[NSString stringWithFormat:@"%@",[[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]];
        NSLog(@"SERVER RESPONSE: %@",holder);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    }];
    [operation start];
    return holder;
}
@end

А затем, когда я захочу вызвать его из других частей своего приложения, я

#import "UDIDGen.h"

А потом

 NSString *wsa=[NSString getUDID];
 NSLog(@"Response %@",wsa);

По некоторым причинам NSLog(@"SERVER RESPONSE: %@",holder); работает, и я могу занести в журнал ответ сервера. Но NSString *wsa=[NSString getUDID]; дает мне нулевое значение. Я считаю, что это связано с тем, как я реализую свой собственный класс, я делаю что-то не так. Любая помощь?

РЕДАКТИРОВАТЬ : мой рабочий код, чтобы его использовали другие:

UDIDGen.h

#import <Foundation/NSString.h>
@interface UDIDGen:NSObject{

}
- (void)getUDIDWithCompletion:(void (^)(NSString *udid))completion;
@end

UDIDGen.m

#import "UDIDGen.h"
#import "AFHTTPClient.h"
#import "AFHTTPRequestOperation.h"

@implementation UDIDGen

- (void)getUDIDWithCompletion:(void (^)(NSString *udid))completion {
    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://domain.com/id.php"]];
    NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET"
                                                            path:@"http://domain.com/id.php"
                                                      parameters:nil];
    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    [httpClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSString *udid=[[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
        NSLog(@"SERVER RESPONSE: %@",udid);
        if (completion)
        {
            completion(udid);
        }
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        //  TODO: Handle error
    }];
    [operation start];
}
@end

Используйте это так:

UDIDGen *getResponse = [[UDIDGen alloc] init];

    [getResponse getUDIDWithCompletion:^(NSString *udid) {
        NSLog(@"SERVER RESPONSE: %@",udid);
    }];
1
Theodoros80 5 Окт 2013 в 20:36
Фактически блоки были реализованы асинхронным способом, поэтому, когда вы вернули объект-держатель, вызвав метод getUDID, к тому времени значение для этого объекта-держателя не было присвоено. Итак, просто попробуйте вернуть значение в успешном блоке. просто вернитесь из строки NSLog.
 – 
Bharath
7 Окт 2013 в 11:50

1 ответ

Лучший ответ

Вы запускаете AFHTTPRequestOperation асинхронно. Это означает, что он работает в отдельном неблокирующем потоке, и ваш метод может вернуться до завершения запроса.

Самый простой способ - просто сделать это, но это, скорее всего, заблокирует графический интерфейс при загрузке:

[operation startSynchronous];

Самый чистый способ - использовать блок завершения или делегировать себя и проинформировать целевой класс о получении ответа:

+ (void)getUDIDWithCompletion:(void (^)(NSString *udid))completion {
    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://domain.com/id.php"]];
    NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET"
                                                            path:@"http://domain.com/id.php"
                                                      parameters:nil];
    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    [httpClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSString *udid=[[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
        NSLog(@"SERVER RESPONSE: %@",udid);
        if (completion)
        {
            completion(udid);
        }
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        //  TODO: Handle error
    }];
    [operation start];
}

Вы бы назвали этот метод так:

[YourCustomClass getUDIDWithCompletion:^(NSString *udid) {
   // use udid / update GUI
}];
1
Andreas Ley 5 Окт 2013 в 21:03
Что ж, [операция waitUntilFinished] заблокировала мой графический интерфейс. Любой пример кода? Любая ссылка?
 – 
Theodoros80
5 Окт 2013 в 20:51
Я добавил пример.
 – 
Andreas Ley
5 Окт 2013 в 21:11