Hiding types from Objective-C framework header files - objective-c

I'm writing a media player framework for a project I'm working on. This depends on VLC. One of my classes' header file looks like this
#import <vlc/vlc.h>
#interface MediaPlayerVLC : MediaPlayer
{
libvlc_media_player_t *player;
libvlc_media_t *media;
}
#end
I need the instance variables in the class, and I need the #import <vlc/vlc.h>, because they're defined in there. But I don't want users of this framework to have to import all of VLC's headers just for these two types. I've seen a few solutions to this problem around...
Forward declaration, such as #class. Unfortunately, these types are typedef struct types, I can't seem to find any way to forward declare them
declare the ivars as void *, then cast them whenever I want to use them. I'd like to avoid this if possible, as we lose type-safety and implementation files become full of ugly casts.
I've seen this in Apple's frameworks...
#interface CAAnimation : NSObject <NSCoding, NSCopying, CAMediaTiming, CAAction>
{
#private
void *_attr;
uint32_t _flags;
}
What does _attr point to? I guess it would be a struct of ivars, I'm curious what advantages this has...
Two header files for the class, one public and one private. The private one would look like the above, and the public would just have void * pointers. This is pretty ugly, as I'd have to be very careful to keep them both in sync.
What's considered best practise? Is there an approach I've missed?

You can use class extensions. You should try doing this:
MediaPlayerVLC.h:
#interface MediaPlayerVLC : MediaPlayer
{
}
#end
MediaPlayerVLC.m:
#import "MediaPlayerVLC.h"
#import <vlc/vlc.h>
#interface MediaPlayerVLC ()
{
libvlc_media_player_t *player;
libvlc_media_t *media;
}
#end
#implementation MediaPlayerVLC
// The implementation
#end
From Apple's docs:
Class extensions are like anonymous categories, except that the
methods they declare must be implemented in the main #implementation
block for the corresponding class.
Using the Clang/LLVM 2.0 compiler,
you can also declare properties and instance variables in a class
extension.
That's using a class extension category to declare extra ivars in the implementation file.

With the newest compiler you can also declare ivars in your class's #implementation section:
// MediaPlayerVLC.m
#import "MediaPlayerVLC.h"
#import <vlc/vlc.h>
#implementation MediaPlayerVLC
{
libvlc_media_player_t *player;
libvlc_media_t *media;
}
...
#end

You can put ivars in implementation like
#implementation Something
{
int a;
}

Related

Best way to define private variables in Objective-C

I want to define private instance variables in MyClass.m file. It seems to me there are two ways to do it:
use class extension
#interface HelloViewController ()
{
int value;
}
define in #implementation section
#implementation HelloViewController
{
int value;
}
Which is better?
I think recent Apple's coding style is to use class extension?
e.g. MasterViewController.m generated by 'Master-Detail Application Template'
#interface MasterViewController () {
NSMutableArray *_objects;
}
#end
The "Modern Objective-C" way to do this is to declare them in your implementation block, like this:
#implementation ClassName {
int privateInteger;
MyObject *privateObject;
}
// method implementations etc...
#end
See this earlier post of me with more details.
#interface HelloViewController ()
{
#private //optional, this is old style
int vale;
}
If you were making a library, though, theoretically no one would know about any methods you didn't declare in the header files.
Copied from: How to make a real private instance variable?
Declaring instance variables in the #implementation is a recent
feature of Obj-C, this is why you see a lot of code with them in the
#interface - there was no other choice.
If you are using a compiler which supports declaring instance
variables in the implementation declaring them there is probably the
best default - only put them in the interface if they need to be
accessed by others.
Instance variables declared in the implementation are implicitly
hidden (effectively private) and the visibility cannot be changed -
#public, #protected and #private do not produce compiler errors (with
the current Clang at least) but are ignored.
Copied from: Private ivar in #interface or #implementation
In my view the best is to define it like private properties that you can access as fields or properties just within your implementation, the advatage is that you can access them by self as well as by _fieldName syntax what is handy in some situations.
#interface SignUpController ()
#property ViewHeaderView*header; //private properties/fields
#property UITextField*activeField;
#property CGFloat keyboardHeight;
#end
#implementation SignUpController {
}
#end

