How to override a superclass' property with more specific types? - objective-c

The Scenario
I have a situation where a base class called AbstractRequest has a delegate property of type id <AbstractRequestDelegate> declared in the header file:
#property (nonatomic, assign) id <AbstractRequestDelegate> delegate;
The abstract delegate protocol contains a few required methods, and as indicated with the word 'abstract', both the AbstractRequest and the AbstractRequestDelegate are intended to be subclasses/extended.
One example of this would be the subclass ConcreteRequest and extended protocol ConcreteRequestDelegates, that both add extra methods to the abstract ones. The intention is that both the abstract and concrete class methods can send messages to the single assigned delegate instance.
At a certain point in time the ConcreteRequest would like to call a method on the delegate that is defined by ConcreteRequestDelegate. Because the type of the delegate is id , the compiler will give a warning that this method might not be implemented.
ConcreteRequest.m:38: warning:
property 'delegate' requires method
'-delegate' to be defined - use
#synthesize, #dynamic or provide a
method implementation
The Problem
This warning is justified, for the property is after all typed to id <AbstractRequestDelegate>. In order to fix this, I want to make clear to the compiler that the delegate assigned to the concrete instance must be of type id <ConcreteRequestDelegate>. This sounded perfectly reasonable to me, so I put in a new property in the ConcreteRequest header, hoping to override the abstract one:
#property (nonatomic, assign) id <ConcreteRequestDelegate> delegate;
But this is where the compiler disagrees with me, probably with good reason. I would have thought it would give a warning for overriding a super class' property with the wrong type, but instead it just demands me to re-synthesize this new property. I don't want to go there, because then the super class' methods won't have access to the same delegate property.
The Question
Is there a way to 're-declare' the property in the concrete subclass with the added type information? Or can you spot the error in my thinking, for maybe this is a fairly common problem that I just haven't come across until now?
Cheers,
EP.
P.S. All class and protocol names appearing in this work are fictitious. Any resemblance to real class and protocol names, open source or patented, is purely coincidental.

The warning already gave the right clue. I used #dynamic in the overriding subclass and all is good.

Just synthesize id<ConcreteRequestDelegate>delegate in the ConcreteRequest.m it will work fine...It won't create any problem.

Related

Explaning syntax for #property id<delegateName>

I see a lot of code references when writing delegates using something likes
#property (nonatomic, weak) id<mySuperCoolDelegate> delegate;
normally where id<mySuperCoolDelegate> is, is the data type of the property. So the questions are:
Is my understanding correct, that above syntax is telling the compiler data type of the id is mySuperCoolDelegate?
Any other examples where this sort of code (data type specified for id) could be used?
Thanks!
This piece of code is objective-c's way of implementing interfaces (as in Java or Go). using "id" means that you don't know at compile time what type of object it will be. But using the protocol in angle brackets you are telling the compiler that no matter what object it will be, it will need to support the 'mySuperCoolDelegate" protocol. If it doesn't - the compiler will let you know.
This syntax tells the compiler that delegate is of some kind of class (any class) that implements the mySuperCoolDelegate protocol.
This allows a certain component to notify another component on some event that happened without the need to know about the notified component (type-wise). (e.g. UITextView notifies its controller that the text has been changed without having a reference to that controller, only through the generic-typed delegate so the UITextView does not need to limit itself to a specific controller's type)
Also note that delegates are usually declared as weak (rather than strong). If an instance of UIViewController has a strong reference to a UITextView instance and that text view delegate (assume it is strong) is the controller instance then you will have a retaining cycle where both objects release will be dependent on the other object's release (which will never happen and leave you with a memory leak).
Short:
This tells the compiler that the property can be of any type as long as it implements the protocol mySuperCoolDelegate.
Still too short to be 100% accurate but easy to understand:
id is similar to NSObject*, meaning it is a reference to any kind of object (not only subclasses of NSObject, to be frank). Witin <> you declare which protocols the object has to conform to.
Example: It could be both:
#interface mySuperCoolClass : <mySuperCoolDelegate> ... #end
or
#interface somebodyElsesSuperCoolClass : <mySuperCoolDelegate> ... #end
Wherever you use that property, the compiler will allow you to access all methods that are declared in the related #protocol (most likely in some .h file that you need to #include).

Need assistance understanding objective-c protocol

#import <UIKit/UIKit.h>
#protocol myProtocol <NSObject>
-(void)aMethod;
#end
#interface ViewController : UIViewController
#property (weak) id<myProtocol> dSource;
#end
I am trying to get a firm grip on Obj-c protocols, I am reading apple doc to study, few things are not clear to me. Below are the points from doc:
The pie chart view class interface would need a property to keep track of the data source object. (The code above, we mostly declare protocol this way, when I have protocol declared in my class why need a tracking object, Or protocol can be defined in independent class? and for that we need tracking object?)
By specifying the required protocol conformance on the property, you’ll get a compiler warning if you attempt to set the property to an object that doesn’t conform to the protocol.
If you attempt to call the respondsToSelector: method on an id conforming to the protocol as it’s defined above, you’ll get a compiler error that there’s no known instance method for it. Once you qualify an id with a protocol, all static type-checking comes back; you’ll get an error if you try to call any method that isn’t defined in the specified protocol. One way to avoid the compiler error is to set the custom protocol to adopt the NSObject protocol.
I dont understand this question
Correct, the property requires that the property is an id which
conforms to your property, if you try to set it to something else
the compiler rightly complains
This is because respondsToSelector: is a method on the NSObject
protocol, so you can either have your protocol extend NSObject
(standard), or you could declare the property as
NSObject

iOS: Ambiguous property synthesis behavior. Inheritance related

I'm using AppCode and it flagged an interesting situation in the code of a very large project. Pre-ARC.
A subclass defines and synthesizes a property called delegate. Actually the property declaration had been commented out! But the #synthesize delegate = delegate_; statement was left behind.
The code compiles, presumably because the base class defines and synthesizes a property also called delegate and synthesizes it with a backing variable with the same name: #synthesize delegate = delegate_;
My question is: What happens with a message is sent to the delegate in
a) the base class methods and
b) in the sub-class methods.
AppCode flags the synthesize statement in the sub-class as an error:
Accessors of property 'delegate' were already synthesized with
instance variable 'delegate_'
The #synthesize directive is shorthand for creating accessor methods and an ivar according to the specifications (atomicity, memory management) of the property of the same name. Given that, re-synthesizing a property in a subclass (without re-declaring it) works exactly like overriding the accessor methods -- the subclass's implementations are used instead of the superclass's. Since the implementations are created by the compiler in both cases, there's no noticeable difference in behavior.
The one difference is that a synthesized ivar has the same visibility as a #private ivar, so subclasses can't access it, including to use it as the backing variable for a property. This means that the re-synthesis in the subclass must use a different ivar name. If the superclass has #synthesize wildHorses = wildHorses_;, then the compiler requires the subclass to do something like #synthesize wildHorses = equusFerus;.*
*If the superclass uses the default name for the created ivar, #synthesize wildHorses; then the subclass must still synthesize a new variable: #synthesize wildHorses = wildHorses_;

