Meaning of the angle brackets in Objective-C? - ios

Even though the question is quite wide I am actually curious regarding one case I sow recently while using the Realm library. As I previously used the protocols(delegate) on many occasions and also imported classes using <>. And now this is the line the code I don't completely understand or don't understand at all if I am mistaking:
#property (nonatomic, strong) RLMArray <ExerciseLog *><ExerciseLog> * exerciseLogs;
I suppose that the second part of the line <ExerciseLog> * exerciseLogs is used to ensure that exerciseLogs may be an instance of any ExerciseLog that conforms to the ExerciseLog protocol, is my assumption correct?
Or simple said if the user send a different object then the expected one, the app won't crash, and that a default value will be assigned.
And this part I am guessing, the is some sort of safe casting so that the returned object confirms to the ExerciseLog.

A combination of Obj-C protocol conformance and generics. RLMArray is declared as
#interface RLMArray < RLMObjectType : RLMObject * > : NSObject<RLMCollection,NSFastEnumeration>
it has one generic argument. That's the <ExerciseLog *>.
The second part <ExerciseLog> is conformance to protocol of the given type.
By the way, that protocol is declared using RLM_ARRAY_TYPE macro. The code seems to be a bit complicated but it was probably an older way to enforce element type for arrays (RLMArray<protocolX> is not assignable to RLMArray<protocolY>).
Quoting the documentation:
Unlike an NSArray, RLMArrays hold a single type, specified by the objectClassName property. This is referred to in these docs as the “type” of the array.
When declaring an RLMArray property, the type must be marked as conforming to a protocol by the same name as the objects it should contain (see the RLM_ARRAY_TYPE macro). RLMArray properties can also use Objective-C generics if available. For example:

The angle brackets in a class interface definition indicates the protocols that your class is conforming to.
A protocol is almost like an interface in Java or C#, with the addition that methods in an Objective-C protocol can be optional.
Additionaly in Objective-C you can declare a variable, argument or instance variable to conform to several protocols as well. Example
NSObject *myVariable;
In this case the class must be NSObject or a subclass (only NSProxy and its subclasses would fail), and it must also conform to both NSCoding and UITableViewDelegate protocols.
In Java or C# this would only be possible by actually declaring said class.

Related

id<> required for MTLDevice class

I am very new to Objective-c so bear with me I am still trying to make sense of the multitude of places you can put properties and class variables in objective c.
I am an experienced Metal developer but I have barely done anything with objective-c.
I am trying to create a MetalCore class that will hold the MTLDevice, MTLCommandQueue and facilitate the creation of the apps core pipelines etc.
I therefore defined the following
#property (readonly, nonatomic, assign) MTLDevice* devicePtr;
In my class however I get the error Unknown type name MTLDevice; did you mean... even though I #import <Metal/Metal.h> so what is going on here?
I looked on stack overflow and found examples where people were defining function like this
- (<MTLDevice> *)device;
or
- (instancetype)initWithDevice:(id<MTLDevice>) device;
What is going on with this whole id and <> thing? In what cases can you omit the id part?
What I find especially weird is while id seems to be required for most Metal types there are some like MTLRenderPipelineDescriptor that dont need it and in fact only work in the Type* mode. Why is this and how do I determine what is needed from the documentation?
In Objective-C, id basically means "any object type". If you want to ensure that an object conforms to a protocol (such as MTLDevice), you specify the protocol in angle brackets after id when stating its type: id<MTLDevice> means "a type that conforms to the MTLDevice protocol".
Unlike with concrete classes (such as MTLRenderPipelineDescriptor), you don't use a * after id, so you wouldn't write id<MTLDevice> * (unless you were taking a pointer to a device, which is uncommon). MTLDevice * doesn't make sense because MTLDevice isn't a concrete type. <MTLDevice> by itself is nonsense, and a syntax error, as is <MTLDevice> *.
Coming from Swift, you might be used to conflating between protocols and concrete types, since Swift doesn't make a syntactic distinction between "some type that conforms to a protocol" and "some concrete type." To tell whether something is a protocol, consult the documentation; it'll explicitly note when something is a protocol. In Metal, all "descriptor" types are concrete (e.g., MTLRenderPipelineDescriptor), while most other object types are abstracted behind protocols (MTLDevice, MTLCommandQueue, MTLLibrary, MTLFunction, MTLTexture, MTLRenderPipelineState, MTLCommandBuffer, etc.)
If you know java ,id<MTLDevice> is like a object that inherited the Interface named ‘MTLDevice’.
Mainly due to different iPhone has different GPU architectures. For the maximum efficiency,different GPU has different implementation of metal.
Such as in iPhoneX the real MTLDevice is a class named 'AGXA11Device' , while in iPhone 6 plus is 'AGXA9Device'.

Cannot assign a value of type 'AnyDataSource<NSManagedObjectSubclass>' to a value of type 'AnyDataSource<NSManagedObject>'

I'm stumped.
The title of this question the compiler error.
I am creating an object that basically marries the delegates of NSFetchedResultsController and UITableViewDataSource. The type parameter is used to indicate which NSManagedObject subclass should be used in the fetch requests.
Here is an example where Swift lacks dynamism and we end up writing all sorts of crazy code, (OR, I'm new to Swift and dislike being told what I'm not allowed to do)
So, on a UITableViewController subclass, i'd like to have a property
var dataSource: AnyDataSource<NSManagedObject>?
when I try to create one of these with a subclass of NSManagedObject and assign it to that property, the compiler complains. There seems to be nothing I can do that will succeed without a warning.
You would think that I should be able to use NSManagedObject or any of its subclasses, so I'm a little confused.
Any ideas? I'm using typical "type erasure" patterns that can be found on the internet, like via realm.io.
Ultimately I found that this approach was not possible. I mean, to achieve these with completely protocol-based programming.
I defined a few base protocols with no associated type, implemented an abstract baseclass that implements that protocol, then introduced generic type parameters in subclasses, that implement further protocols that have associated type.
I'll post my generalized solution on github when it's finished.

