簡體   English   中英

AFNetworking從錯誤的端點獲取響應JSON

[英]AFNetworking getting response JSON from the wrong endpoint

我在代碼中看到了一個非常奇怪的隨機問題,無法追蹤。 從AFNetworking JSON請求方法返回時,我的數據模型init方法崩潰。 當應用程序崩潰時,我可以返回調用堆棧以調試JSON請求/響應的內容。 奇怪的是,當我檢查URL,請求和resonseJSON時。 responseJSON與URL /請求的預期結果不匹配。 就像我正在獲取其他一些API方法調用和數據一樣。 因為數據/ JSON不是我期望的,所以應用程序將在模型初始化時崩潰。

我獲取的數據通常是不同的,並不總是相同的。 有時數據是來自端點A的,有時是來自B的,這永遠是不一致的。 但是,它似乎在同一模型對象中始終崩潰。

請求端點A數據,但我取回端點B數據。 當我崩潰時調試AFHttpOperation時,我看到的是結果。 幾乎就像有2個電話被越過一樣,這是某種競爭狀況。 以下是我的模型對象,Rest客戶端和模型訪問層的示例。

模型對象

@implementation Applications

- (id)initWithData:(NSDictionary *)appData forLocation:(Location *)location inCategory:(Category *)category {
    // appData is the JSON returned by The Rest Client and AFNetworking
    self = [super init];
    DDLogVerbose(@"appData = %@", appData);
    if (self) {
        _location = location;
        _listeners = [NSMutableArray mutableArrayUsingWeakReferences];
        _devices = [[NSMutableDictionary alloc] init];
        _category = category;
        _subscriptions = [Utility sanitizeArray:appData[@"Subscriptions"]];
    }
    return self;
}

@end

@implementation Location

- (void)refreshApplications {
    [[Model shared] appsForLocation:self 
                            success:^(NSObject *obj) {
        self.apps = nil; //we have to get our apps again
        self.apps = [NSMutableArray array];

        NSArray *newApps = (NSArray *) obj;
        for (NSDictionary *app in newApps) {
            **// This is where it's crashing!**
            Applications *newApp = [[Applications alloc] initWithData:app
                                                          forLocation:self
                                                           inCategory:[[SmartAppCategory alloc] init]];
            [self.apps addObject:newApp];
        }

        [self notifyListeners];
    }
                            error:nil];
}

@end

休息客戶

@interface Rest

+ (Rest *)sharedClient;
- (void)GET:(NSString *)path parameters:(NSDictionary *)params success:(SuccessCallback)sCallback error:(ErrorCallback)eCallback;

@end

@implementation Rest

+ (Rest *)sharedClient {
    static dispatch_once_t token;
    static Rest *shared = nil;
    dispatch_once(&token, ^{
        shared = [[Rest alloc] init];
    });
    return shared;
}

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

- (void)createClients {
    // Setup the Secure Client
    // Private implementation properties
    self.secureClient = [[AFOAuth2Client alloc] initWithBaseURL:baseUrl clientID:OAUTH2_CLIENT_ID secret:OAUTH2_CLIENT_SECRET];
    [self.secureClient setParameterEncoding:AFJSONParameterEncoding];
    AFOAuthCredential *credential = (AFOAuthCredential *) [NSKeyedUnarchiver unarchiveObjectWithData:[KeyChainStore dataForKey:KEYCHAIN_SETTINGS_AFOAuthCredential]];
    if (credential) {
        [self.secureClient setAuthorizationHeaderWithToken:credential.accessToken];
    }

    // Setup the Anonymous Client
    self.anonymousClient = [[AFHTTPClient alloc] initWithBaseURL:baseUrl];
    [self.anonymousClient setParameterEncoding:AFJSONParameterEncoding];
    [self.anonymousClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
}

- (void)GET:(NSString *)path parameters:(NSDictionary *)params success:(SuccessCallback)sCallback error:(ErrorCallback)eCallback {

    [_secureClient getPath:path
                parameters:params
                   success:^(AFHTTPRequestOperation *operation, id responseObject) {
                       DDLogVerbose(@"Success Path: %@ JSON: %@", path, responseObject);
                       if (sCallback) sCallback(responseObject);
                   }
                   failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                       [Rest callErrorBlock:eCallback withOperation:operation];
                   }];
}

@end

模型訪問層

@interface Model

+ (Model *)shared;
- (void)appsForLocation:(Location *)location success:(SuccessCallback)success error:(ErrorCallback)error;

@end

@implementation Model

- (void)appsForLocation:(Location *)location success:(SuccessCallback)success error:(ErrorCallback)error {
    NSString *path = [NSString stringWithFormat:@"/api/locations/%@/apps/", location.locationId];

    [[Rest sharedClient] GET:path parameters:nil success:success error:error];
}

@end

位置是應用程序中的根對象,將被告知經常刷新。 通過UI交互,事件或數據反序列化,refreshApplications將執行以從服務器獲取更多數據。 同時,其他請求和事件正在應用程序中進行,以獲取和發送數據到JSON。 這些對其他端點的GET調用中似乎有些混亂了響應數據。

問題

  1. AFNetworking怎么會這樣?
  2. 我是否太過責怪AFNetowrking了嗎?我是否應該在系統中尋找其他可能跨越響應的地方? 我確實在Amazon托管了一個負載平衡后端。
  3. 這是端點問題嗎?
  4. 如何更好地調試和重現此問題? 它僅在隨機時間出現,並且很難復制。 我必須不斷運行並重新運行該應用程序,以希望它崩潰。
  5. 是否可以使用xcode追溯跟蹤此調用/崩潰的任何高級調試技術?

我建議您使用Charles代理仔細檢查接收的數據是否正確。 提供30天的試用版,與注冊版相同。 我的第一個猜測是您和您的服務器之間存在某種錯誤的緩存層,或者您的服務器錯誤。 像Charles這樣的HTTP代理將允許您確認或拒絕該假設。

本頁說明如何設置Charles來代理來自iOS設備的非HTTPS連接。

要調試非HTTPS以及HTTPS流量,請使用mitmproxy

它使您可以檢查所有軟件包,還可以重新發送它們等等。 使用此工具,您可以檢查實際發生的情況以及后端是否有問題或AFNetworking是否存在錯誤。

作為一個很酷的副作用, mitmproxy是完全免費的,並且根據MIT許可是開放源代碼的。 在他們的網站上,您將找到一些專門針對iOS的便捷教程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM