How to transfer ownership of @autoreleasepool using ARC

I have the following code

- (NSString *)stringByEscapingXMLEntities; { NSString *result; @autoreleasepool { result = [self stringByReplacingOccurrencesOfString:@"&" withString:@"&"]; result = [result stringByReplacingOccurrencesOfString:@"\"" withString:@"""]; // ... lot of -stringByReplacingOccurrencesOfString: calls result = [result stringByReplacingOccurrencesOfString:@" " withString:@" "]; } return result; } 

Now I ask myself how to pass the result method from the method. Before ARC, I would save the result before exiting the autoadvertising block and returning it auto-implemented at the end of the method.

Thanks!

+4
source share
4 answers

There are two ways to do this:

  • Rename the method to something like copyStringByEscapingXMLEntities - copy indicates the transfer of ownership, and ARC creates the appropriate code.
  • Add a method definition to the NS_RETURNS_RETAINED header as follows: - (NSString *)stringByEscapingXMLEntities NS_RETURNS_RETAINED .

EDIT: As mentioned in "iljawascoding", @autoreleasepool does not need to be supported other than optimization.


EDIT 2: And remember: ARC always does the right thing. Everything that you tried (your comment) leads to the same correct program, although with the absence of some optimization if the result was defined as __strong .

+4
source

Get rid of auto-advertising in general. According to Apple, ARC automatically inserts the required release after your code is executed with temporary instances stored in the "result". There is nothing to gain by rolling your own abstract here.

+2
source

The code you posted is correct. Any accident has a different cause.

Since result is a strong link outside the scope of auto-advertising, ARC is responsible for maintaining its performance when exiting the pool, and this happens. You do not have to do anything.

More specifically, ARC generates code equivalent to this:

 void *_arp = objc_autoreleasePoolPush(); temp1 = objc_retainAutoreleasedReturnValue([self stringByReplacingOccurrencesOfString:@"&" withString:@"&"]); temp2 = objc_retainAutoreleasedReturnValue([temp1 stringByReplacingOccurrencesOfString:@"\"" withString:@"""]); objc_release(temp1); result = objc_retainAutoreleasedReturnValue([temp2 stringByReplacingOccurrencesOfString:@" " withString:@" "]); objc_release(temp2); // result is not released here objc_autoreleasePoolPop(_arp); return objc_autoreleaseReturnValue(result); // Result is returned autoreleased, or handed off to a matching objc_retainAutoreleasedReturnValue() in the caller. 

Note that temporary variables are handled by objc_retainAutoreleasedReturnValue / objc_release . Due to the runtime optimization implemented in objc_retainAutoreleasedReturnValue and objc_retainAutoreleasedReturnValue , this means that temporary values ​​will actually be released immediately, even if they are not put into the autorun pool if -stringByReplacingOccurrencesOfString: built using. I assume that most system frameworks have not yet been created.

+2
source

Why not use [[NSString alloc] initWithString:result] before closing the @autoreleasepool ? But why ARP in the first place?

0
source

Source: https://habr.com/ru/post/1391417/


All Articles