instanceType/id keyword explanation

Hello. I am developing an iOS app that uses Core Bluetooth to send data from an iOS device to a BLE micrcontroller. I am following the example TemperatureSensor sample app as a guide and in the LeDiscovery.h and .m files I came accross the id keyword used to create a sharedInstance. I found another online tutorial which implemented almost the same exact code except with the instanceType keyword.


Could some explain what id and instanceType are? How do you which one to use? Also, I would greatly appreciate if someone were to explain the following code in the TemperatureSensor app:


+ (id) sharedInstance

{

static LeDiscovery *this = nil;

if (!this)

this = [[LeDiscovery alloc] init];

return this;

}

Accepted Reply

Here's a layman's interpretation of what is happening with that code.

When another class first executes code like:

aVariable=[[LeDiscovery sharedInstance] aMethod];

that method is called by the nested [LeDiscovery sharedInstance]. Because 'this' is nil it creates (i.e. executes alloc/init) an instance of the class (i.e. it grabs code from a library and sticks it in memory ready to handle any calls to methods in the class and it makes 'this' be a pointer to that one instantiated class. It returns that pointer to the one instantiated class of LeDiscovery and then executes the now modified line of code:

aVariable [this aMethod];


What's cool is the next time any code in your app does the follwoing:

anotherVariable=[[LeDiscovery sharedInstance aMethod];

that method is again called by the nested [LeDiscovery sharedInstance] but this time, because of 'static', the value for 'this' is not nil. It is pointing to that earlier instantiated class, the same one that was created the first time you executed the sharedInstance method in the clsss. So you get a pointer to the pre-existing class.


It is the "Model' in Model-View-Controller. You can share information with any class in your app. be a little careful how you use it.

Replies

1) https://developer.apple.com/library/content/releasenotes/ObjectiveC/ModernizationObjC/AdoptingModernObjective-C/AdoptingModernObjective-C.html


2) The code you posted attempts to provide a single instance of its type that can be shared by various parts of the app without passing it from object to object. If your app has multiple threads, though, this isn't a good way to do that. I suggest looking for examples of shared instances that use dispatch_once as the means of doing it.

Here's a layman's interpretation of what is happening with that code.

When another class first executes code like:

aVariable=[[LeDiscovery sharedInstance] aMethod];

that method is called by the nested [LeDiscovery sharedInstance]. Because 'this' is nil it creates (i.e. executes alloc/init) an instance of the class (i.e. it grabs code from a library and sticks it in memory ready to handle any calls to methods in the class and it makes 'this' be a pointer to that one instantiated class. It returns that pointer to the one instantiated class of LeDiscovery and then executes the now modified line of code:

aVariable [this aMethod];


What's cool is the next time any code in your app does the follwoing:

anotherVariable=[[LeDiscovery sharedInstance aMethod];

that method is again called by the nested [LeDiscovery sharedInstance] but this time, because of 'static', the value for 'this' is not nil. It is pointing to that earlier instantiated class, the same one that was created the first time you executed the sharedInstance method in the clsss. So you get a pointer to the pre-existing class.


It is the "Model' in Model-View-Controller. You can share information with any class in your app. be a little careful how you use it.

Could some explain what id and instanceType are? How do you which one to use?

There’s three common cases:

  • In your

    +sharedInstance
    example, you should set the return type to the actual type (
    LeDiscovery *
    ). That’s because this method can’t possibly return anything other than that type.
  • For an init method you should use

    instancetype
    ; this tells the compiler at the call site that the method will return an instance of the messaged type. This allows the compiler to catch a variety of common bugs via static type checking (like
    NSMutableArray * a = [[NSArray alloc] init];
    ).
  • id
    basically turns off all static type checking: you can assign it to anything and call it as anything without the compiler complaining. It is traditionally used for container methods (like
    -getObjectAtIndex:
    ) where you’ve no idea what the returned type will be (although recently we’ve started using lightweight generics to get better static type checking in that case as well).

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Oh, I forgot one extra fun case:

If you know that the returned value will be an instance of class

***
or one of its subclasses, you can use
__kindof *** *
. A classic example of this is UIView’s
-viewWithTag:
, where the result is always some sort of view.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks PBK for explaining the code. Also thanks Quinn for explaining the difference between id and instanceType, it clarified a lot!