Clang Attributes black Magic Little Memory
Clang Attributes is a source code annotation provided by Clang, which allows developers to express certain requirements to the compiler, participate in control such as Static Analyzer, Name mangling, code Generation and so on, generally In __attribute__(xxx)
the form of code; for ease of use, some commonly used properties are also defined by COCOA macro, such as the NS_CLASS_AVAILABLE_IOS(9_0)
__attribute__(availability(...))
simple notation of this property, which is often seen in the system header file.
A description of the common properties can be seen in Nshipster's introductory article and the Twitter introductory article. This article will also introduce a few interesting "black Magic" Attribute, perhaps in some scenarios will play an unexpected effect oh ~
The following tests are subject to Xcode 7.3 (Clang 3.8)
objc_subclassing_restricted
Use this property to define one Final Class
, that is, a class that cannot be inherited, assuming that we have a Eunuch(太监)
class named, but do not want someone to inherit from it:
@interface Eunuch:nsobject @end @interface Child:eunuch//eunuch can not have a child hit @end |
Just add this property before the @interface objc_subclassing_restricted
:
__attribute__ ((objc_subclassing_restricted)) @interface Eunuch:nsobject @end @interface Child:eunuch//<---Compile Error @end |
Objc_requires_super
AKA: NS_REQUIRES_SUPER
the flag subclass needs to be called when inheriting this method super
, otherwise a compile warning is given:
@interface Father:nsobject -(void) Hailhydra __attribute__ ((objc_requires_super)); @end @implementation Father -(void) Hailhydra { NSLog (@ "Hail hydra!"); } @end @interface Son:father @end @implementation Son -(void) Hailhydra { }//<---Warning missing [super Hailhydra] @end |
Objc_boxable
The @(...)
syntax sugar in objective-c can be an object of the basic data type NSNumber
, and if you want to box a struct
type or union
type into an NSValue
object, you can use this property:
typedef struct __ATTRIBUTE__ ((objc_boxable)) { CGFloat x, y, width, height; } Xxrect; |
In this XXRect
way, you have the ability to be box:
CGRect rect1 = {1, 2, 3, 4}; Nsvalue *value1 = @ (rect1); <---Compile Error Xxrect Rect2 = {1, 2, 3, 4}; Nsvalue *value2 = @ (RECT2); √ |
Constructor/destructor
As the name implies, constructors and destructors, together with the functions of these two properties, are invoked at the time of the executable (or shared library)load and unload , which can be understood as main()
executing before and after a function call:
__attribute__ ((constructor)) static void Beforemain (void) { NSLog (@ "Beforemain"); } __attribute__ ((destructor)) static void Aftermain (void) { NSLog (@ "Aftermain"); } int main (int argc, const char * argv[]) { NSLog (@ "main"); return 0; }
Console: "Beforemain", "main", "Aftermain" |
Constructor and +load
both are called before the main function executes, but +load
earlier than constructor, because DYLD (the dynamic linker, the original starting point of the program) notifies to load all of the classes, every time a class is loaded, it's +load
called, and when it's all loaded, Dyld calls all the constructor methods in the image.
So constructor is a great time to do bad things:
- All classes have been loaded and completed
- The main function is not yet executed
- No need to be mounted in a Class like +load
FDStackView
The Fdstackviewpatchentry method is to use this time to achieve the bogus trick.
PS: If there are multiple constructor and want to control the priority, it can be written __attribute__((constructor(101)))
, the smaller the number of the priority, the higher the 1 ~ 100 for the system reservation.
Enable_if
This property can be used only on C functions, which allows static checking of parameters :
static void Printvalidage (int age) __attribute__ ((enable_if > 0 && Age < 120, "You Ya Martian?" "))) { printf ("%d", age); } |
It indicates that the function must be satisfied age > 0 && age < 120
before it is called to be allowed, and thus:
Printvalidage (26); √ Printvalidage (150); <---Compile Error Printvalidage (-1); <---Compile Error |
Cleanup
Declare to a variable, when this variable scope ends, call a specified function, reactive COCOA with this feature to achieve the Magic @onExit
, about this attribute, in the previous article has introduced, the portal.
Overloadable
For C functions, you can define several methods with the same function name but different parameters, and the compiler will automatically select the function prototype according to the parameters when called:
__attribute__ ((overloadable)) void loganything (id obj) { NSLog (@ "%@", obj); } __attribute__ ((overloadable)) void loganything (int number) { NSLog (@ "%@", @ (number)); } __attribute__ ((overloadable)) void loganything (CGRect rect) { NSLog (@ "%@", Nsstringfromcgrect (rect)); } Tests Loganything (@[@ "1", @ "2"]); Loganything (233); Loganything (CGRectMake (1, 2, 3, 4)); |
Objc_runtime_name
For @interface
or @protocol
, specify the name of the class or protocol as another at compile time:
__ATTRIBUTE__ ((Objc_runtime_name ("Sarkgay"))) @interface Sark:nsobject @end
NSLog (@ "%@", Nsstringfromclass ([Sark class])); "Sarkgay" |
All places that directly use this class name are replaced (the only thing to be aware of is that this is not the case with reflection), and the simplest and most brutal thing to do is to confuse a class name:
__ATTRIBUTE__ ((Objc_runtime_name ("40EA43D7629D01E4B8D6289A132482D0DD5DF4FA"))) @interface Secretclass:nsobject @end |
Can also start with the numbers, afraid of fear--if you write a script to each class before adding a randomly generated objc_runtime_name
, is not the most concise version of the code to complete the confusion ...
It is the only one I know of the OBJC runtime class structure has an impact on the attribute, by encoding the class name can be injected at compile time some information, is taken to the runtime, and then back out, which is equivalent to open a secret channel, the write code and run time. Brain hole, if this attribute definition macro, in annotation
the form of the completion of certain functions, such as:
@singleton Wrapped Up __attribute__ ((Objc_runtime_name (...))) Rename the class name to "Singleton_sark_sharedinstance" @singleton (Sark, sharedinstance) @interface Sark:nsobject + (instancetype) sharedinstance; @end |
At runtime, we use the runtime to __attribute__((constructor))
find this class, to solve the selector information of "sharedinstance", to replace it dynamically + alloc
, and to return a - init
+ sharedInstance
single case.
References
Http://llvm.org/releases/3.8.0/tools/clang/docs/AttributeReference.html
Http://clang-analyzer.llvm.org/annotations.html
Black Magic's Coming, don't blink.