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.
Related
I have a protocol for which I want the implementations to use __weak references for method arguments. I define my protocol as:
#protocol TestProtocol
-(void) op:(__weak NSObject*)x;
#end
Then I create an implementation:
-(void) op:(NSObject*)x
{
}
And x becomes an strong reference. If I move the __weak declaration to the protocol implementation, 'x' is a weak reference.
As the caller of the protocol already keeps a strong reference, I want to ensure that the implementations don't create another strong reference.
I'm a tad surprised the compiler doesn't complain about a declaration mismatch. And, sure enough, it doesn't. I filed radar #13730581 to see what the compiler folks say.
As #hypercrypt cites, ARC isn't going to retain or release the arguments to a method in the general case. One of the few cases where the performance vs. correctness sacrifice was large enough to warrant such a tradeoff. (Note that you'll see a storeStrong in the non-optimized case but no such thing in the -Os case Release build case).
Which means you are really defending against a strong reference being created against the object by implication of the code in the method body (and, as per comments, that said strong reference isn't torn down when an #throw goes "over" the frame).
There isn't much you can do about that -- if you pass x off to, say, NSMutableArray's addObject: method, it'll create a strong reference.
Thus, in the general case, there isn't really a means of preventing a strong reference to an object from being created as a side effect of variable usage.
Specific to NSException cleanup, it isn't worth worrying about. Exceptions should be fatal and the state of the app after an exception is thrown is undefined (unless you can ensure that no system code was in any way involved with the exception, which isn't really viable).
// code tossed in main.m to play w/compiler behavior
#protocol TestProtocol
-(void) op:(__weak NSObject*)x;
#end
#interface DogBowl:NSObject <TestProtocol>
#end
#implementation DogBowl
-(void) op:(NSObject*)x
{
}
#end
I think that both methods are equivalent.
Do you know the difference?
objc_arc_weak_unavailable objc_arc_weak_unavailable attribute on
the class's interface declaration. A retainable object pointer type is
weak-unavailable if is a pointer to an (optionally protocol-qualified)
Objective-C class T where T or one of its superclasses has the
objc_arc_weak_unavailable attribute. A program is ill-formed if it
applies the __weak ownership qualifier to a weak-unavailable type or
if the value operand of a weak assignment operation has a
weak-unavailable type.
supportsWeakPointers If you you [sic] find that you must
implement custom retain or release methods, then you must also
implement the following method in your class:
-(BOOL)supportsWeakPointers { return NO; }
This method will prevent weak pointers from being formed to your objects. You are strongly encouraged to find a solution that doesn’t
require implementing your own retain and release methods instead of
doing this.
Note: By checking the LLVM parser I found that the right symbol is objc_arc_weak_reference_unavailable, that is:
__attribute__((objc_arc_weak_reference_unavailable))
#interface Point : NSObject
#end
Significantly, objc_arc_weak_unavailable is a compile time option (you can also declare it using NS_AUTOMATED_REFCOUNT_WEAK_UNAVAILABLE) whereas supportWeakPointers is a runtime call. This question addresses why you might use this.
So in some of the codes I see, they access an objects ivar directly instead of using accessors . What are the advantages of using them instead of accessors?
So how would this
thing = object->ivar
differ from this?
thing = object.ivar
Thanks.
First let me say, I totally loathe the Objective-C dot notation. It sacrifices understandability for brevity and that is a bad thing. In fact, the other two answers here both show evidence of the kind of confusion dot notation introduces.
Having got the rant out of the way, I'll now try to answer the question.
Under the hood, Objective-C objects are implemented as pointers to C structs. This is why
obj->ivar
sometimes works. Given that it's a C struct
(*obj).ivar
should also work exactly as you would expect for C. Having said that, you can make ivars private or protected, in which case using the above outside a scope where they are visible will cause a compiler error.
The dot operator when applied to an Objective-C object (which is a pointer don't forget) has a totally different meaning. It's syntactic sugar for sending an accessor message to the object meaning that:
foo = obj.property;
obj.property = foo;
is identical in effect to
foo = [obj property];
[obj setProperty: foo];
That is all there is to dot notation. If you go through your code changing all instances of the first form to instances of the second form, you have done everything the compiler does wrt dot notation.
In particular
you do not need a declared #property to use dot notation. You can declare the set and get accessors in the traditional way as Objective C methods, although it is definitely best practice to use #property declarations for things that are logically properties.
you do not need a backing instance variable. There's no reason why your getters and setters can't calculate values.
Given the above, the major difference between obj->ivar and obj.ivar is that the former modifies the ivar directly and latter invokes an accessor, this means that the latter can do any memory management stuff needed (retains, releases, copies etc) and can also invoke key value observing.
This is one thing with a huge difference between c/c++ and objective-c.
In C/C++ the . accesses the variable directly and the -> accesses the variable if it's a pointer to the variable, so basically it is the same.
In Objective-C the . is a shortcut to access the property using the setter and getter function and it is always using those functions. You can't access ivars with it if there is no property with that name.
Some say it's "dirty" to allow direct access to the variables. If more people work on the code it's "cleaner" to use accessors because it might be easier to debug where variables are changed since you can always break in the setter.
You can even do "bad" things with it, like:
NSArray *array = [NSArray alloc] init];
int count = array.count;
array.release;
this will technically work, because the array.release is a shortcut for [array release] but it is bad style to use . for other things then properties.
The advantage of properties is that they call methods that work with your ivars, in stead of calling the ivars directly, so you can do things like this:
-(void)setFrame:(CGRect)frame
{
if([self frameIsValid:frame])
{
if(self.flipsFrames)
{
frame.size = CGSizeMake(frame.size.height,frame.size.width);
}
[super setFrame:frame];
[delegate viewSubclass:self ChangedFrameTo:frame];
}
}
Four advantages shown here are:
The possibility to override
The possibility to check a given value
The possibility to alter a given value (use with caution)
A way to react to calls
Another advantage:
-(NSInteger) amountOfMinutes
{
return amountOfSeconds * 60;
}
You can use 1 ivar for multiple properties, saving memory and preventing/reducing redundancy, while keeping useful different formats.
There's not really an advantage to using ivars, except when you don't want to use a property so your class is more encapsulated. That does not make it impossible to reach, but it makes it clear it isn't supposed to be reached.
All ivars are private. There is no way to access them directly from outside the object. Therefore, both of your code samples are equivalent, in ObjC terms.
When you call object.ivar, what you are really doing is calling object's ivar selector. This may be either a getter method that you wrote yourself, or more likely, a synthesized getter method that you created with #synthesize.
thing, however, is an ivar. Your code would be calling the ivar selector on object and assigning the result directly to your instance's thing ivar.
If you had instead written it as self.thing = object.ivar, then you would be using your instance's setter method to assign to thing.
Some of the advantages of using accessors (specifically, synthesized properties) in ObjC are KVO/KVC compliance; better concurrency support; access control (readonly, readwrite); as well as all of the advantages that accessors give you in any other OO language.
I found out Objective-C object properties can be marked as #dynamic to let compiler know that implementation will be available at runtime. I'd like to know if there is a way to tell the compiler that all properties on an object are dynamic without explicitly specifying them one-by-one (I don't have a list of properties up front). I know that this would not be a problem if I would just use [object something] but for stylistic purposes I want to use object.something syntax.
I'm fairly sure that it's not possible to do that but I'd like someone to confirm that. Since this is not for production use solution can involve anything you can imagine.
Thanks.
Additional info:
I only care about -something (getter) working so if your solution does not support setters that is fine.
Example:
#interface MagicalClass : NSObject
// property 'something' is not defined!
#end
#implementation MagicalClass
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { ... }
- (void)forwardInvocation:(NSInvocation *)anInvocation { ... }
#end
MagicalClass *obj = [[MagicalClass alloc] init];
[obj something]; // compiler warning
obj.something; // compiler error
This really doesn't work with declared properties. The whole point of them is that you declare upfront what your properties are and how you interact with them. If you don't have any to declare, then you don't have any declared properties.
Unfortunately, it also doesn't work well with plain messages, although it can work better than dot syntax. Objective-C's static type checking will throw a hissy-fit of warnings, and if any of the properties are of non-object types, it might not be able to generate the correct calling code.
This kind of thing is common in languages like Python and Ruby where things don't have to be declared, but it just doesn't mesh well with Objective-C. In Objective-C, accessing arbitrary attributes is generally done with strings (cf. Key-Value Coding and NSAttributedString).
I don't believe this is possible. If you use the id type, you may be able to send undeclared messages, but dot syntax really relies on knowing about your specific accessors.
I haven't tried this, but if you provide a getter and setter, does Xcode still want the #synthesize or #dynamic directive?
So if you property is called something, implement -setSomething: and -something.
How can I prevent a method from getting overridden in a subclass, missing a call to its superclass' implementation within?.
I know calling [super methodName]; will solve my problem sometimes.
But if somebody else was to use my parent class and overrode my method, accidentally missing to call super, what can I do?
Some more explanations:
I create a viewcontroller VC1 which has a method -(void)indexDidChange:(int)index { }. I write some actions there which I need to perform every time. and I subclass this viewcontroller named as SVC1 in it I need -(void)indexDidChange:(int)index { } for doing some other actions but at the same time the VC1 -(void)indexDidChange:(int)index { } action also need to perform. So I need to call like,
-(void)indexDidChange:(int)index {
[super indexDidChange:index];
}
So I decide to change VC1 function like,
-(void)indexDidChange:(int)index {
[self currentIndexDidChange:(int)index];
}
-(void)currentIndexDidChange:(int)index { }
And I need -(void)currentIndexDidChange:(int)index { } to override and prevent -(void)indexDidChange:(int)index { } from overriding.
Is it possible?
Edit: After OP rephrased the question it is clear that OP is actually NOT looking for final methods, despite the questions initial phrasing, which implied just this.
New (updated) answer to OP's question on method overriding safety:
According to your rephrased question you are not looking for protecting a method from being overridden at all, but rather worried about one of your subclasses overriding a method and accidently missing to include a call to super in its new implementation.
This however is a fairly common and widespread issue and something you're dealing with on a daily basis, without paying much attention to it.
Every Objective-C programmer is familiar with the following method, right?
- (void)dealloc {
[iVar release], iVar = nil;
[super dealloc]; //skipping this call to super is fatal!
}
And we al know that skipping the [super dealloc]; makes things get uncomfortable. (afaik the clang compiler issues a warning if dealloc lacks the call to super, …pretty handy.)
Despite the fact that a bad overriding of this method can have fatal consequences Apple did not choose to put any kind of security system in place here.
Instead Apple did this (as done with any other method requiring calls to super):
Add a note to the method's documentation:
After performing the class-specific
deallocation, the subclass method
should incorporate superclass versions
of dealloc through a message to
super
Expect you, the programmer, to be a grown-up and responsible for what you do. And for playing by the rules (as defined by the documentation).
Keep in mind that - (void)dealloc is by no means an exception. There are dozens and dozens of methods of this type in Cocoa. (Take just about any derivative of - (id)init, most of the KVO observing methods, etc. just to name a few.)
So what you should do is:
Write a good documentation for your
method. (better for your entire project, actually)
Add a big loud note to your method's documentation, explaining its rules.
Add a note to each of your subclasses' overridden method implementations, right above the line that's calling super, telling the reader/dev to look up documentation, when in doubt of the rules. (optional)
Code responsibly. Otherwise, you shouldn't be coding in first place. It's your customers who will suffer from it, eventually.
Old (pre-rephrasing) answer on archieving pseudo-final methods:
What you are asking for is the equivalent of a final function, as known from Java or C++.
Unlike Java or C++, however there are no final methods in Objective-C.
Depending on your situation there are solutions that might bring your at least near to what you're aiming for. All you'll get though is slightly better separation. You won't get any significant security from them. In Objective-C you cannot even be sure about the origin of your methods. Method swizzling allows you to exchange methods at will. With code injection you an even inject code into processes at runtime. All this is by design of Objective-C. Objective-C allows you to saw off the branch you're sitting on. Thus it demands you to act like a grown-up. As such there are no private methods either. If a method is proclaim private you as a dev are expected to behave accordingly.
Now to possible "solutions":
If only your super class if supposed to call the given (final) method anyway:
Then Macmade's solution of making your method a pseudo-private method would work quite well. The downside of hiding method declarations though is, that calling your hidden method from subclasses will give you a compiler warning, basically preventing*(sic!)* you from calling it. (It will not prevent you from calling the method though. It will only avoid you from doing so, by throwing compiler warnings.)
If subclasses however are expected to call the given (final) method:
Use a delegation pattern and by this only make those methods public that are allowed to be overridden.
To prevent overriding at all you could use the class cluster & abstract factory patterns, which hides your implementation classes and thus preventing overriding entirely. (Apple's NSArray, NSDictionary, NSSet classes do this)
However you might notice that with Objective-C lack of protection one usually can only choose between the two: openness, protectedness, not intermix them.
You can use categories in the implementation, so your methods aren't exposed in your header file.
MyClass.m
#interface MyClass( Private )
- ( void )myMethod;
#end
#implementation MyClass( Private )
- ( void )myMethod
{}
#end
#implementation MyClass
/* ... */
#end
If you don't declare your function in the ".h file" then its not listed, I think.