Singleton release method produces warning? - objective-c

In my singleton release method, I have it doing nothing:
-(void) release {
//A whole lot of nothing.
}
But it produces this warning:
Warning: Conflicting distributed object modifiers on return type in implementation of 'release'
I googled and saw others have the same error, but no explanation of the warning. Anyone know what the warning is about?

You need to declare it oneway.
- (oneway void) release {}
oneway is a keyword used with distributed objects to indicate that the call can be made asynchronously. Since the NSObject header uses it when it declares the release method, you must also use it. It won't affect your program unless you use distributed objects, but it will satisfy the compiler.

In NSObject.h, the definition of the release method returns a oneway void.
The oneway keyword is used for distributed objects.
Since Xcode4.2 and LLVM, checkings are more strong and if it was accepted by previous versions of Xcode or by gcc, you now need to add this oneway keyword so that the LLVM compiler stops warning about this.
-(oneway void) release { /* do nothing */ }
This won't have any incident on your code.

Related

Why would compiler give an error if a method get called cannot be found within the given glass since Objective-C checks it during runtime? [duplicate]

I heard that Objective-C is influenced by the "message passing mechanism" of SmallTalk.
Objective-C, like Smalltalk, can use dynamic typing: an object can be
sent a message that is not specified in its interface. This can allow
for increased flexibility, as it allows an object to "capture" a
message and send the message to a different object that can respond to
the message appropriately, or likewise send the message on to another
object.
And I felt for codes like [anObject someMethod], the binding of someMethod to the machine code may happen at run-time..
Therefore, I write a demo like this:
#import <Foundation/Foundation.h>
#interface Person : NSObject {
#private char *name;
}
#property (readwrite, assign) char *name;
- (void)sayHello;
#end
#implementation Person
#synthesize name;
- (void)sayHello {
printf("Hello, my name is %s!\n", [self name]);
}
#end
int main() {
Person *brad = [Person new];
brad.name = "Brad Cox";
[brad sayHello];
[brad sayHelloTest];
}
I tried [brad sayHelloTest] to send brad a message sayHelloTest which brad doesn't know how to handle with.. I expect the error will NOT happen at compile-time..
However, the compiler still throws an error:
main.m:24:11: error: instance method '-sayHelloTest' not found (return type defaults to 'id') [-Werror,-Wobjc-method-access]
[brad sayHelloTest];
^~~~~~~~~~~~
main.m:3:12: note: receiver is instance of class declared here
#interface Person : NSObject {
^
Change [(id)brad sayHelloTest] to [(id)brad sayHelloTest]; doesn't work either.. (The compiling command is clang -Wall -Werror -g -v main.m -lobjc -framework Foundation -o main)
In Objective-C, does the binding of method really happen at "run-time"? If so, why will there be a compiler error like this?
If the binding doesn't happen at "run-time", why was "Objective-C" called "dynamic typing language"?
Does anyone have any ideas about this?
One job of a compiler is to catch as many errors at compile time as possible. If it can tell that the call will fail at runtime, you generally want it to complain.
You can suppress this via casting to show that runtime resolution is happening:
[(id)brad sayHelloTest];
Because the IDE can infer the obvious error from the context.
When you write if (a = 1),you will get a warning. A good IDE should help you find mistakes as early as possible.
I figured out the reason finally..
It throw errors during compiling because -Werror flag is included, which will turn warning into error..
http://clang.llvm.org/docs/UsersManual.html#cmdoption-Werror
After I delete -Werror flag, everything works as expected and the error only happens at run-time.
It has become a compiler error only within the last five years for there to be no known declaration of a method. It has to do with Automatic Reference Counting. Under ARC, the compiler is now responsible for the reference-counting-based memory management that Cocoa uses.
Given that responsibilty, it must be able to see the declarations of methods for any messages before they are sent, so that it knows what retains and releases are appropriate.
The method resolution (the lookup of the method on the class) does still happen at runtime, and -- particularly if you disable ARC -- you can still take advantage of message forwarding.
One way around ARC's requirement was given by Marcelo Cantos -- cast the receiver to id. Another is to use performSelector:. A third -- though I can't recommend it -- is to use objc_msgSend() directly.
Note that the "binding" of the method does, and always did, happen at compile time. Methods are associated with classes, when the classes are defined. Messages are distinct from methods, and it is they that resolve at runtime to a method.

