objective c - iOS selector crashes the App -
i created simple httpclient afnetworking.
httpclient *client = [[httpclient alloc] initwithtarget:(id)target before:(sel)before success:(sel)success failure:(sel)failure timeout:(sel)timeout]
so controller can register callback function when perfroms http request. , here how wrote callback functions:
- (void)successmethod:(id)response { // logdebug(@"success: %@", response); self.lock = false; if (self.target == nil || self.successcallback == nil) { return; } if ([self.target respondstoselector:self.successcallback]) { [self.target performselector:self.successcallback withobject:response]; } }
but here found problem. when request comes fast, works fine. if request comes after longtime , meanwhile, user changes view. crashes app , throw exception like, selector can not performed on nil object.
so want know whether did in right way , there way solve problem? best practices implement this?
=====
update:
sorry didn't put error log. there no information can get. sometime there no log. put screenshot here , hope can help.
i , there no exception log.
==== update
and hope can help
#import "httpclient.h" #import "afnetworking.h" #import "logging.h" @interface httpclient () @property int retrycounter; @property(nonatomic) nsstring *action; @property(nonatomic) nsstring *url; @property(nonatomic) nsdictionary *param; @property(nonatomic) afhttprequestoperationmanager *manager; @end @implementation httpclient - (id)initwithtarget:(id)target before:(sel)before success:(sel)success failure:(sel)failure timeout:(sel)timeout { self = [super init]; if (self) { self.target = target; self.before = before; self.success = success; self.failure = failure; self.timeout = timeout; self.lock = false; self.retrymaxcounter = 2; self.retrycounter = 0; self.manager = [afhttprequestoperationmanager manager]; self.manager.requestserializer = [afjsonrequestserializer serializer]; self.manager.responseserializer = [afjsonresponseserializer serializer]; } return self; } - (void)request:(nsstring *)action url:(nsstring *)url param:(nsdictionary *)param { self.action = action; self.url = url; self.param = param; [self beforemethod]; [self request]; } - (void)request { if (self.lock) { return; } if ([[self.action lowercasestring] isequal:@"get"]) { // logdebug(@"send request."); self.lock = true; loginfo(@"%@\n%@", self.url, self.param); [self.manager get:self.url parameters:self.param success:^(afhttprequestoperation *operation, id responseobject) { [self successmethod:responseobject]; } failure:^(afhttprequestoperation operation, nserror error) { if ([operation.response statuscode] == 500) { [self failuremethod:operation.responseobject]; } else { [self timeoutmethod]; } }]; } else if ([[self.action lowercasestring] isequal:@"post"]) { // post logdebug(@"send post request."); self.lock = true; loginfo(@"%@\n%@", self.url, self.param); [self.manager post:self.url parameters:self.param success:^(afhttprequestoperation *operation, id responseobject) { [self successmethod:responseobject]; } failure:^(afhttprequestoperation operation, nserror error) { if ([operation.response statuscode] == 500) { [self failuremethod:operation.responseobject]; } else { [self timeoutmethod]; } }]; } else { logerror(@"not supported request method."); } } #pragma clang diagnostic push #pragma clang diagnostic ignored "-warc-performselector-leaks" - (void)beforemethod { logdebug(@"before requesting."); if (self.target == nil || self.before == nil) { return; } if ([self.target respondstoselector:self.before]) { [self.target performselector:self.before]; } } - (void)successmethod:(id)success { // logdebug(@"success: %@", success); self.lock = false; if (self.target == nil || self.success == nil) { return; } if ([self.target respondstoselector:self.success]) { [self.target performselector:self.success withobject:success]; } } - (void)failuremethod:(id)failure { logdebug(@"failure: %@", failure); self.lock = false; if (self.target == nil || self.failure == nil) { return; } if ([self.target respondstoselector:self.failure]) { [self.target performselector:self.failure withobject:failure]; } } - (void)timeoutmethod { logerror(@"request timeout."); self.lock = false; self.retrycounter++; if (self.retrycounter < self.retrymaxcounter) { [self request]; } else { if (self.target == nil || self.timeout == nil) { return; } if ([self.target respondstoselector:self.timeout]) { [self.target performselector:self.timeout]; } } } #pragma clang diagnostic pop @end
thank much!
==== update
i found problem. because set targe assign
instead of weak
. difference between assign
, weak
, please refer stackoverflow question
there not enough information problem. can guess possible reason.
i guess add target first request, works okay, when make second request, there 2 targets perform selector. first object released can't perform selector.
you have remove target not in use.
Comments
Post a Comment