when use protocol not for a delegate in objective-c?

A protocol is a list of method statement , anyone who conforms to it must or may implement it .
In most cases,a delegate's implementation relies on protocol,such as below:
#protocol VSActivateCouponDelegate <NSObject>
-(void)activateCouponSuccessWithActivateType:(ActivateType)type;
#end
My question is protocol's usage scenarios except implementing Delegate ?
For example, any interface that you want to keep generic in terms of not knowing the exact class that will be providing a specific role in some relationship. Delegate is one example of that but any relationship between two classes could use the same approach to abstraction.
Check out NSCopying, NSCoding etc. These are also protocols, but they are not used as delegates.
Let's look at NSCopying for example. If a class conforms to NSCopying, you know that you can call copy on any of its instances (and... copy it ), without even looking at the specific class, you can even pass instances as id<NSCopying> - this makes things more decoupled. For instance NSDictionary only accepts key values that are id<NSCopying>.
To summarize, protocols let you declare behavior without coupling it to a specific class. It doesn't always have to be delegates.
an example would be:
say you have an array of arbitrary objects of arbitrary types. now you want to make sure that all the objects at least have a certain function you can call on all of them to make them do something, then you can make all those objects conform to a protocol that has that method, thus making sure all the objects in that array have that certain functionality.
pseudo code of what that may look like:
#protocol MyProtocol {
- (void) doSomething;
}
//used somewhere
for(MyProtocol object in arrayOfUnknownObjects)
[object doSomething]; //dont know what object's type is but we know it has [doSomething] method

Is it possible to make an NSObject conform to a protocol ? and if it, how ? -Take it serious

My question may seem strange, but i wanna to get this idea around Stackers' minds, in my work i just noticed that every protocol is conformed by a class all the time, i wondered about the possibility to make a simple object conforms to protocols too, and if not (and almost not ), why not ??
Appreciate your concern
There are two parts to protocol conformance:
the object must respond to the required messages in the protocol definition
the object must return YES when asked whether it conforms to the protocol
So, can we arrange for an instance of NSObject to satisfy those two conditions? Yes. In fact, there are at least two ways to do so. First, let's make all instances of NSObject conform to the protocol. What we do is to define the protocol methods in a category on NSObject, which solves the first part. Then we "swizzle" (which means using the class_replaceMethod() runtime function) -[NSObject conformsToProtocol:], returning YES for our interesting protocol.
Now let's imagine that you want to make a specific instance of NSObject conform to the protocol. This is slightly easier. First, create a subclass of NSObject that conforms to the protocol and implements the required methods; there's no need to override -conformsToProtocol: because the runtime library can see that this class conforms. Now, at runtime, take your NSObject instance and call object_setClass() to switch its class to your conforming subclass.
You can add protocols to classes at runtime, using the runtime function class_addProtocol(). However, doing so when the class does not implement all the methods of the protocol will likely lead to bad results.

Do I need ARC keywords for properties that I don't synthesize?

I have a property that I do not synthesize, instead I create a getter and setter myself. Therefore, the ARC keywords (strong or weak) have no meaning, I assume, so I eliminate them. This works fine on Xcode 4.3, but when my coworker opens them on XCode 4.2 the compiler complains that there is no strong/weak keyword, so I instructed him to meaninglessly enter the keyword back in again. Which is correct (with or without keywords)?
To be clear: I have a property like this #property (nonatomic) NSString *foo and in the .m file I implement -(NSString *)foo and -(void)setFoo:(NSString *)foo and do NOT include #synthesize foo. Another relevant detail is that there is no corresponding iVar, instead the properties interact with a Core Data object. This will not compile in XCode 4.2 unless I add strong or weak to the keywords.
EDIT I thought of one more relevant thing, one of these properties is on a Protocol, I don't know if that makes a difference.
The declared attributes that you are referencing are optional. To quote the documentation:
Property Declaration and Implementation
The #property directive declares a property. An optional parenthesized
set of attributes provides additional details about the storage
semantics and other behaviors of the property - see “Property Declaration Attributes” for possible values.
Property Declaration Attributes
You can decorate a property with
attributes by using the form #property(attribute [, attribute2, ...]).
Like methods, properties are scoped to their enclosing interface
declaration. For property declarations that use a comma-delimited list
of variable names, the property attributes apply to all of the named
properties.
If you use the #synthesize directive to tell the compiler to create
the accessor methods (see “Property Implementation Directives”), the
code it generates matches the specification given by the keywords. If
you implement the accessor methods yourself, you should ensure that it
matches the specification (for example, if you specify copy you must
make sure that you do copy the input value in the setter method).
If you then use #dynamic instead of #synthesize it is telling the compiler that you will be writing your own methods and prevents it from complaining when it doesn't find suitable methods.
More information can be found here.
borrrden,
First, why do you care to elide your memory policy in your property statement? It announces to consumers of your class what the policy is. Don't you want them to know?
Second, the #synthesize is not a nop. It is the mechanism by which the language support KVO. While you may not be using that now, why would you preclude this use for the future.
Frankly, by not using a full description in #property nor using #synthesize, you are, IMO, engaging in premature optimization. Your current design doesn't save you message dispatches and forces you to manage, if necessary, the creation and typing of ivars. And you are losing features of the language.
Unless you have a good reason to get outside the bounds of the preferred Obj-C v2+ patterns, and you haven't listed those, then I would return to using the standard pattern. Then your problem just goes away.
Andrew

Resources