blocks and ARC - copy or crash with release build (caused by optimization level)

I'm using Xcode 4.3.3 and developing for iOS 5.0+. In development of an ARC iOS application, I've started using blocks as a callback mechanism for asynchronous operations. The app works fine in the simulator and on the device.
Then I ran it the profiler for the first time, and it started crashing on me nearly right away - in particular, an EXC_BAD_ACCESS when trying to invoke the first callback block.
After a little investigation, it was clear the difference in behavior was because the profiler runs in "Release mode" by default - in particular, with Optimization Level set to "Fastest, Smallest [-Os]" instead of "None [-O0]".
For example, the following code (simplified for this question) would crash when trying to execute the callbackBlock:
- (void) setCallbackBlock:(void (^)(NSString *input))block
{
callbackBlock = block;
}
- (void) invokeCallbackWithInput:(NSString *)input
{
if (callbackBlock) {
callbackBlock(input);
}
}
Debugging into it, calling setCallbackBlock with optimization level set to "None", the incoming block would be an NSStackBlock, and the callbackBlock would become an NSMallocBlock.
However, with Optimization Level "Fastest, Smallest", it remained an NSStackBlock.
Changing the setter code to use [block copy] fixes the crashing problem (based on iOS 5 blocks crash only with Release Build).
However, another related question indicates that this shouldn't be necessary with ARC - block variables are copied to the heap in ARC - Why does Objective-C block still work without copying it to the heap?
So my question: What's going on here, and why? (Also, how can both of those answers be correct...?)
Edit:
To clarify how callbackBlock is being declared - just above my #implementation where those methods are is this:
#interface MyClass ()
{
void (^callbackBlock)(NSString *input);
}
#end
So my question: What's going on here, and why? (Also, how can both of those answers be correct...?)
I actually think the answer to the other question is wrong, in that it doesn't answer that particular question about blocks in ARC. The question is about passing a stack based block from one function/method to another. The answer is about something different, which is capturing __block variables within a block. That's a different issue.
The answer to your question is in the FAQ of the Transitioning to ARC Release Notes:
Blocks “just work” when you pass blocks up the stack in ARC mode, such as in a return. You don’t have to call Block Copy any more. You still need to use [^{} copy] when passing “down” the stack into arrayWithObjects: and other methods that do a retain.
So the way this works is that when you pass a block (in your case a block literal allocated on the stack), the compiler does not copy that block when it initializes the parameter for that call. The called function or method has the responsibility to copy that block itself if needed.
Where ARC does copy blocks automatically is when you are returning a block from a function or method. In that case, the compiler knows that it must do a copy to the heap for you, and so it does.
So your setter should be doing a block copy, even with ARC.
I hope that helps.
This is a long comment on Firoze's answer.
The document Automatic Reference Counting" section 7.5 states:
With the exception of retains done as part of initializing a __strong parameter variable or reading a __weak variable, whenever these semantics call for retaining a value of block-pointer type, it has the effect of a Block_copy. The optimizer may remove such copies when it sees that the result is used only as an argument to a call.
And this is the behavior I have seen.
So if callbackBlock is a strong instance variable then ARC should copy any stack-allocated block pass in block. I.e. the Debug version was correct and the Release version is a compiler bug.
If this is correct then you've found a compiler bug and should report it. Reporting it would not be bad either way, it should produce a definitive answer.

Using __weak to modify storage of a parameter in implementation

