How to create NSMutableArray in which objects follow protocol? - objective-c

How to create NSMutableArray in which objects follow protocol?
For example in swift I can do something like:
var array:[MyProtocol] = []
How to implement that in objC

In Objective-C you declare a variable of protocol type by declaring it as id<SomeProtocol>, e.g.:
#protocol SomeProtocol<NSObject>
...
#end
#interface SomeClass : NSObject<SomeProtocol> // base class NSObject, implements SomeProtocol
...
#end
#implementation SomeClass
...
#end
// a variable declaration somewhere which holds a reference to any object
// which implements SomeProtocol
id<SomeProtocol> anyObjectImplementingSomeProtocol = SomeClass.new;
Using Objective-C's lightweight generics you can extend this to containers of protocol type, e.g.:
NSMutableArray<id<SomeProtocol>> someArray = NSMutableArray.new;
Warning: Lightweight generics are named that for a reason, it is quite easy to bypass the restrictions imposed by them, e.g. by adding an object which does not implement SomeProtocol to someArray. You don't get the same strong generics as in Swift.
HTH

Related

Pass #protocol type in Swift

I have an Objective-C method which takes Protocol* type as parameter.
How can I invoke this method in Swift.
Example:
// In Objective-C
#protocol AProtocol <NSObject>
#end
#interface MyClass : NSObject
+ (id)proxyWithProtocol:(Protocol*)protocol;
#end
// I can call this method with a protocol as parameter
[MyClass proxyWithProtocol:#protocol(AProtocol)];
If I want to use MyClass in Swift by bridging. How can I pass a protocol defined in Objective-C to proxyWithProtocol method. Can I even pass a protocol defined in Swift to this method?
You would pass the Objective-C protocol in like so:
MyClass.proxyWithProtocol(AProtocol)
If you wanted to pass in a Swift protocol, you would have to expose that protocol to Objective-C:
#objc protocol MyProtocol {
func someGreatFunc()
}
// ...
MyClass.proxyWithProtocol(MyProtocol)
In Swift 3, depending on the way the class is bridged to Swift, your function might look like this:
MyClass.proxy(with: AProtocol)
MyClass.proxy(with: MyProtocol)
Although the compiler isn't happy with the location of "with" and may complain.

Cocoa Singletons and Protocols

I want to define a protocol and create an easy, standard way to grab a 'default', shared implementation of said protocol - singleton style. Cocoa adhere's to the following pattern:
[NSUserDefaults standardUserDefaults]
[NSNotificationCenter defaultCenter]
but in both cases, they have #interfaces at the bottom of the object hierarchy. I'm struggling with how to do this using #protocols. I can obviously create a class that has empty or simple method implementations - but in reality, what I want is a #protocol at the bottom of the hierarchy. I've tried something like:
#protocol ConfigurationManager <NSObject>
//...
#interface ConfigurationManagerFactory : NSObject
+ (id<ConfigurationManager>)sharedConfiguration;
#end
// ...
id<ConfigurationManger> config = [ConfigurationManagerFactory sharedConfiguration];
[config ...];
and it works - but I'm always having to explain how to use this and why I did it this way. Is there a way to conform to Cocoa's syntax (calling convention) while still leveraging the value of #protocols?
As an aside, is there a reason why I wouldn't want to use #protocols like this? The implementing #interface can still leverage categories and alternate implementations, etc - just like how instantiating an NSString usually leaves you with a class extending NSString.
Here's an idea: create your protocol and a class with the same name with a factory method that returns you the default implementation of the protocol:
#protocol ConfigurationManager <NSObject> ...
#interface ConfigurationManager : NSObject <ConfigurationManager>
+(ConfigurationManager *) defaultConfigurationManager;
...
Other specialized implementations can then inherit from your base class.
The whole point of a protocol is that it specifies an interface without providing an implementation. If you want a default implementation, provide a class that implements your protocol, much as the NSObject class implements the NSObject protocol. Then clients can either subclass the class that you provide, or instantiate the class you provide and use the resulting object's implementation, as with your config object.

Does Objective-C have something like C++ virtual functions?

