0

Here is the simple code:

// let's assume that I have to allocate this variable with alloc/init
NSString *someString = [[NSString alloc] initWithFormat:"%@", @"someString"];

NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
  [someClass someFunction: someString];
}];

[queue addOperation:op]

[someString release];

This code will crash when nsblockoperation gets ran since someString is released. What is the best practice to prevent this?

Thank you.

EDIT: ARC is not a choice as it's not my decision to make. Any way to get around this in MRC?

EDIT2: What about following code? Would it work?

// let's assume that I have to allocate this variable with alloc/init
NSString *someString = [[NSString alloc] initWithFormat:"%@", @"someString"];

[someString retain]
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
  [someClass someFunction: someString];
  [someString release]
}];

[queue addOperation:op]

[someString release];
  • 1
    WHY on earth are you not using ARC? – Lord Zsolt Jun 25 '14 at 19:49
  • If it's not your decision to make, then pick up a hammer and smack the person who wants to to use MMR in the head as damn hard as you can. – Lord Zsolt Jun 25 '14 at 20:04
  • Thanks for the suggestion. Unfortunately that's not an option either. Any other options?? – user3776727 Jun 25 '14 at 20:07
  • It is possible to turn ARC off/on at the file level. Maybe use ARC in this one case. It will save you headaches. That said, you have a potential leak here if the operation is never executed (eg: gets cancelled). Also, there's no need to add the extra retain after you alloc it--just omit that and the release (after the addOperation). However, there's no easy way to fix the case of releasing the string if the operation gets cancelled. You're probably best off creating your own NSOperation class which retains the string and releases it when the operation is dealloc'd. – Nicholas Hart Jun 25 '14 at 20:33

2 Answers2

0
// let's say the variable is allocated with alloc/init
NSString *someString = [[[NSString alloc] initWithFormat:"%@", @"someString"] autorelease];

NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
  [someClass someFunction: someString];
}];

[queue addOperation:op];

There are hundreds of thousands of apps around that need to be maintained and do not use ARC. Wrap the string in an autorelease. I think that should work but I did not test.

Joseph Nardone
  • 457
  • 2
  • 15
-1

You really should use Automatic Reference Counting, and simplify the code to

// let's say the variable is allocated with alloc/init
NSString *someString = @"someString";

NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
  [someClass someFunction: someString];
}];

[queue addOperation:op]

If you really have to use Manual Reference Counting you can do this:

// let's assume that I have to allocate this variable with alloc/init
NSString *someString = [[NSString alloc] initWithFormat:"%@", @"someString"];

NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
  [someClass someFunction: someString];
  [someString release]
}];

[queue addOperation:op]

I know its just example code, but if it were not you could also do this... ;)

NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
  [someClass someFunction:@"someString"];
}];

[queue addOperation:op]
Michael
  • 6,451
  • 5
  • 31
  • 53
  • Thanks for your suggestion. However, ARC is not a choice for me. Any work around with MRC? I also edited my OP. Sorry for not mentioning it . – user3776727 Jun 25 '14 at 20:03
  • @user3776727 hmm, maybe if you provide some real code? In the code you posted, you can just replace `someString` with `@"someString"` and dump the variable `someString` outside of the block completely, including the `-release`. – Michael Jun 25 '14 at 20:12
  • @user3776727 furthermore, `[[NSString alloc] initWithFormat:"%@", "someString"]` would crash, because you are missing a `@` in front of `"someString"` (I doubt that "some" translates to a proper 32-bit-`isa`-pointer...) – Michael Jun 25 '14 at 20:14
  • I cannot do that either. I cannot change 2 things from the code I posted. 1. ARC -> MRC 2. using alloc/init when creating variable. Given that, there is no way to get around this I guess?? – user3776727 Jun 25 '14 at 20:16
  • Ha I was thinking the same thing, but, adding retain/release set instead of moving release into the block(Please check my OP, EDIT2). You think that would work? – user3776727 Jun 25 '14 at 20:30
  • @user3776727 I know that my code works... but it's hard to tell if your real code would work if you don't post it. you don't want to pass `someString` into a block like this. you would just use my third block and avoid all memory management issues. The fact that you forget a `@` in the first revision of your question proves that you just made the code up and that it isn't code that you are using productively... this is all a bit abstract... – Michael Jun 25 '14 at 20:35