Objective c protocol generics - objective-c

Can Objective-C protocol be generic?
Following this tutorial, I'm basically looking for something like that:
#protocol ItemsStore<__covariant ObjectType> <NSObject>
-(NSArray <ObjectType> *)items;
#end
Which is a generic protocol for some ObjectType that "implements" ("inherits") another protocol NSObject

As #rmaddy suggested, and as referred to this questions, it is NOT possible.
Shame, moving to Swift then...

Maybe you could just redefine it as generic in the interface.
#protocol ItemsStore <NSObject>
- (NSArray *)items;
#end
#interface MyItemsStore<ObjectType> : NSObject <ItemsStore>
- (NSArray <ObjectType> *)items;
#end
This seems an unlikely scenario though. You might be better just defining the type of the items in each subclass. Like what Apple do with NSFetchRequest in their core data model generation.

Probably, this question has exactly the same source problem as mine. Well, the idea of the design is great but doesn't work with ObjC. I also was wondering about that. I thought it could work some way like that:
#protocol Prototype<__covariant OtherProtocolOrClass> <NSObject>
/// Construct an object of the desired class or protocol
#property (nonatomic, nonnull, readonly) <OtherProtocolOrClass> objectFromPrototype;
#end
(I have not tested #protocol Prototype <NSObject,__covariant OtherProtocolOrClass> yet, but think it will fail.)
Another object in my framework (it is a collection) states, it can auto-construct an NSArray<ObjectType>* of an object type, if there is a Prototype that returns instances, like this:
#interface ValueProto : NSObject <Prototype<id<Value>>>
#end
#implementation ValueProto
-(id<Value>)objectFromPrototype {
return [Value new];
}
#end
Im my dreams, the collection was constructed like this:
MyCollection<id<Value>>* const collection = [MyCollection new];
collection.prototype = [ValuesProto new];
And if you then access the collection's property, your array of id<Value> objects is constructed on the fly:
-(NSArray<id<Value>>*)values {
NSArray*const sourceCollection = ...
NSMutableArray<id<Value>>* const result = [NSMutableArray arrayWithCapacity:sourceCollection.count];
for (id o in sourceCollection) {
id<Value> v = self.prototype.objectFromPrototype;
v.content = o;
[result addObject:v];
}
return result;
}
Instead one of my class' objects must be the prototype itself:
-(id)objectFromPrototype {
return [self.class new];
}
That clashes with my so-called 'Injector', which constructs and returns objects by protocols instead of classes.
If any Apple engineer is reading this:
Please, provide protocol covariants for ObjC. It's not yet dead! :-)

Why not use generic abstract class?
#interface AbstractItemStore <__covariant ObjectType> : NSObject
- (NSArray<ObjectType> *)items;
#end
#implementation AbstractItemStore
- (NSArray<id> *)items {
NSParameterAssert("Not implemented!");
return nil;
}
#end

Related

add category property to a class confirming to a protocol

I have a generator which returns objects conforming to protocol A.
I would like to add a property, probably with categories, to these objects so i can do something to serve my purposes, which obviously isn't there in the protocol.
is this doable?
The more I've thought about this, the more I agree that it's not a duplicate, and in fact the answer is very straightforward as long as what you say you want is what you really want.
Given that you are returning values that conform to some protocol, create a type that conforms to that protocol, and forwards all protocol methods to a wrapped value. Then you can add whatever additional properties you'd like.
For example, given a protocol like:
#protocol Runnable <NSObject>
- (void)run;
#end
You can create a trivial wrapper like:
#interface AnyRunnable: NSObject <Runnable>
- (instancetype)initWithRunnable:(id<Runnable>)runnable;
#end
#interface AnyRunnable (Private)
#property (nonatomic, readwrite) id<Runnable> wrapped;
#end
#implementation AnyRunnable
- (instancetype)initWithRunnable:(id<Runnable>)wrapped
{
self = [super init];
if (self) {
self.wrapped = wrapped;
}
return self;
}
- (void)run {
[self.wrapped run];
}
#end
Now, AnyRunnable is a Runnable, so you can return that from your method. It's also a type you control, so you can add any properties you like to it. This scales to any protocol; you just need to implement the required methods.
It's not possible to do this via a category for the reasons given in Why can't categories have instance variables? (If it were possible to add properties based on protocols, but not classes, then you could just define a protocol that matched your class, and bypass that limitation.)
Here is possible approach (based on Objective-C associated objects). Tested & worked.
Assume we have some class, which we cannot touch
#interface SomeClass: NSObject
#end
#implementation SomeClass
#end
Then some new properties can inject in the following way
#interface SomeClass (VirtualProperty)
#property (atomic) NSInteger virtualProperty;
#property (nonatomic, readonly) NSInteger calculableProperty;
#end
static const char *kVirtualPropertyKey = "virtualProperty";
#implementation SomeClass (VirtualProperty)
#dynamic virtualProperty;
- (NSInteger)calculableProperty {
return self.virtualProperty * 2;
}
- (NSInteger)virtualProperty {
return [(NSNumber *)objc_getAssociatedObject(self,
kVirtualPropertyKey) integerValue];
}
- (void)setVirtualProperty:(NSInteger)newValue {
objc_setAssociatedObject(self, kVirtualPropertyKey,
#(newValue), OBJC_ASSOCIATION_RETAIN);
}
#end
Usage:
SomeClass *some = SomeClass.new;
some.virtualProperty = 5;
NSLog(#"Result: %lu", some.calculableProperty);

Swift Classes vs. Objective-C Classes. Am I on the right track?

I am new to Swift. I've taken a couple of online course and have started converting an existing Objective-C project to Swift as a learning experience. I have a few questions if someone has time. I've searched the board but haven't found the answers. I am sorry if I missed them.
Delegate Protocols - I'm used to defining my own in Objective-C. Below I have the original Objective-C version and below it I have my new Swift version. Have I followed the correct design pattern for Swift?
I find myself making optionals for all of the properties especially objects like NSData or custom classes. Is this practice acceptable? I am not sure how I would know an initial value for most objects. I know the language wants you to set an initial value but it seems strange for certain objects.
If I am not mistaken we do not have to call self.super init in custom initializers in Swift. Is this correct?
Objective-C Version
#protocol FLOParserHandlerDelegate;
#interface FLOParserHandler: NSObject <NSXMLParserDelegate>
// Properties
#property (nonatomic, strong) NSMutableData *PHData;
#property (nonatomic, strong) NSMutableString *currentParsedCharacterData; // This grabs the characters as they come in and adds them together.
#property (nonatomic, strong) NSMutableArray *XMLDataArray; // This is the master array that holds all of the article arrays with the date, title and link objects.
#property (nonatomic, strong) NSMutableDictionary *dateTitleLinkDictionary;// This is used to gather the date, title and link in an array to added to the master array.
// Delegate Property
#property (nonatomic, weak) id <FLOParserHandlerDelegate> delegate;
// init Methods
- (id) initWithCHData: (NSMutableData *) data;
// Class Methods
-(void) startParser;
#end
#pragma mark-
#pragma mark FLOParserHandler Protocol Definition
#protocol FLOParserHandlerDelegate
#optional
- (void) floParserHandlerDidFinishParsing: (FLOParserHandler *) parserHandler;
- (void) floParserHandler: (FLOParserHandler *) parserHandler didFailWithError: (NSError *) error;
#end
Swift Version
import Foundation
protocol FLOParserHandlerDelegate
{
func floParserHandlerDidFinishParsing(parserHandler : FLOParserHandler) -> ()
func floParserHandler(parserHandler : FLOParserHandler, error : NSError) -> ()
}
// Note that we have to inherit from NSObject here. I believe this iis because we are mixing it with Objective-C.
class FLOParserHandler : NSObject, NSXMLParserDelegate
{
var PHData : NSData?
var currentParsedCharacterData : String?
var XMLDataArray : [String]?
var dateDictionary : [String:NSDate]?
var titleDictionary : [String:String]?
var linkDictionary : [String:String]?
// Delegate Property
var delegate : FLOParserHandlerDelegate?
// Init Methods
init(data : NSData)
{
self.PHData = data
}
// Class Methds
func startParser()
{
var parser = NSXMLParser(data: self.PHData)
parser.delegate = self
parser.parse()
}
}
Thank you,
Jon
Your protocol definition is valid. There is one little thing you should know about:
As with type property requirements, you always prefix type method
requirements with the class keyword when they are defined in a
protocol
protocol SomeProtocol {
class func someTypeMethod()
}
Its perfectly fine to use optionals, or you may use implicity unwrapped optionals like NSData!. In which case you should do this and where no, you may read here: Why create "Implicitly Unwrapped Optionals"?.
Shortly, you doing this in following situations:
a) Constant cannot be defined using initializtion, but you know that it would not be nil (otherwise app will crash)
b) Objective-C Api required you to use pointers, and pointers in Obj-C could be nil. In that case you use imilicity unwrapped optionals.
You always have to call 'super' if you have superclass, to be sure, that class is properly initialized.
Hope that helps.

Is it possible to add a category to an Objective-C meta-class?

I would assume... NO. But wouldn't it be nice if instead of...
NSStringFromClass(SomeClass)
you could...
#interface Class (ToString)
#property (readonly) NSString* stringValue;
#end
#implementation Class (ToString)
- (NSString*) stringValue { return NSStringFromClass(self); }
#end
and subsequently use...
SomeClass.stringValue
I'm sure there's a good reason the meta-heirarchy prevents this (although it seems like a half-truth when it's said that Classes (and Protocols, and Methods, etc) are-indeed "real" Objects)... when a lot of the "stuff" that makes a NSObject an Object can NOT be performed on a "metaclass".
Can anyone shed a light on this functional difference / offer an alternative (i.e. resolveClassMethod: that might achieve similar result?
Since an instance method of a metaclass is just a class method on the non-meta class, why not simply add a category on the original (non-meta) class?
#implementation NSObject (Name)
+ (NSString *)className
{
return NSStringFromClass(self);
}
#end

Dependency injection with #protocol?

Can I use a #protocol for interfacing between classes? My main goal is to do some dependency injection like in Java (with interfaces and implements).
I've got the following classes: SignUpServiceImpl (which has an interface called SignUpService) and ServiceHelperImpl (interface is ServiceHelper).
I don't want to hard wire both implementations together so I use a #protocol in ServiceHelper which is implemented by ServiceHelperImpl. Then SignUpServiceImpl is initialized with ServiceHelper like this:
- (id)initWithHelper:(ServiceHelper *)myServiceHelper
Is what I'm trying to accomplish possible? It looks so much easier in Java....
An objc protocol is very similar to a Java interface.
The blocking point for you may be how you expect things are actually tied together -- or protocol syntax.
Declare a protocol:
#protocol ServiceHelperProtocol
- (void)help;
#end
Use it in a class:
#interface SomeClass : NSObject
- (id)initWithServiceHelper:(id<ServiceHelperProtocol>)inServiceHelper;
#end
#implementation SomeClass
- (id)initWithServiceHelper:(id<ServiceHelperProtocol>)inServiceHelper
{
self = [super init];
if (nil != self) {
[inServiceHelper help];
}
return self;
}
#end
MONHelper adopts the protocol:
#interface MONHelper : NSObject < ServiceHelperProtocol >
...
#end
#implementation MONHelper
- (void)help { NSLog(#"helping..."); }
#end
In use:
MONHelper * helper = [MONHelper new];
SomeClass * someClass = [[SomeClass alloc] initWithServiceHelper:helper];
...
To accept an object that conforms to a protocol, your init method should be like this:
- (id)initWithHelper:(id<ServiceHelper>)myServiceHelper
If you want to keep a number of different implementations behind a unified class interface, one way to do this in Objective-C is to create an abstract class SignUpService, then in the init method of SignUpService, instead of returning self you actually return a instance of the class that you want to implement it, so in your case, SignUpServiceImpl.
This is how certain class clusters in Cocoa like NSString work.
Let me know if you need more info.

Objective-C : How may I hide a class member from outside the class?

I'm fighting with something and I don't find any satisfying solution.
I have a class with a "myMutableArray" member.
I would like the class to manage itself adding and removing items from the array, so I don't want any other class being able to access the member and call NSMutableArray methods on it.
In an ideal situation, I would like to have a private getter (to be able to call self.myMutableArray) and a public setter for this member.
Do you know how I may achieve this ?
In other words :
I would like other classes
be able to call
- [oneInstance setMyMutableArray:thisArray]; // set
- oneInstance.myMutableArray = thisArray; // set using setter
- thisArray = oneInstance.myMutableArray; // get
- [oneInstance addItem:anItem]; // add
not being able to call :
- [oneInstance.myMutableArray add:etc...] // add
I would like my class
be able to call
- self.myMytableArray = [NSMutableArray array]; // set
- thisArray = self.myMytableArray ; // get
Thank you.
Is there any reason you need the public setter? It sounds like the class itself owns the array. You'd probably be better off not providing any public property access to the field, and making a public method which copies the values into your private field.
// public interface, in the .h file
#interface MyClass : // superclass, protocols, etc.
- (void) setSomething:(NSArray *)values;
#end
// private interface, not in the .h
#interface MyClass ()
#property (/* attributes */) NSMutableArray *myMutableArray;
#end
#implementation MyClass
#synthesize myMutableArray = myMutableArray_;
- (void) setSomething:(NSArray *)values
{
[self.myMutableArray setArray:values];
}
#end
Foo.h
#interface Foo : NSObject
#property(readonly, retain) NSArray * myReadonlyArray;
- (void) addItem: (Item *) anItem;
- (BOOL) publiclyDoSomething;
#end
Foo.m
#interface Foo()
#property(readwrite, retain) NSMutableArray * myMutableArray;
- (void) doSomethingInPrivate;
#end
#implementation Foo
#synthesize myMutableArray = myMutableArray_;
- (void) addItem: (Item *) anItem
{
// assuming myMutableArray_ was already iniitialized
[self.myMutableArray addObject: anItem];
}
- (NSArray *)myReadonlyArray
{
return self.myMutableArray;
}
... rest of methods (including the public/private) implementations ...
#end
Some details:
Objective-C has "instance variables", not "member variables".
The above defines a public getter and private setter that is synthesized automatically. For clarity's sake, I also added a public method and a private method.
"Public" and "private" in Objective-C are defined entirely by visibility to the compiler. The setter for myMutableArray and the method doSomethingInPrivate are only private because their declarations in an #interface cannot be imported.
self.myMutableArray and [self myMutableArray] do the same thing; the . syntax is merely short hand for an equivalent method call (with a few edge case details beyond this question)
#property in the #interface is purely short hand for method declarations (with a bit of extra metadata).
#interface Foo() is a class extension and not a category. It exists for exactly the purpose demonstrated above; to extend the #interface of a class with additional declarative information whose scope should be limited. It can appear in a header file that, say, you only import in your library's implementation to create library-private functionality.
#dynamic is used when you neither #synthesize an #property nor provide a conventional method implementation. It is not needed otherwise!
I'm probably forgetting something.