In objective-c it is possible to add a #dynamic to a property.
Is this also possible for normal instance methods?
EDIT
I think i wasn't clear enough.
I want to do the following:
#interface MyClass
#property (retain) NSObject *somePropertyObject;
- (void) myMethod;
#end
#implementation MyClass
#dynamic somePropertyObject;
//Make myMethod dynamic. I do not want to implement it. Like C++ Virtual
#end
If you mean "How can I declare a method, but not provide a definition which I will subsequently provide at runtime?" Then it's easy, just use a category. Like this:
#interface MyObject : NSObject
// Methods I'll define
- (void)doFoo;
#end
#interface MyObject (DynamicallyProvidedMethods)
// Methods I won't
- (void)myDynamicMethod;
#end
#implementation MyObject
// Methods I'll define
- (void)doFoo
{
}
#end
The compiler will not complain, however if you call -myDynamicMethod at runtime, unless you have provided an implementation for it somehow, it will crash with "unrecognized selector." You can, of course, test for that at runtime by calling respondsToSelector:.
Relatedly, if you're looking to do a near-equivalent of a base class pure virtual method, I would recommend providing an empty implementation that asserts when called if it has not been overridden by a subclass. You can do that like so:
NSAssert((class_getInstanceMethod([self class], _cmd) == class_getInstanceMethod([MyObject class], _cmd)),
#"Subclass of %# must override -%#",
NSStringFromClass([MyObject class]),
NSStringFromSelector(_cmd));
// ...where overridesSelector:ofBaseClass: looks like:
//
// return ;
Of course, that won't alert you to problems at compile time, but it's better than nothing.
HTH
I think you might be asking how to declare a method that will be implemented some time later somewhere else.
The Objective-C way to do that is to use Protocols.
You declare a protocol like this, usually in a header file
#protocol MyProtocol <NSObject> {
#optional
- (void)optionalMethod;
#required
- (void)requiredMethod;
}
#end
This declares two methods, one which is optional and one is required. To use this protocol you declare the conformance when declaring the class that will implement the protocol
#interface MyConformingClass : NSObject <MyProtocol> {
}
// you don't have to redeclare methods that are declared in the protocol
#end
This new class is checked at compile time for the implementation of requiredMethod so it has to implement it, but it can choose whether or not to implement the optionalMethod
Now, any class that requires instances of objects to conform to the protocol can declare this, for example, in the interface
#interface RequiringClass : NSObject {
MyConformingClass <MyProtocol> *conformingClassObject;
}
…
#end
Again, this is checked at compile time
To make sure that the conforming class implement the #optional methods, we can use this handy structure
if [conformingClassObject respondsToSelector:#selector(optionalMethod)] {
[conformingClassObject optionalMethod];
} else {
// Do something here because the optional method isn't provided
}
Examples of this are all over Cocoa - it's a class can provide a list of actions that it would like to farm out to it's delegate, the delegate adopts the protocol and provides the implementations of those delegate methods. The calling object can then check if this delegate responds to those methods at runtime as I've described above, and call those methods to perform actions, or provide information where ever it needs to.
This is used quite a lot in Objective-C, where classes provide a list of methods that they would like some other class to perform, unlike virtual functions, where a class declares functions it wants subclasses to provide implementations for. Particularly as Composition is favoured over inheritance in the language. Rather than create a subclass to provide an implementation, you just create another class that can do the same thing, and add a reference to that in the class instead.
No.
#dynamic is just an instruction to the compiler that says: "Don't bother generating accessors for this property, I'm going to provide my own."
Using #dynamic with other methods wouldn't be helpful because the compiler doesn't generate any methods other than accessors for you, and of course you're supplying the other methods anyway.
What are you trying to accomplish?

Construction "Class<? extends SomeType>" variable declaration in Objective-C

