【问题标题】:AFnetworking 3 or 4 GET ResponseObject how to have responseString and ResponseDataAFnetworking 3 或 4 GET ResponseObject 如何拥有 responseString 和 ResponseData
【发布时间】:2021-03-04 15:26:52
【问题描述】:

您好,我想知道responseStringresponseObject 的新版本AFNetworking 是如何实现的。

当我进行 GET 操作时,我得到了 NSURLSessionDataTaskid responseData 的成功响应。

我想要responseStringresponseObject

感谢您的帮助。

【问题讨论】:

  • responseObject 您需要使用AF...ResponseSerializer(github.com/AFNetworking/AFNetworking/tree/…),根据您的解析器,您将拥有一个字典、数组等。对于responseString,它只是[[NSString alloc] initWithData: responseData encoding: NSUTF8StringEncoding],这里没什么特别的。
  • bonjour en faite j'avais deja commencé a faire ça pour le responseString cependant j'ai cette erreur là de temps en temps et qui me fait cracher l'application。异常 NSException * "-[__NSSingleEntryDictionaryI bytes]: 无法识别的选择器发送到实例 0x600000ae1b60" 0x00006000000f65e0
  • 我是法国人,所以没关系,但我建议你用英文写。 "[__NSSingleEntryDictionaryI bytes] 哪里?它说你认为一个对象是NSData,但实际上它是NSDictionary,但我们猜不出有什么问题。
  • 因此,当我使用 NSURLSessionDataTask 和 id responseObject 获取请求并收到成功时。我收到和 XML 值,但我想复制 responseObject 以更改为 responseString 并且当我制作 [[NSString alloc] initWithData: responseData encoding: NSUTF8StringEncoding] 时。应用程序崩溃并出现此错误 'NSInvalidArgumentException',原因:'-[NSXMLParser dataUsingEncoding:]: or Exception NSException * "-[__NSSingleEntryDictionaryI bytes]: unrecognized selector if I have other format
  • 你能展示你的完整代码吗?因为看起来你放了一个响应序列化,如果我不得不猜测的话,一个 JSON 序列化..

标签: ios swift afnetworking afnetworking-3


【解决方案1】:

很快,我实现了自己的 ResponseSerializer,它只是一种封装 AFNetworkingSerializer 的方法(~AFHTTPResponseSerializer 是其他的超类,并尊重AFURLResponseSerialization 协议),它将返回一个自定义序列化对象, 除了 NSDictionary/NSArray 序列化对象之外,它还将具有您想要的 2 个属性:NSDataNSString

.h

@interface CustomResponseSerializer : NSObject <AFURLResponseSerialization>
-(id)initWithResponseSerializer:(id<AFURLResponseSerialization>)serializer;
@end

.m

@interface CustomResponseSerializer()
@property (nonatomic, strong) id<AFURLResponseSerialization> serializer;
@end

@implementation CustomResponseSerializer

-(id)initWithResponseSerializer:(id<AFURLResponseSerialization>)serializer {
    self = [super init];
    if (self)
    {
        _serializer = serializer;
    }
    return self;
}

- (nullable id)responseObjectForResponse:(nullable NSURLResponse *)response data:(nullable NSData *)data error:(NSError * _Nullable __autoreleasing * _Nullable)error {

    id serialized = nil;
    if ([_serializer respondsToSelector:@selector(responseObjectForResponse:data:error:)]) {
        NSError *serializationError = nil;
        serialized = [_serializer responseObjectForResponse:response data:data error:&serializationError];
    }
    //You could put NSError *serializationError = nil; before, and set it into the `CustomSerializedObject` `error` property, I didn't check more about AFNetworking and how they handle a parsing error
    
    return [[CustomSerializedObject alloc] initWithData:data
                                                 string:[[NSString alloc] initWithData:data encoding: NSUTF8StringEncoding]
                                                 object:serialized];
}

+ (BOOL)supportsSecureCoding {
    return YES;
}

- (void)encodeWithCoder:(nonnull NSCoder *)coder {
    [coder encodeObject:self.serializer forKey:NSStringFromSelector(@selector(serializer))];
}

- (nullable instancetype)initWithCoder:(nonnull NSCoder *)coder {
    self = [self init];
    if (!self) {
        return nil;
    }

    self.serializer = [coder decodeObjectForKey:NSStringFromSelector(@selector(serializer))];
    return self;

}