Workaround to accomplish protected properties in Objective-C

I've been trying to find a workaround to declare #protected properties in Objective-C so only subclasses in the hierarchy can access them (read only, not write).
I read that there is no documented way of doing this so I thought of this workaround and I wanted to ask StackOverflow's opinion about it.
Every custom class at the top of the hierarchy contains three classes, one implementation and two interfaces.
Let's name them:
ClassA.h
ClassA_protected.h
ClassA.m
Then any subclass of this ClassA would be as usual:
ClassB.h
ClassB.m
First I created the interface ClassA.h where I declare a protected int variable so any subclass of ClassA can have access to it:
#interface ClassA : NSObject{
#protected
int _myProtectedInt;
}
#end
Next step is the workaround I was talking about. However, once you read it you will see that it is quite straight forward. I declared a second interface called ClassA_protected.h which actually works as an extension of ClassA.h and allows us to tag the property as readonly:
#import "ClassA.h"
#interface ClassA ()
#property (nonatomic , readonly) int myProtectedInt;
#end
Last step of preparing the protected hierarchy is to declare its implementation in ClassA.m where we only synthesize our property:
#import "ClassA_protected.h"
#implementation ClassA
#synthesize myProtectedInt = _ myProtectedInt;
#end
This way, every class that needs to be a subclass of ClassA.h, will import ClassA_protected.h instead. So a child like, for example ClassB.h, would be as follows:
#import "ClassA_protected.h"
#interface ClassB : ClassA
#end
And an example of accessing this property from ClassB.m's implementation:
#implementation ClassB
-(void) method {
//edit protected variable
_myProtectedInt= 1;
//normal access
self.muProtectedInt;
}
#end
Sure, that works fine. Apple uses the same approach for example in the UIGestureRecognizer class. Subclasses have to import the additional UIGestureRecognizerSubclass.h file and override the methods that are declared in that file.
For simple "properties" just use ivar instead. That's as good as properties for all practical purposes.
Moreover, the default is already protected.
If you ask for opinion, this is mine: If one decides to mutate your
_myProtectedInt
he will probably succed anyway, because it's definitely possible with Objective-C runtime. Except this, your solution is quite OK.
Import the protected header in the implementation only. e.g.
ClassB.h
#import "ClassA.h"
#interface ClassB : ClassA
#end
ClassB.m
#import "ClassA_protected.h"
#implementation ClassB
#end
And in a framework the protected header should be marked project so it is not included in the public headers of the framework. Apple usually use the suffix _Internal.h for their protected methods.
For init or overriding a lazy loaded get property you would need direct access to the #proteced ivar, however for your use it would be better to redeclare the property as readwrite instead then you can take advantage of any features of the setter, atomicity for example.

Add ivars in #implementation

For good encapsulation, decent Objective-C programmers put their private ivars in a private extension declared in the main implementation file, like this:
// MyClass.m
#interface MyClass () {
float value;
}
#end
#implementation MyClass
#end
But recently, I found a simpler way to hide private ivars: ivars can be declared in a {} block following #implementation, like this:
// MyClass.m
#implementation MyClass {
float value;
}
#end
It is really handy when no private methods but only private ivars need to be hidden.
However, I'm not sure about its syntax validity. Can anyone validate or invalidate it with some canonical references?
It's perfectly valid and here is a document by Apple talking about it:
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html#//apple_ref/doc/uid/TP40011210-CH5-SW6
I don't personally use it as I prefer the syntax of a class continuation category.
I was also curious about this. Here is the updated link from Apple:
You Can Define Instance Variables without Properties
It’s best practice to use a property on an object any time you need to keep track of a value or another object.
If you do need to define your own instance variables without declaring a property, you can add them inside braces at the top of the class interface or implementation, like this:
#interface SomeClass : NSObject {
NSString *_myNonPropertyInstanceVariable;
}
...
#end
#implementation SomeClass {
NSString *_anotherCustomInstanceVariable;
}
...
#end