I am just curious about whether declaring a variable in a way known from Java is possible in Objective-C:
Class<?extends SomeType>
For example: I have a class called MyClass. It has a static method
+ (void)myMethod
It has also two subclasses: MySubclassA and MySubclassB. I have such code:
Class myClass;
if(<some condition>) {
myClass = [MySubclassA class];
} else {
myClass = [MySubclassB class];
}
[myClass myMethod];
This code works fine, there are no compiler warnings, but I am just curious whether the construction I mentioned is somehow present in Objective-C.
Thanks!
Objective-C does not have templates (like C++) or generic types with type erasure (like Java) or runtime generic types (like C#). Unlike these languages, Objective-C messages are dynamically dispatched at runtime (instead of bound at compile time). Thus, many of the systems for producing type-agnostic code in C++, Java or C# are unnecessary. Objective-C prefers "duck-typing" whereby any object that responds to a given selector (message) can be given that message by calling code, regardless of the receiving object's type. Since classes are objects in Objective-C, the same is true for class methods as for instance methods.
So, given
#interface MyClassA : NSObject
{}
- (void)someMethod;
#end
#interface MyClassB: NSObject
{}
- (void)someMethod;
#end
calling code can look like this
- (void)someOtherMethodInAnOtherClassWithObject:(id)obj
{
[obj someMethod];
}
This code will compile and will work fine at runtime, assuming obj is either an instance of MyClassA or MyClassB.
Of course, good practice would dictate that you define a #protocol in this situation:
#protocol MyProtocol
- (void)myMethod
#end
and declare that your MyClassA and MyClassB both implement the MyProtocol protocol. Your calling code would then look like
- (void)someOtherMethodInAnOtherClassWithObject:(id<MyProtocol>)obj
{
[obj someMethod];
}
and the compiler would give you a warning/error (depending on -W flags) if you tried to call someOtherMethodInAnOtherClassWithObject:, passing an object of a type that doesn't implement the MyProtocol interface.
Note that id<MyProtocol> is not a generic type, it's an instance of type id that you are claiming implements the MyProtocol protocol. Also note that the first version of client code works just fine because all that really maters is whether obj can respond to the -myMethod selector.

Objective C - How can I create an interface?

I need to be able to create an interface like you create in C# to enforce a group of classes to implement certain methods.
Is this possible in objective c?
You can create a protocol. it would look something like this:
in MyProtocol.h:
#protocol MyProtocol
-(void)myMethod;
-(void)myMethod2;
#end
in MyClass.h
#import "MyProtocol.h"
#interface MyClass : NSObject<MyProtocol>
#end
If you want to receive objects of a given protocol, you can do so like this:
id<MyProtocol> var;
or
NSObject<MyProtocol> *var;
more info here
You declare a "protocol" (Objective-C's interfaces) using
#protocol MyProtocol <BaseProtocol1,...,BaseProtocolN>
//methods and properties
#end
where <BaseProtocol> is optional and indicates that MyProtocol "inherits" BaseProtocol's interface. The NSObject protocol is useful in this context because it allows you to use
#protocol MyProtocol <NSObject>
//...
#end
to indicate (when appropriate) that conforming instances of MyProtocol have the standard NSObject methods as well (e.g. -retain/-release, etc.).
You then declare that a class "conforms" to a protocol:
#interface MyClass : NSObject <MyProtocol,...,OtherProtocols>
{}
#end
And you can test whether an instance conforms to a protocol:
id myInstance = ...; //some object instance
if([myInstance conformsToProtocol:#protocol(MyProtocol)]) {
// myInstance conforms to MyProtocol
}
You can further silence compiler warnings by declaring that a variable holds instances that conform to a protocol (note that Objective-C's dynamic nature prevents the compiler from verifying that contract and you can still get runtime errors by assigning a non-conforming instance to the variable):
id<MyProtocol> o;
In this case, the compiler will complain if you send [o retain] without MyProtocol conforming to the NSObject protocol. You can silence these warnings by declaring MyProtocol as conforming to NSObject as described above or by delcaring o as
NSObject<MyProtocol> o;
Since NSObject is not the only root object in Cocoa (i.e. NSProxy does not inherit from NSObject), it's not necessarily true that all instances conforming to MyProtocol also conform to NSObject. If you know that they do, you can declare MyProtocol as conforming to NSObject.
In the Objective-C world, interfaces are called "Protocols"
According to Apple,
Protocols declare methods that can be implemented by any class. Protocols are useful in at least three situations:
To declare methods that others are expected to implement
To declare the interface to an object while concealing its class
To capture similarities among classes that are not hierarchically related
So, to declare a protocol you can:
#protocol SomeClassProtocol
- (void) do:(int) number something:(id) sender;
- (void) somethingElse;
#end
To implement a protocol , you do:
#interface MyClass : NSObject <Protocol1, Protocol2, ..., ProtocolN>
#end
Check out this link for the official documentation.
Interfaces are called protocols in Objective C
If you go to add a class to your project you will have an option to create it as protocol and you will end up with something like:
#protocol MyProtocol
-(void) DoSomething;
#end