Objective-C has a lot of dynamic features. Basically, it is also often mentioned and used with dynamic types (dynamic typing) and dynamic binding (dynamic binding) and dynamic loading (dynamic loading ).
These dynamic features are commonly used in cocoa program development. After that, OC also provides a wealth of runtime features at the underlying layer, for example, enumeration class attribute methods and obtaining method implementation. Although these lower-level running features are basically not needed in common cocoa development, in some cases, if you know these features and use them properly, you will often get twice the result with half the effort ~
Dynamic Features
1. Dynamic type
That is, the type of the object is determined at runtime. This kind of dynamic feature is very common in daily applications, simply put, it is the ID type. The ID type is a common object class, and any object can be referred to by the ID pointer. In actual use, introspection is often used to determine the actual class of the object:
id obj = someInstance; if ([obj isKindOfClass:someClass]) { someClass *classSpecifiedInstance = (someClass *)obj; // Do Something to classSpecifiedInstance which now is an instance of someClass //...}
-isMemberOfClass:
YesNSObject
To determineNSObject
Whether the object is a member of a class. Similar-isKindOfClass:
To determine whether an object is a member of a class or its subclass. These two methods are typical introspection methods. After an object is determined to be a member of a certain type, it can be forcibly converted to continue the subsequent work.
2. dynamic binding
Based on the dynamic type, the type of an instance object is determined after it is determined. The attributes of the object and the Response Message are also completely determined, which is dynamic binding. Before continuing, You need to clarify the concept of messages in objective-C. Due to the dynamic characteristics of OC, the concept of "function" is rarely mentioned in OC, traditional Functions usually package the parameter information and function implementation into the compiled source code during compilation, while the message mechanism is most often used in OC. Call an instance method to send a message to the instance pointer. After receiving the message, the instance looks for a method to respond to the message from its own implementation.
Dynamic binding: After the instance class is determined, some attributes and corresponding methods are bound to the instance. The attributes and methods mentioned here include the newly added implementations that are not implemented in the class, but are required at runtime. At the cocoa layer, we generally send-respondstoselector: Or-instancesrespondtoselector: To a nsobject object to determine whether the object can respond to a sel. Before the OC message forwarding mechanism is triggered, the + resolveclassmethod: And + resolveinstancemethod of the corresponding class will be called. In this case, the opportunity is to dynamically add new methods to the class or instance, that is, the implementation of classes can be dynamically bound. Example:
Void dynamicmethodimp (ID self, Sel _ cmd) {// implementation ....} // this method is called before OC message forwarding takes effect + (bool) resolveinstancemethod :( SEL) Asel {If (Asel ==@ selector (resolvethismethoddynamically )) {// Add a void implementation to [self class] And the SEL name is Asel. The specific implementation content is dynamicmethodimp class_addmethod ([self class], Asel, (IMP) dynamicmethodimp, "[email protected]:"); Return yes;} return [Super resolveinstancemethod: Asel];}
Of course, it can also be called wherever neededclass_addMethod
Ormethod_setImplementation
(Add implementation for the former, and replace implementation for the latter) to meet the dynamic binding requirement.
3. Dynamic Loading
It is easy to understand how to load the required resources as needed. For iOS development, it is basically adapted according to different models. The most typical example is to load the @ 2x image on the retina device, while loading the source image on some older normal screen devices. With the release of the retina iPad and the emergence of the retina Mac, this feature is expected to be used more and more.
In-depth runtime features
Basic Dynamic features are frequently used in conventional cocoa development, especially dynamic types and dynamic binding. Because cocoa programs use the Protocol-delegate design pattern extensively, most of the delegate pointer types must be IDs, in Java, this design pattern is called strategy? I am not familiar with Java, please correct it ). Objective-C also has some advanced or lower-level runtime features, which are rarely seen in General Cocoa development and are basically used to compile interfaces of OC and other languages. However, if you understand and use it properly, you can easily solve some difficult problems in cocoa development.
Most of these runtime features are caused/usr/lib/libobjc.A.dylib
This dynamic library provides many APIs for classes, instance members, member methods, and message sending, including obtaining the class instance variable list and replacing the methods in the class, it is very powerful to add variables to class members and dynamically change the implementation of methods. The complete API list and manual can be found here. Although the beginning of the document indicates that it is applicable to Mac OS X objective-C 2.0, because these are the underlying methods of OC, they are also identical for iOS development.
A simple example, for example, when developing a universal application or game, if IB is used to build a large number of custom UIS, one of the important problems facing the transition from iPhone to iPad is how to load interfaces from different nib instances. Before ios5, allUIViewController
When loading with the default Interface (init
OrinitWithNibName:bundle:
).-loadNibNamed:owner:options:
. Because we cannot get-loadNibNamed:owner:options
Therefore, it is difficult and risky to overload it. Therefore, when using the iPad version of nib, a simple method is to unify all the nib naming methods, and then use the new similar-loadNibNamed:owner:options
To replace the original method, and ensure that non-iPad devices still follow the original method.loadNibNamed:owner:options
Method. With the OC runtime features, you can easily complete this task.
The Code is as follows:+swizze
, Exchange self-implementedloadPadNibNamed:owner:options
And SystemloadNibNamed:owner:options
, After allloadNibNamed:owner:options
All messages will be sentloadPadNibNamed:owner:options
, Which is processed by your own code.
+(BOOL)swizze { Method oldMethod = class_getInstanceMethod(self, @selector(loadNibNamed:owner:options:)); if (!oldMethod) { return NO; } Method newMethod = class_getInstanceMethod(self, @selector(loadPadNibNamed:owner:options:)); if (!newMethod) { return NO; } method_exchangeImplementations(oldMethod, newMethod); return YES;}
loadPadNibNamed:owner:options
The implementation is as follows. Note thatloadPadNibNamed:owner:options
Because the exchange has been performed before, it is actually sent as the system'sloadNibNamed:owner:options
. This completes loading of different resources.
-(Nsarray *) loadpadnibnamed :( nsstring *) Name owner :( ID) Owner options :( nsdictionary *) Options {nsstring * newname = [name stringbyreplacingoccurrencesofstring: @ "@ pad" withstring: @ ""]; newname = [newname stringbyappendingformat: @ "@ pad"]; // determines whether nsfilemanager * fm = [nsfilemanager defamanager manager] exists. nsstring * filepath = [[nsbundle mainbundle] pathforresource: newname oftype: @ "nib"]; // The loadpadnibnamed: Owner: Options called here is actually the method after the switch, that is, loadnibnamed: Owner: Options: If ([FM fileexistsatpath: filepath]) {return [self loadpadnibnamed: newname owner: Owner options: Options];} else {return [self loadpadnibnamed: name owner: Owner options: Options];}
Of course, this is just a simple example, and this function can be implemented in other ways. For example, if you add a category of uiviewcontroller to reload init, this overload is dangerous because you cannot fully understand the implementation of uiviewcontroller, therefore, some existing init Code may not be overwritten due to overload, resulting in unpredictable errors. Of course, there is no problem if you reload the init of Vc in the above example (for VC, The init method will be automatically forwarded as loadnibnamed: Owner: options, therefore, the init method does not do anything more complicated, so it is no problem as long as init is used during VC initialization ). However, this overload cannot be guaranteed to be feasible for other classes. Therefore, it is a good choice to use the above runtime exchange method to implement unknown system methods ~
In-depth objective-C Dynamic Features