Inherited Methods that are not in Header File of Superclass

Is there a way to have "private" methods in a superclass (which are not in its header file) and still be able to access these from subclasses?
You could use a custom category, for example:
Stuffy.h
// The "official" header file to be used by almost anyone
#interface Stuffy {
int myMember;
}
- (void) somePublicMethod;
#end
Stuffy+Secret.h
// The magic header file, which should only be used by knowledgable people
#import "Stuffy.h"
#interface Stuffy (Secret)
- (void) _pseudoProtectedMethod;
#end
Stuffy.m
#import "Stuffy+Secret.h"
#implementation Stuffy
- (void) somePublicMethod {
// ...
}
#end
#implementation Stuffy (Secret)
- (void) _pseudoProtectedMethod {
// ...
}
#end
Subclasses of Stuffy can now either import Stuffy.h in their .m files and stick to the public API, or import Stuffy+Secret.h and use the semi-protected stuff.
Note, that Objective-C has no true notion of protected or private methods. Basically, anyone can include Stuffy+Secret.h and use the stuff declared there.
You can "cheat" several ways. In addition to categories, you can simply cast your Stuffy pointer to FunnyStuff, and have a whole 'nother #interface for it. (Just don't declare any statics and don't do an #implementation.) Or, a little cleaner, cast to an #protocol that defines your added methods. (And, since you're doing a subclass, you can simply add the protocol to your subclass definition, and avoid any casting.)
Keep in mind that Objective-C doesn't require that every method in an #implementation have a corresponding declaration in #interface, and method calls are entirely dynamic, effectively including name look-up. The only thing you have to do is to trick the compiler into allowing the call. (In fact, you can make the call with no declaration at all if you don't mind the compiler warning.)

Putting methods in separate files

I have a class (MyClass) with a lot of methods. Consequently, the .m file has become quite difficult to read. I'm relatively new to Objective-C (having come from REALbasic) and I was wondering if it's possible to put some of the methods in MyClass into different files and then include them in the class. How would I go about this in Xcode?
Yes it is possible and fortunately this can be done easily in Objective-C with Categories.
Say you have your base class MyClass.
#interface MyClass : NSObject
-(void) methodA;
#end
And the according implementation file (not relevant here).
Then you can create a category by defining a new interface in a new header file:
// the category name is in parenthesis, can be anything but must be unique
#interface MyClass (extended)
-(void) methodB;
#end
and the implementation file:
#implementation MyClass (extended)
-(void) methodB {
}
#end
Common convention to name these files is ClassToAddMethodsTo+CatgoryName, i.e.:
MyClass+extended.h
MyClass+extended.m
Group related functionality into categories and give it a meaningful name.
In Objective-c you can break a class into 'categories' - a class spread across many files. The normal Object-Oriented way is to use SuperClasses and SubClasses.
This is almost certainly a code smell telling you that you have a design problem. See this antipattern
There is one thing you could do..........
But be warned, some might consider this pure blasphemy. :)
Say you have a class with two methods you want to have in separate files.
You'll have three files:
• Class.h
• Class.m
• Class_otherMethod.m
Your Class.h should look just like any other. I think it's better to keep the header file complete, but this 'trick' can work on separating .h files just as well.
#interface Class : NSObject
- (void) method;
- (void) otherMethod;
#end
In your Class.m file you will #include the Class_otherMethod.m inside the Class #implementation like this:
#import "Class.h"
#implementation Class
- (void) method {
// do something.
}
#include "Class_otherMethod.m"
#end
And your Class_otherMethod.m file will have only the bare otherMethod implementation:
- (void) otherMethod {
// do something different.
}
Why this works
It's quite simple actually. The preprocessor simply "pastes" the content of Class_otherMethod.m inside the Class.m file and the compiler treats it as one big long file. :P