Is it valid to use the __weak storage modifier in a method's implementation's signature? Especially if it is not part of the method's public signature? For example:
- (UIView *)tableView:(__weak UITableView *)tableView viewForHeaderInSection:(NSInteger)sectionIndex
{
UIView *view = [ABHeaderView view];
view.actionBlock = ^{
[tableView doSomething];
}
// ...
return view;
}
Does this correctly use tableView as a weak pointer? Or should I really do something like __weak *weakTableView = tableView; and use weakTableView within the block?
I do not get any warnings or errors and the clang Static Analyzer does not throw any warnings.
Don't count on storage modifiers or attributes to be honored 'dynamically' when dynamic dispatch is involved and overriding(1).
This method is formally declared in UIKit. The compiler may get it wrong when using ARC because it may match the selector to the original declaration when called. That is, your declaration is not visible to UIKit, and UIKit will treat it as default/strong if it's compiled as ARC as well. This could happen if the declarations do not match, or even if they are not visible in the client+caller translation.
Parameter types/attributes are not part of the selector, nor are they applied to dispatch dynamically. ARC should assume strong here, and that the caller holds the reference. This specific example may not cause a runtime error, but it's a questionable practice which I assume errors could be found. I've proven this for attributes in this answer. Fundamentally, it is a similar concept.
Simple rule with dynamic objc dispatch: Always match the signature of the original declaration when redeclaring, defining, and overriding. The only exception one might make is for C compatible qualifiers which would not alter the signature (a very uncommon practice in ObjC programs I've seen).
(1) technically, it's not an override, but an implementation of the protocol's method. regardless, the sig should be identical.
__strong or __weak storage modifiers are part of your internal implementation, as far as I can see. They do not influence the code generated by the caller of the method, so I think you're safe now and very likely in the future.
I do think it's poor style, though, so your suggestion of copying the reference to a weak reference seems a good solution.

Private Methods in Objective-C, in Xcode 4.3 I no longer need to declare them in my implementation file ?

I have a lot question marks tolling above my head.
What I don't get is before xcode 4.3 I needed to declare forward declarations (for private methods) in my implementation file.
Like in my .m file:
// deleting this with xcode 4.3 the below code still does work
// in previous versions i had to put this because otherwise the compiler can't find methodFirst
#interface DetailViewController ()
- (void)methodFirst;
- (void)methodSecond;
#end
#implementation DetailViewController
- (void) methodSecond
{
// if i delete the forward declaration now adays i dont get a compiler error that he cant find method first
[self methodFirst];
}
- (void) methodFirst
{
}
#end
Now it seems I don't need to do that anymore? Did Apple update the compiler so that it isn't needed anymore to put forward declarations?
I can't find any reference to an official Apple source about this change. I wonder what other people have encountered in their new environment.
As of the LLVM Compiler version shipped with Xcode 4.3, if you try to call a method that the compiler has not previously seen, it will look in the rest of the current #implementation block to see if that method has been declared later. If so, then it uses that, and you don't get a warning. Hence, as of Xcode 4.3, there's much less need to pre-declare your internal methods. Clearly, you still need to declare methods that are publicly exposed to other classes.
This change was noted in the release notes of some of the Xcode 4.3 betas, but apparently didn't make it into the "What's New in Xcode 4.3" final documentation.
Unlike has been suggested in other answers, this is not just an "Undeclared Selector" warning that has been turned off by default. In fact, if you're using ARC, unrecognized selectors are still hard errors. Try calling [self myNonexistentMethod] and you'll see; the compiler still complains.
There aren't any private methods in Objective-C. What you're thinking of is the class continuation, the "nameless" category interface you can declare in your .m file to declare methods that will be in the class implementation, but that aren't in the public interface.
There's never been a requirement to declare methods before they're used. However, it's always been a good idea, and the compiler has a warning flag to indicate when methods that haven't been seen are used. The reason is to do with the operating system's calling convention for functions. Different types, such as structures, floating point numbers, integer numbers, and pointers, can all be handled in different ways when they are the arguments to or return values from functions. Indeed, on different computers and in different operating systems, they are handled in different ways. To know how to handle the arguments and return values for an Objective-C method, the compiler needs to know the signature for that method: how many arguments of what types it takes, and what type it returns.
If it hasn't seen a declaration of the method, then the compiler will need to make a guess. If that guess is incorrect, then it can end up putting the wrong values into the arguments, or interpreting the return value incorrectly, or trying to take something off the stack that doesn't exist.

Did the Target-Action design pattern became bad practice under ARC?

For years I've been following a great pattern called Target-Action which goes like this:
An object calls a specified selector on a specified target object when the time comes to call. This is very useful in lots of different cases where you need a simple callback to an arbitrary method.
Here's an example:
- (void)itemLoaded {
[specifiedReceiver performSelector:specifiedSelector];
}
Under ARC it now turns out that doing something like this all of a sudden became dangerous.
Xcode throws a warning that goes like this:
PerformSelector may cause a leak because its selector is unknown
Of course the selector is unknown since as part of the Target-Action design pattern you can specify whatever selector you want in order to get a call when something interesting happens.
What bugs me most about this warning is that it says there can be a potential memory leak. From my understanding ARC doesn't bend the memory management rules but instead simply automates the insertion of retain/release/autorelease messages at the right locations.
Another thing to note here: -performSelector: does have an id return value. ARC analyzes method signatures to figure out through application of naming conventions if the method returns a +1 retain count object or not. In this case ARC doesn't know if the selector is a -newFooBar factory or simply calling an unsuspicious worker method (which is almost always the case with Target-Action anyways). Actually ARC should have recognized that I don't expect a return value, and therefore forget about any potential +1 retain counted return value. Looking at it from that point of view I can see where ARC is coming from, but still there is too much uncertainty about what this really means in practice.
Does that now mean under ARC something can go wrong which would never happen without ARC? I don't see how this could produce a memory leak. Can someone give examples of situations in which this is dangerous to do, and how exactly a leak is created in that case?
I really googled the hell out of the internet but didn't find any site explaining why.
The problem with performSelector is that ARC doesn't know what the selector which will performed, does. Consider the following:
id anotherObject1 = [someObject performSelector:#selector(copy)];
id anotherObject2 = [someObject performSelector:#selector(giveMeAnotherNonRetainedObject)];
Now, how can ARC know that the first returns an object with a retain count of 1 but the second returns an object which is autoreleased? (I'm just defining a method called giveMeAnotherNonRetainedObject here which returns something autoreleased). If it didn't add in any releases then anotherObject1 would leak here.
Obviously in my example the selectors to be performed are actually known, but imagine that they were chosen at run time. ARC really could not do its job of putting in the right number of retains or releases here because it simply doesn't know what the selector is going to do. You're right that ARC is not bending any rules and it's just adding in the correct memory management calls for you, but that's precisely the thing it can't do here.
You're right that the fact you're ignoring the return value means that it's going to be OK, but in general ARC is just being picky and warning. But I guess that's why it's a warning and not an error.
Edit:
If you're really sure your code is ok, you could just hide the warning like so:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[specifiedReceiver performSelector:specifiedSelector];
#pragma clang diagnostic pop
The warning should read like this:
PerformSelector may cause a leak because its selector is unknown. ARC doesn't know if the returned id has a +1 retain count or not, and therefore can't properly manage the memory of the returned object.
Unfortunately, it's just the first sentence.
Now the solution:
If you receive a return value from a -performSelector method, you can't do anything about the warning in code, except ignoring it.
NSArray *linkedNodes = [startNode performSelector:nodesArrayAccessor];
Your best bet is this:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
NSArray *linkedNodes = [startNode performSelector:nodesArrayAccessor];
#pragma clang diagnostic pop
Same goes for the case in my initial question, where I completely ignore the return value. ARC should be intelligent enough to see that I don't care about the returned id, and therefore the anonymous selector is almost guaranteed not to be a factory, convenience constructor or whatsoever. Unfortunately ARC is not, so the same rule applies. Ignore the warning.
It can also be done for the whole project by setting the -Wno-arc-performSelector-leaks compiler flag under "Other Warning Flags" in project build settings.
Alternatively, you can surpress the warning on a per-file basis when you add that flag under Your Target > "Build Phases" > "Compile Sources" on the right-hand side next to the desired file.
All three solutions are very messy IMHO so I hope someone comes up with a better one.
As described above you get that warning because the compiler does not know where (or if) to put the retain/release of the performSelector: return value.
But note that if you use [someObject performSelector:#selector(selectorName)] it will not generate warnings (at least in Xcode 4.5 with llvm 4.1) because the exact selector is easy to be determined (you set it explicitly) and that's why compiler is able to put the retain/releases in the correct place.
That's why you will get warning only if you pass the selector using SEL pointer because in that case the compiler is unable to determine in all case what to do. So using the following
SEL s = nil;
if(condition1) SEL = #selector(sel1)
else SEL = #selector(sel2)
[self performSelector:s];
will generate warning. But refactoring it to be:
if(condition1) [self performSelector:#selector(sel1)]
else [self performSelector:#selector(sel2)]
will not generate any warnings
ARC is throwing the warning because it can't guarantee that the selector isn't creating an object it doesn't know about. You could theoretically receive something from that method that ARC can't handle:
id objectA = [someObject performSelector:#selector(createObjectA)];
Maybe someday it can, but right now it can't. (Note if it does know the object (it's not an id) it doesn't throw this warning).
If you're trying to simply execute a method without receiving an object back from it, I recommend using objc_msgSend. But you've gotta include in your class:
#include <objc/message.h>
objc_msgSend(someObject, action);