Explaning syntax for #property id<delegateName> - objective-c

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).

Related

Objective-C : Accessing fields in implementation

Is it possible to fields defined only in implementation but not in interface definition ?
#interface MyInterface .... #end --> dict not defined here!!!
#implementation MyInterface
...
NSDictionary *dict;
...
#end
In this case if somewhere I somehow accessed to this class, can I access to the dict or should I create a getter just like in Java ?
Edit after #Rob's answer
Thanks for the answer Rob, I wish I have the implementation of these interface and classes. Instead I am trying to bind two different libraries ( I know it is reallllly bad as architectural point of view but this is where I end up).
Basically, I am in react-native world. And we are using react-native-video as our player layer. But since AVPlayer does not support some subtitle types our head company sent us a library that needs a player instance and a view instance to draw subtitle on the view. I believe they will bind to events of the player and draw sub titles based on player states.
So react-native-video is in this github repo with the interface and implementation.
I find the UIView that includes the properties and casted it to the object itself RTCVideo in this case). But now I am stuck. I can go and change some stuff as per your suggestion in the "Development Pods" to be able to access but this is my last bullet :) I prefer to convince these two libraries in a friendly way :)
Yes, but the above syntax isn't what you want. The modern way to do this is with a class extension.
Your header file is the same:
#interface MyInterface
#end
But in your .m file, you create an extension by appending ():
#interface MyInterface ()
#property (nonatomic, readwrite) NSDictionary *dict;
#end
Now, inside your .m file, you can access self.dict normally, but outside of your .m file it won't appear available.
For full details, see Programming with Objective-C: Class Extensions Extend the Internal Implementation.
The syntax you've written actually creates a static (global) variable called dict that isn't tied to any instance.
It is possible to create raw instance variables using a {...} syntax, either on the extension or on the implementation, but this isn't used that often today, except for managing raw buffers that you don't want accessors for. The syntax is either:
#interface MyInterface () {
NSDictionary *_dict;
}
...
#end
or on the implementation:
#implementation MyInterface {
NSDictionary *_dict;
}
...
#end
But I recommend simple extensions with properties any time you can. And if you are considering creating an accessor for it, you definitely want to use #property and let the system do it for you.
If I understand your edits correctly, you're trying to read the internal ivars of an object that doesn't expose them with an accessor, correct? I believe specifically you want to access _player.
There's several common ways to do that. The key feature you want is Key-Value Coding.
The simplest approach for this problem is -valueForKey:
AVPlayer *player = [view valueForKey:#"player"];
The first thing -valueForKey: looks for is _<key>, and if it's just an object pointer (as in this case), it just returns it.
(This can be broken if a class return false for +accessInstanceVariablesDirectly, but the default is true, and it's unusual to override this.)
Another very common approach is to just declare any methods you know exist as a category. (This won't work for _player, since it's not a method, but in case you need similar things.) Imagine you wanted to call the "private" method -removePlayerTimeObserver. In your .m file, just say you know about it using a category:
#interface RCTVideo (PrivateMethods)
- (void)removePlayerTimeObserver;
#end
And since you know about it, you can call it:
[video removePlayerTimeObserver];
If you're wrong, and that method doesn't really exist, then the program will crash. In Objective-C, almost all rules are advisory. You can break them if you want to. ObjC programmers tend to be big rule-followers because otherwise the program crashes and ObjC has very clear rules that are pretty easy to follow. It's not because the system forces us to.

When should I declare an instance variable rather than property in the header? [duplicate]

This question already has answers here:
Do declared properties require a corresponding instance variable?
(6 answers)
Closed 8 years ago.
For example, in the following codes.
#interface TUTViewController : UIViewController
{
NSTimer *timer;
}
#end
and
#interface TUTViewController : UIViewController
#property (weak, nonatomic) NSTimer *timer;
#end
In which scenario do we use the first method to declare variable?
You are going to get lots of opinions on this, often stated as hard fast rules.
Example:
Maddy: Never put ivars in the .h. ivars should always be private
meaning they do not belong in the public .h. If you create ivars, put
them in the .m file
I have tremendous respect for Maddy, but I disagree with him on this one.
If you put your iVars in your .m file, they are hidden from other classes, but they are also hidden from subclasses that you create.
I prefer to mark my instance variables as #protected, which makes them available to subclasses, but not to other classes.
Others will tell you to make EVERYTHING a property. Before ARC, it made sense to save all your objects in properties, since you could use the setter on the property to manage the memory on your objects. (When assigning a value to a retained property, the setter would first release any old value, then retain the new value.) Now ARC takes care of that for you even for iVars, so the argument for making everything a property is less.
What I do is to make everything an iVar, unless:
I need a custom getter or setter method with special behavior.
I want to access the value from another object.
I need to mark a property as "atomic" for access from another thread. (get in the habit of declaring all of your properties as "nonatomic." If you don't know what atomic is for for, you want nonatomic. Atomic properties are slower than nonatomic.)
As a matter of policy I NEVER access another object's iVars except trough a property.
There is a small but real amount of overhead in using a property rather than an instance variable. A property read/write always makes a method call. An iVar accesses the memory directly without the overhead of a method call. Usually the difference is too small to matter. But, if you're doing millions of operations, like doing something to every pixel in a large image, or handling callbacks from processing video or audio samples in real-time, the difference can be large.
I would highly suggest to use #properties unless there is a very good reason not to. It's true the discussion is a religious one more than a technical one but since we are probably all followers of the Cult of Mac, if Apple prefers you to use #properties then that's the standard. In my opinion both Apple documentation and Xcode aren't as pushy on standards like ReSharper would do in Visual Studio for instance (it warns when you don't use var for example). That's a pity because that would make it easier for me to pick up code after somebody else.
There is a way to "hide" #properties in a .m file, you should declare it as follows:
#interface ABCMySpiffyClass ()
#property (weak, nonatomic) IBOutlet UIImageView *spiffyImage;
#property (weak, nonatomic) IBOutlet UILabel *spiffyTitle;
#end
These are not completely private to another consumer of your class but it is hidden at first sight. This should tell the other developer that he or she should not use them. I think public/private has more to do with documentation as it has to do with application security for most apps.

Why do I declare properties twice? or do I?

Sorry for the kind of useless post title, but since I'm not really sure what I am doing, that was the best i could come up with.
In my header file it looks like this
#interface RootViewController : UITableViewController {
NSMutableArray *eventsArray;
}
#property (nonatomic, retain) NSMutableArray *eventsArray;
#end
This is not all the properties but i removed all but one for simplicity.
I'm doing this by following a guide from apple developer. It seems as though the guide is not totally updated since it tells me to synthesize properties, wich i should not have to anymore right?
Anyways, why is it like this? To me, a beginner at this, it seems as though I declare the property twice? Or do I do something else at the first row there?
It's like this for historical reasons, with the older compiler.
You can do this nowadays:
#interface RootViewController : UITableViewController
#property (nonatomic, retain) NSMutableArray *eventsArray;
#end
The way you have it, you are declaring an instance attribute, and then you are saying you want to automatically generate getters and setters.
Nowadays, you can just say you have a property and the compiler will automatically generate the instance attribute at compile time. It removes the apparent redundancy.
To me, a beginner at this, it seems as though I declare the property
twice? Or do I do something else at the first row there?
A property and the instance variable that backs it up (if there is one) are two different things. A property is really just a promise that the class provides certain accessor methods. So the fact that you had to declare the property and ivar separately isn't strange. However, most properties are, in fact, backed by an ivar with a related name, and writing and maintaining the two separately got to be a chore. So Apple added ivar synthesis to the compiler, so that the compiler generates an ivar for any synthesized properties for which an ivar doesn't already exist. Also, because synthesized accessors are by far the most common, and because the compiler will use any accessors that you provide even if a property is marked #synthesize, that became the default so that you no longer need the compiler directive.

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

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.

Unexpected content in default files generated for opengl template in xcode

I was just starting a new opengl project in xcode. When I was going through the default files created, I was confused by this following line of codes in the viewController interface.
#interface RetinaTestViewController ()
#property (nonatomic, retain) EAGLContext *context;
#property (nonatomic, assign) CADisplayLink *displayLink;
- (BOOL)loadShaders;
- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file;
- (BOOL)linkProgram:(GLuint)prog;
- (BOOL)validateProgram:(GLuint)prog;
#end
My question is why this is written in the implementation of viewController rather than in the interface itself. This may be very basic but I just started to work with the openGL stuff. Please do help.
I don't think this is really OpenGL related, but Objective-C has something called categories, which allow you to add extra methods to an existing class. You can add them to any class you want, whether you have the source code or not. The syntax looks like:
#interface classname (categoryName)
- (void)extraMethod1;
- (void)extraMethod2;
#end
#implementation classname (categoryName)
- (void)extraMethod1
{
}
- (void)extraMethod2
{
}
#end
And, as I say, you can use that to add methods to any class, including e.g. NSString, NSDictionary and the other Foundation objects.
The brackets after the classname in the interface declaration dictate that this is a category, not a full interface definition. Historically there was no way to add extra storage to a class through a category, so you may not declare member variables in categories. Hence there's no {} section.
In the modern runtime (on 64bit OS X and iOS), you can add extra storage via #properties, as Apple appear to do in the code you've given.
Here Apple are using category methods to create something like private methods — in this case methods that everyone in the class knows are there but which aren't declared externally. That's a design decision, to keep the bits that other people are likely to look at neat and to indicate the programmer's intent.
What's going on is that:
the bits of RetinaTestViewController that Apple want everyone else to know about are declared in the header file
the bits that aren't meant to be exposed are declared only in the implementation file
A well-designed object should expose a public interface and conform to that interface, while doing whatever is necessary internally and keeping its internals secret.
You can read a little more category methods here, here and here (scroll down to number 11).