- (nonnull id)copyWithZone:(nullable NSZone *)zone {
    CustomResponseSerializer *serializer = [[CustomResponseSerializer allocWithZone:zone] init];
    serializer.serializer = [self.serializer copyWithZone:zone];
    return serializer;
}
@end

还有对象:

@interface CustomSerializedObject: NSObject
@property (nonatomic, strong) NSData *rawData;
@property (nonatomic, strong) NSString *string;
@property (nonatomic, strong) id object;
@property (nonatomic, strong) NSError *error; //If needed

-(id)initWithData:(NSData *)data string:(NSString *)string object:(id)object;
@end
@implementation CustomSerializedObject

-(id)initWithData:(NSData *)data string:(NSString *)string object:(id)object {
    self = [super init];
    if (self)
    {
        _rawData = data;
        _string = string;
        _object = object;
    }
    return self;
}
@end

使用方法:

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];

NSURL *URL = [NSURL URLWithString:@"https://httpbin.org/get"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];

CustomResponseSerializer *responseSerializer = [[CustomResponseSerializer alloc] initWithResponseSerializer:[AFJSONResponseSerializer serializer]];
[manager setResponseSerializer: responseSerializer];
NSURLSessionDataTask *task = [manager dataTaskWithRequest:request
                                           uploadProgress:nil
                                         downloadProgress:nil
                                        completionHandler:^(NSURLResponse * _Nonnull response, CustomSerializedObject * _Nullable responseObject, NSError * _Nullable error) {
    NSLog(@"Response: %@", response);
    NSLog(@"ResponseObject data: %@", responseObject.rawData); //If you want hex string ouptut see https://stackoverflow.com/questions/1305225/best-way-to-serialize-an-nsdata-into-a-hexadeximal-string
    NSLog(@"ResponseObject str: %@", responseObject.string);
    NSLog(@"ResponseObject object: %@", responseObject.object);
    NSLog(@"error: %@", error);
}];
[task resume];

【讨论】:

    【解决方案2】:

    我的代码不是完整的代码,但就是这样

    void(^wsFailure)(NSURLSessionDataTask *, NSError *) = ^(NSURLSessionDataTask *failedOperation, NSError *error) {
    
             NSLog(@"failed %@",failedOperation);
    
            [self failedWithOperation:failedOperation error:error];
          };
          void (^wsSuccess)(NSURLSessionDataTask *, id) = ^(NSURLSessionDataTask * _Nonnull succeedOperation, id _Nullable responseObject) {
                   NSLog(@"responseData: %@", responseObject);
                NSString *str = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
                NSLog(@"responseData: %@", str);
    
        }}
    
    
    AFHTTPResponseSerializer *responseSerializer = [self responseSerializerFromResponseType];
        AFHTTPRequestSerializer *requestSerializer = [self requestSerializerFromRequestType];
    
    operationManager.requestSerializer = requestSerializer;
    operationManager.responseSerializer = responseSerializer;
    - (AFHTTPResponseSerializer *)responseSerializerFromResponseType{    
    if ([self.request.parameters[@"responseType"] isEqualToString:@"xml"]) {
            return [AFXMLParserResponseSerializer serializer];
        }
        else if ([self.request.parameters[@"responseType"] isEqualToString:@"html"]) {
            return [AFHTTPResponseSerializer serializer];
        }}
    

    【讨论】:

    • 如果你使用 XML 响应序列化器,你会得到 Dictionary 而不是 NSData。顺便说一句,你为什么需要它?
    • 有时我收到 json 响应,有时我在 responseObject 中收到 xml 响应。但我想处理对做出的响应字符串的响应。当我想处理响应时,我有这个错误 NsxmlParser 或 NSdictionnary.'NSInvalidArgumentException',原因:'-[NSXMLParser dataUsingEncoding:]: or Exception NSException * "-[__NSSingleEntryDictionaryI bytes]: unrecognized selector.
    • 我的 responseObject 有时像这个值,所以我将在 responseObject _NSInlineData * 929 字节之后将响应转换为处理数据
    • 对于 json 请求,我收到 responseObject __NSSingleEntryDictionaryI * 1 键/值对,所以没关系,对于 xml,我有这个 responseObject NSXMLParser *
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-30
    • 1970-01-01
    • 2013-10-05
    • 1970-01-01
    • 1970-01-01
    • 2013-12-06
    • 1970-01-01
    相关资源
    最近更新 更多