why to declare some instance variables as properties

Though this is somewhat a very basic question but I have some doubts still left after reading so many documents and questions on stackoverflow.com.
I want to know why to declare some instance variables as properties.
MYViewController.h
#interface MyViewController : UIViewController {
UIButton *btn;
NSString *name;
}
#property (nonatomic, retain) UIButton *btn;
#property (nonatomic, retain) NSString *name;
MyViewController.m
#implementation MyViewController
#synthesize btn;
-(void) viewDidLoad()
{
[btn setTitle:#"Hello" forState:UIControlstaeNormal]; //this is first way where there is no need to declare btn as property
[self.btn setTitle:#"Hello" forState:UIControlstaeNormal]; //this is second way where we do need to decalre btn as property as we are accessing it through self
//Setting value of name
name = #"abc"; //this is first way where there is no need to declare name as property
[self setName:#"abc"; //this is second way where we do need to declare name as property as we are accessing its aetter method through self
}
Now in the above code I wanna know when we can use the getter/setter methods of btn variable without declaring it as property then what is the need to declare it as property and which is the better way to set the value of "name".
Somewhere I read that when you want your instance variables to be accessed my other class objects then you should declare them as instance variables. Is it the only situation where we should declare them as properties.
Basically I am a little confused about in which situations to declare the instance variables as properties.
Please suggest.
Thanks in advance.
In short, you don't have to declare instance variables as properties unless you want to.
You declare a variable as a property in order to auto-generate getter and setter methods. In your property declaration you can specify how you want them set up (retain vs assign, atomic vs nonatomic). Then, the getter and setter are generated with the #synthesize directive.
So, again, there is no right or wrong way to use properties. Some people never use them, some people make every variable a property. It's really up to you.
typically, you'll use them because:
1) the property belongs in the public interface of the class
used when the class needs to expose a given method. the downside is that clients and subclasses may abuse the public interface (all objc methods are public, where visible), unless you're careful to hide these details (which is also a pain at times). sometimes you're forced to go well out of your way in order to achieve the class interface you need (with the proper levels of visibility).
2) you want auto-generated accessors
implementing nonspecialized accessors is tedious, and error prone. it's better to save the time and let the compiler generate them for you.
3) to document behavior
sometimes it's better to write #property (copy) NSString * title; instead of over-documenting the expected result.
4) stricter selector matching with dot-syntax
the compiler performs stricter selector matching. prefer to catch the errors/issues at compilation, if possible.
5) to force the subclasses to use them instead of handling the ivars directly
objc ivars are protected by default. you'll often want them to be private (depending on how the class is used and distributed, or just to ensure the subclass uses the base class correctly).
there are a ton of reasons for this. threading and maintenance are the big ones.
if you declare the ivar as private and provide a property for the subclass to use, then the subclass is forced to use the property in their implementation (although there are ways they could cheat) rather than giving them direct access to the ivar.
so... it ultimately depends on your preference, and the implementation details of your class, paired with the interfaces you're using. i don't think there's a hard and fast rule here - lesser evils and convenience are key motivations.

Objective-C categories: Can I add a property for a method not in my category?

I want to use a category to make a method on the original class available as a property as well.
Class A:
#interface ClassA
- (NSString*)foo;
#end
Class A category
#interface ClassA (Properties)
- (void)someCategoryMethod;
#property (nonatomic, readonly) NSString *foo;
#end
Now when I do this, it seems to work (EDIT: Maybe it doesn't work, it doesn't complain but I am seeing strangeness), but it gives me warnings because I am not synthesizing the property in my category implementation. How do I tell the compiler everything is actually just fine since the original class synthesizes the property for me?
Here's the warning you're getting:
warning: property ‘foo’ requires method '-foo' to be defined - use #synthesize, #dynamic or provide a method implementation
To suppress this warning, have this in your implementation:
#dynamic foo;
If something's declared in your category's interface, its definition belongs in your category's implementation.
I wrote two articles on this, though the concept is slightly different from the question you're asking.
Add properties to categories without touching the base class: http://compileyouidontevenknowyou.blogspot.com/2012/06/adding-properties-to-class-you-dont.html
Access iVars from categories: http://compileyouidontevenknowyou.blogspot.com/2012/06/if-you-want-to-keep-everything-in-your.html
This is a LOT better than method swizzling, at least: way safer.