Re: Arc and performSelector
Re: Arc and performSelector
- Subject: Re: Arc and performSelector
- From: David Duncan <email@hidden>
- Date: Mon, 17 Oct 2011 10:05:37 -0700
On Oct 15, 2011, at 11:58 PM, Gerriet M. Denkmann wrote:
> I have this code:
>
> for( id aThing in someArray )
> {
> if ( [ aThing respondsToSelector: @selector(setTitle:) ] )
> {
> [ self replaceIn: aThing
> readSelector: @selector(title)
> writeSelector: @selector(setTitle:)
> withTable: tableName
> ];
> }
> }
>
>
> - (void)replaceIn: thing readSelector: (SEL)selectorIn writeSelector: (SEL)selectorOut withTable: (NSString *)tableName;
> {
> NSString *key = [ thing performSelector: selectorIn ];
> ...
> NSString *rep = ...
> [ thing performSelector: selectorOut withObject: rep ];
> }
>
> Now, using Arc I am told that "PerformSelector may cause a leak because its selector is unknown".
> What I am supposed to do about this? I really want to have code without warnings.
ARC can't see the selector you pass to know if it conforms to the memory management policy implied by the -performSelector* calls, hence it reports this warning. If you called [thing performSelector:@selector(copy)] for example, you would leak. If you called [thing performSelector:@selector(release)] (not valid in ARC, but possibly if the selector is passed back by other means) you would over-release and crash.
In general the recommendation for something like this would be to replace this code with something safer, such as with blocks or protocols. Other solutions would involve either calling objc_msgSend() directly or disabling the warning (either of which should probably be considered only after determining that a block or protocol solution is undesirable).
Given what you've provided here, I would be partial to a block solution for this. Assuming that your -replaceIn:::: method does something complex between the read & write, you could rewrite the main loop to do something like this:
[self setValue: ^(id value) { [aTable setTitle:value]; } fromTable: tableName withKey: ^ { return [aTable title]; }];
Note there is no need to pass in 'aTable' now because the blocks capture it instead, which can also provide you with additional flexibility to use this method elsewhere.
--
David Duncan
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden