I'm using my free time to play with Objective C. I was reading about Protocols but I'm afraid I might be using it wrong, considering I'm using it the same way (almost the same at least hehe) I do with C# code.
So, here is what I got. I have a protocol, a class manager to weakly couple my views and two views that implement the protocol.
#protocol IView <NSObject>
- (void) loadViewToScreen;
#end
#interface ViewManager : NSObject
#property (atomic, weak) id<IView> document;
#property (atomic, weak) id<IView> browser;
//Singleton
+ (id) getInstance;
#end
Then I call one view the views from each other.
ViewManager *vm = [ViewManager getInstance];
[vm.browser loadViewToScreen];
I'm not interested here what the best way to load views into the screen. It's just a mock code to test protocols.
I could not get the manager to use pointers to the protocols. So I'm afraid I'm getting view copies around. Did I get this right?
Thanks,
Lucas
A protocol, concpetually, is just a part of the type of an object or class. You can't get a pointer to a protocol. (Well, actually you can obtain a protocol object, but that's runtime mocking which doesn't seem to be what you want).
Don't be afraid about getting copies, though. Unless you copy an object or assign it to a copy property, you'll get pointers to the same instance.
Related
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.
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).
The following code compiles just fine - but are there any issues with it?
I couldn't find any guidelines for Objective-C that would discourage us from using the same identifier for both, properties and method names:
#interface MouseCursorHelper : NSObject
#property (nonatomic, readwrite, retain) NSCursor* rotateCursor;
+ (NSCursor*) rotateCursor;
#end
FWIW, the class is implemented as a singleton modeled after NSCursor to offer app specific cursors.
It could be a little confusing.
The property generates 2 instance methods for you:
- (NSCursor *)rotateCursor;
- (void)setRotateCursor:(NSCursor *)rotateCursor;
And you also have a class method:
+ (NSCursor *)rotateCursor;
It isn't clear from a user point of view what the class method does. Documentation would help.
There's absolutely no problem with what you are doing there at all. All you are doing is saying that both the class object and instances of the class respond to rotateCursor. That's not really conceptually different to instances of NSString responding to intValue and instances of NSNumber responding to intValue. They are just different kinds of object.
In fact, you'll find several instances of Apple doing the same thing in the Cocoa framework e.g.
[NSString class]; // Sending class to the class
[#"foo" class]; // Sending class to an instance of the class.
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).
I have a custom UITableViewController subclass which I use in two places in a nib file. What should I do if I want the two instances to have slightly different behavior? Of course in the code I can select one kind of behavior or the other based on the value of a BOOL, but how do I set that BOOL from Interface Builder, without having to write an Interface Builder plugin?
As of Xcode 6 there is a new way doing this. You can now give your view properties the attribute IBInspectable and then you can edit those properties in IB as you would with and standard view.
So for example:
#property (nonatomic, strong) IBInspectable BOOL
More details (also for the new attribute IBDesignable) in Apples documentation: https://developer.apple.com/library/ios/recipes/xcode_help-IB_objects_media/chapters/CreatingaLiveViewofaCustomObject.html
"User Defined Runtime Attributes" in the Identity inspector is probably what you're looking for. This seems to be new as of Xcode 4.2.
Unfortunately, there doesn't seem to be much (any?) documentation about this feature on the Apple Developer site. I was able to use it for a simple property set.
So far as I know, you can't set parameters in IB without writing an IB Plugin.
That said, you have two other options.
If it is as simple as a single BOOL, you're probably best off making it a property of the MyCustomViewController class and set it in code after you init:
customViewController = [[MyCustomViewController alloc]initWithNibName:#"CustomViewController" bundle:nil];
[customViewController setFunky:YES];
The other option is to create a protocol for a MyCustomViewDelegate. If you're not familiar with protocols, your header would look like this:
#class MyCustomViewController;
#protocol MyCustomViewDelegate
#required
-(BOOL)customViewShouldBeFunky:(MyCustomViewController*)customView;
#end
#interface MyCustomViewController : UIViewController {
NSObject<MyCustomViewDelegate> *delegate;
}
#property (readwrite, retain) IBOutlet NSObject<MyCustomViewDelegate> *delegate;
#end
Since it is an IBOutlet, you can wire up the delegate like any other delegate in Interface Builder.
Then call [delegate customViewShouldBeFunky:self] when you need to determine how your view should behave.
Have two subclasses is probably easier, and will be easier to document.
Here is an example of overriding properties and setting them in custom classes, this may help. The property code will work before awakeFromNib is called. So you may decide what you have to do based on the user's decision right in awakeFromNib.
https://stackoverflow.com/a/31094561/1699210