When to use respondsToSelector vs objc_getClass - ios

if respondsToSelector("UIAlertController"){
//do something
}
if objc_getClass("UIAlertController") != nil{
//do something
}
These both have the same results overall. Is there a case when one is better than the other one? Or should only one of them be used and the other forgotten?

respondsToSelector : This is basically used for to check if object reference, can call perticular method or not. For example, object has inherited from some base class or implemented by some protocols, then it is better to check whether object is able to respond to that method or not, then only call it.
Otherwise it will throw runtime error, method not found type.
if([obj respondsToSelector:#selector(anyMethod)]) {
[obj fizzyWizzle];
}
else {
// do something
}
objc_getClass : The Class object for the named class, or nil if the class is not registered with the Objective-C runtime. It means, are you able to access this class or not, if that class does not exist then it will return 'nil'. So,
if objc_getClass("UIAlertController") != nil{
// it means, these class is available in SDK, hence its iOS version is 8.x
// here you can alloc - init and use UIAlertController functionality
}
else {
// class could not be found
// iOS version is < 8.0
// here that class is not available hence use UIAlertView which is supported by iOS 7 and earlier.
}
Hope this helps.

For checking the class existence you must use objc_getClass. (For Class compatibility with iOS versions)
For checking whether a class implemented a method or a method is available or not you need to use respondsToSelector (For method availability with versions)

These two methods do not have the same result overall.
Responds to Selector
The first case respondsToSelector is a part of the NSObject protocol and will simply indicate if an object is capable of responding to a message with the given signature, at the time of calling. It can be used for a number of cases:
Polymorphism. Ie, informal protocols, or particularly in conjunction with conformsToProtocol for checking if an instance (of any class) responds to the part of a protocol under the #optional directive.
For deciding whether to forward a message to another target.
For instrumenting an object with additional functionality at runtime, for example putting transaction/rollback capability on a persistent model object.
In publish/subscribe type scenarios.
Get Class
The second method is a low-level member of the Objective-C runtime. It is used to simply check the kind of class an object is presenting itself as. (It will check the isa pointer). There are methods on the NSObject protocol that can do the same thing, and it would be generally recommended to use these, unless you have a specific reason to fall back to the lower level APIs. These methods are [an instance class] and [anInstance isKindOfClass].
Replace instanceof with Polymorphism
While there are a great deal of valid uses for querying an object's class, in a typical application it is often a design flaw. There's a refactoring pattern called "replace instanceof with polymorphism". By that we mean, instead of asking an object what kind of class it is, then doing something, instead specific based on that, instead create a protocol and have each of the possible classes implement the method of that protocol in their specific way. Example:
if ([foo isKindOfClass:[Holiday class]]) {
//evaluate if approved
} else if ([foo isKindOfClass:[SickLeave class]]) {
//evaluate if approved
}
Instead do . .
id<Leave> leave;
[leave approveOrDecline]

Related

Objective-C dynamic implementation

Description + sample + explanation: (You can skip to the question section)
I'd like to make an object instance, which can be implemented by different implementations, depend on a condition (the internet status).
Simple declaration
#interface LoginController : NSObject
/** The currently logged-in User. Nil if not logged-in yet. */
#property (strong, nonatomic) User *currentUser;
// Singleton object
+ (instancetype)shareInstance;
/** Abstract methods, will do nothing if call directly. Use inheritance implements (Online/Offline) instead. */
- (User *)loginByEmail:(NSString *)email password:(NSString *)pwd;
#end
#interface LoginControllerOnline : LoginController
// Login will call request to server.
#end
#interface LoginControllerOffline : LoginController
// Login will check data in coredata.
#end
The LoginController's login method actually do nothing (return nil). Instead, the inherited class (Online/Offline) overwrite the parent login's method, with different implementations (as in comments)
And then, I have a manager to define which class should be in use:
#implement InternetManager
+ (LoginController *)loginController
{
return [self hasInternet] ? [LoginControllerOnline shareInstance] : [LoginControllerOffline shareInstance];
}
+ (BOOL)hasInternet
{
// Check with Reachability.
}
#end
This work. But it's not the mechanism I'd like to achieve.
This mean I have 2 instances of inherited LoginController instead of 1.
When internetStatus change from offline to online, I'd like to re-login online (to get session/oauthToken...). But, I'll have to do many things (copy user, change instance, check retained...) before I can actually call from login online
QUESTION:
Is there a way for me to create only one instance of LoginController, which hold the same properties (User), but can has different (dynamic) implementations (Online/Offline)?
Update question:
Quote from Apple's Dynamic typing:
The isa Pointer:
Every object has an isa instance variable that
identifies the object's class. The runtime uses this pointer to
determine the actual class of the object when it needs to.
So, is there a way for me to change this isa pointer of an object instance?
It sounds like the real problem is that you've given these things direct primary ownership of state that you actually don't want them to own — factor it out. There's no copying, just give each an instance of the thing that marshals sate at -init and allow them to talk to it.
Then just do the normal programming thing when you want to do either one thing or another based on a condition: use an if statement.
So, I don't think use of the dynamic runtime is appropriate. However, academically, supposing an interest:
If you really must, use object_setClass, which "[s]ets the class of an object", answering your actual question. Obviously you need the storage to be compatible, so probably your subclasses shouldn't declare any properties or instance variables.
A commonly-discussed alternative for this general area is not changing the class of an existing instance but changing the methods that are a member of the class. So you'd have two alternative implementations of -loginByEmail:password: and set which was the one that actually responded to that selector dynamically. But there's really no advantage over just using an if if you have access to the source code and a bunch of disadvantages around its generally indirect, opaque nature. The whole thing is usually known as swizzling. class_replaceMethod is the key component but just search for swizzling.

iOS / Objective-C: Correct Way of Obtaining Meta Class Object

Which from the following is the correct way of obtaining the meta class?
Class myMetaClass = objc_getMetaClass("NSString");
Or:
Class myMetaClass = object_getClass([NSString class]);
Are they both any different?
As mentioned in another post that is linked by the first answerer here:
Please tell me why objc_getMetaClass(); would break in certain cases in detail.
The proper way to use those in different scenarios.
Both functions are correct, but objc_getMetaClass("NSString") only works if NSString is registered with the objective C runtime. Which it almost always is if you want to get its metaclass.
But if you're creating a class using Class myClass = objc_allocateClassPair(superClass,"my_own_class",0) the situation is slightly different.
my_own_class isn't registered yet, so if you need to access the metaclass (in order to add class methods), you must use object_getClass(myClass).
objc_getMetaClass("my_own_class") would return nil.
The difference is, that the second function returns the object for the named class and the second first the object for the metaclass of the named class... :)
Both of them call the class handler callback if the class is not registered to check a second time. When you call the metaclass function you WILL get a return result.
...(However, every class definition must have a valid metaclass
definition, and so the metaclass definition is always returned,
whether it’s valid or not.)
from: Objective-C Runtime Reference
I think your real question is: What is the difference between a class and a metaclass ?
Please have a look at this excellent explanation:
What is meta-class in objective-c

