__bridge

__bridge is often seen in development. Today we will take a look at the meaning of __bridge from the application level. We will start with a small example, creating a custom class Son and implementing a method

@implementation Son
- (void)method{
    NSLog(@"method");
}
@end
Copy the code

Does the following code work?

int main(int argc, char * argv[]) { @autoreleasepool { Class class = [Son class]; void *cf = &class; [(__bridge id)cf method]; } return 0; } Run result methodCopy the code

It works, line by line

Class class = [Son class]; + (class)class {return self; } // So class is class SonCopy the code

The C++ language is special in its use of void* because void* can refer indirectly to Pointers to any other data type, such as int*, float, or even abstract data types, and can be cast from void to Pointers to any other data type, making it sometimes dangerous to use

Void * is a generic pointer to any type. This line of code declares a pointer cf to class Son

void *cf = &class;
Copy the code

__bridge

In Cocoa applications, we can’t do without Foundation and we use Core Foundation a lot, Foundation is a wrapper around Core Foundation, and the underlying data structure is the same, We can use __bridge to convert CF and NS objects to each other without transferring ownership

NSString *str = @"abc"; CFStringRef cfstring = (__bridge CFStringRef)str; NSLog(@"1 -- %@",cfstring); NSString *s = (__bridge NSString *)cfstring; NSLog(@"2 -- %@",s); Result 1 -- ABC 2 -- ABCCopy the code

__bridge_retained

__bridge_retained or CFBridgingRetain Transfers the OC pointer to a CF pointer and transfers the ownership. The CF uses CFRelease to release the object

NSString *str = @"abc"; CFStringRef cfstring = (__bridge_retained CFStringRef)str; NSLog(@"1 -- %@",cfstring); CFRelease(cfstring); Run result 1 -- ABCCopy the code

__bridge_transfer

Opposite to __bridge_retained, the CF pointer is converted to OC and ownership is handed over

NSString *str = @"abc"; CFStringRef cfstring = (__bridge_retained CFStringRef)str; NSLog(@"1 -- %@",cfstring); NSString *s = (__bridge_transfer NSString *)cfstring; NSLog(@"2 -- %@",s); Result 1 -- ABC 2 -- ABCCopy the code

Let’s go back to the example above

[(__bridge id)cf method];
Copy the code

This line of code simply means converting a pointer to void * to id and executing method. The three lines of code in this small example are summarized as

  • 1.classforSonClass object
  • 2. Declare a generic pointercfPoint to theSonClass object
  • 3, will pointercftoidType and callSonInstance methodsmethod

Now the question is simplified to can you call an instance method of a class through a pointer to a class object?

We through the instance object to invoke the process instance method is through the instance objects isa to obtain a pointer to the class object, and then start to find out the process execution, check the method is invoked, here have bypassed the class pointer obtained through isa process, to find out the process is the same, so the back can be normal call, nice!!!!!!

careful

While these may look fancy, we should use them with caution because they involve ownership transition issues that complicate our memory management and can cause problems, such as the following code

void *p; { Son *son = [[Son alloc] init]; P p = (__bridge *)son; NSLog(@"%@",p); NSLog(@"%@",p);Copy the code

If you change __bridge to __bridge_retained, this is fine

void *p; { Son *son = [[Son alloc] init]; P = (__bridge_retained void *) p = (__bridge_retained void *)son; } // NSLog(@"%@",p) is still accessible; Result <Son: 0x281210150>Copy the code

attribute

__attribute__ is a compiler directive that can help us find more errors at compile time. The format __attribute__(parameter) is just a brief exploration of what it means, and we’ll see what it means when we see it again.

Format (Format check)

NSLog, for example

FOUNDATION_EXPORT void NSLog(NSString *format, ...) NS_NO_TAIL_CALL NS_FORMAT_FUNCTION (1, 2); #define NS_FORMAT_FUNCTION(F,A) __attribute__((format(__NSString__, F, A)))Copy the code

The format parameter for

format (archetype, string-index, first-to-check)
Copy the code
  • archetypeSpecify which style, in this caseNSString
  • string-indexSpecifies the number of arguments passed in as a format string
  • first-to-checkSpecifies the index of the first variable argument

So what we’re passing in here is a 1 and a 2 which means that the first argument to the NSLog has to be an NSString string, and the second argument starts as an optional argument

availability

__attribute__((availability(ios,introduced=2_0,deprecated=7_0,message=""__VA_ARGS__)));
Copy the code
  • iosplatform
  • introducedThe first version to appear
  • deprecatedThe version to be scrapped
  • messagePrompt information

unavailable

This method is not allowed to use

- (void) method __attribute__ ((unavailable (" immortal plate plate ")));Copy the code

nonnull

Parameter cannot be empty prompt

- (void)method1:(NSString * _Nonnull)name;
- (void)method2:(NSString *)name __attribute__((nonnull(1)));
Copy the code

constructor/ destructor

These are the constructors and destructors of c++ functions

int main(int argc, char * argv[]) { @autoreleasepool { NSLog(@"main"); } return 0; } __attribute__((constructor(1))) void methodStart1(){NSLog(@" constructor "); } __attribute__((destructor(1))) void methodEnd1(){NSLog(@" destructor 1"); } __attribute__((constructor(2))) void methodStart2(){NSLog(@" constructor "); } __attribute__((destructor(2))) void methodEnd2(){NSLog(@" destructor 2"); }Copy the code

Implement the load method in Son class

@implementation Son +(void)load{ NSLog(@"load"); } @end executes the result load constructor 1 constructor 2 main destructor 2 Destructor 1Copy the code

The constructor is executed before main, the destructor after main, and the following number indicates the execution priority,

  • The smaller the value, the higher the priority, the earlier the execution, the later the release
  • The higher the value is, the lower the priority is. The later the execution is, the earlier the release is

The load function executes earlier than the constructor

The reason: When dyld loads an image, it tells objc Runtime to load all of its classes. When dyLD loads an image, its +load is called. When dyLD loads an image, its +load is called. Dyld calls all the constructor methods on the image before calling main.

cleanup

Black magic attribute ((cleanup))

objc_runtime_name

Change the name of a class or protocol at compile time

__attribute__((objc_runtime_name("Son")))
@interface Person : NSObject
@end

NSLog(@"%@", NSStringFromClass([Person class])); // "Son"
Copy the code

Refer to the article

# bridge of iOS

# Use of void* (equivalent to id in OC)

# Use of Bridge in iOS

# iOS _attributeSummary of the usage of _