what does do method class in objective c

This might be a silly question. I'm learning objective C (iOS) by studying the code and I came across the expression
[InstanceName class];
What does it do?
I tried to search for class method but It just pops up difference between class method and instance method etc. I guess it might give some sort of class object but I have no idea what is the purpose of the statement.
the original code is Sample Facebook App (scrumptious) using FB SDK....
If you see something like this as a standalone expression....
[InstanceName class];
... then the code is most likely forcing the execution of the +initialize method on said class. The first time any method is invoked on a class, the +initialize method will be invoked prior by the runtime. So, have a look at InstanceName and see if it has a +initialize method.
Note that forcing +initialize to execute in this fashion is a sure sign of bad design. +initialize should never need to be forced like this and should not have execution order dependencies.
There is a legitimate additional reason why this line of code might exist. By referring to InstanceName with a hard reference, it'll force the linker to link in all symbols in the library. (If you don't have a hard reference to at least one symbol in a library -- a .a -- some linkers will simply drop the library from the link unit entirely.)
It gets the class of the object.
So for instance if InstanceName is an instance of class Foo
[InstanceName class]; will return Foo, in a variable of type Class
You can use class_getClassName to get an NSString from this class to log it.
class is a method inherited from NSObject. It lets you get the instance of the class object representing the class of the instance on which the method is called.
It can be used to examine the metadata of the current object. For example, you can use class method to determine if a given object is of a particular class:
if ([sender isKindOfClass:[UIButton class]]) {
...
}
It returns the class of the object. Suppose you have an array of UIView subclasses you created and you want to perform some action only to those who belong to a certain class. You could loop through the array and check for each object's class:
for (id view in myViews) {
if ([view isKindOfClass:[MyUIViewSubclass class]]) {
// Do something
}
}

resolveInstanceMethod on super returns NO for a valid selector

I've implemented +resolveInstanceMethod on a class that subclasses NSDictionary. I will dynamically add methods to my class for certain cases, but I want standard NSDictionary methods to 'just work'.
I thought this would be the case if I just call [super resolveInstanceMethod:sel]; at the end of my method but it doesn't work.
+ (BOOL) resolveInstanceMethod:(SEL)sel
{
BOOL value = [super resolveInstanceMethod:sel]; // this is always NO!?
return value;
}
Why is this? How do I get my class to behave 'normally' for existing methods on the superclass?
What leads you to expect that -resolveInstanceMethod: would return YES for already existing methods? The release notes which introduced the new method say that the default implementation simply returns NO:
The NSObject class implements these methods with a default
implementation that returns NO today, though you should still invoke
it even if you're just directly subclassing NSObject.
In any case, it should never even be called for methods which are already present on the class. It's only called when you message an object with a selector which isn't already "resolved" to an implementation.

Get Which iOS Frameworks are Available?

I'm writing a static library for iOS. I want to programmatically figure out if CoreLocation is added to the project, is there any way to do that?
Probably something like:
if(NSClassFromString(#"CLLocationManager"))
{
NSLog(#"CoreLocation is available");
}
Would do it. NSClassFromString takes an NSString and checks whether there's a class of that name currently available in the runtime. If so then it returns the Class object, otherwise it returns nil. The if statement there effectively compares to nil.
So, the logic you're applying is "does a class called CLLocationManager currently exist?", which is a proxy for checking that CoreLocation is loaded because it's one of the fundamental classes to that framework.

Resources