1. The difference at sign synthesize at dynamic

@property has two words,@synthsize @dynamic if you don’t have either of them, then the default is @synthsize var = _var; @synthSize if you don’t implement setter getter methods manually then automatically generate, automatically generate _var variable. @dynamic tells the compiler that setter and getter methods for properties are implemented by the user and not automatically generated. If a property is declared as @dynamic var then no errors are reported at compile time if setter getter methods are not implemented, but if instance.var = someVar,crash is used

2, NSMutableArray, NSMutableString with copy will crash

Retain, weak, assign, copy, nonatomic, atomic, nonullable, nullable

Weak is used in proxy declarations like references. Weak can automatically set the pointer to nil when the object is nil to prevent wild Pointers. Assign does not have this function. Assign is used to declare basic data types, such as int double float. Strong: Attributes modified by strong are not automatically released. In OC, objects are strong Pointers by default, and in practice open general property objects are usually decorated with strong. Retain is the same in MRC as strong in ARC. Nonullable indicates that the object should not be empty. Nullable means that an object can be NULL or nil. Copy Any object instantiated by the NSCopying protocol should use copy

4, Block weakSelf, strongSelf

Do all blocks use weak self? When the block is not a property of self, using self inside the block will not cause memory leaks. When the block is a property of self, use WeakSelf outside the block and StrongSelf inside the block. This will be released immediately after use. And when modifying a variable inside a block, remember to use the __ block modifier when declaring it outside. The memory address of the Block is displayed in the stack area. The feature of the stack area is that the object created may be destroyed at any time. Once the object is destroyed, calling the empty object again may cause the program to crash. Therefore, the Copy modifier is used when using the Block property, and blocks are copied by default in ARC mode.

5. Generics, the use of __kindof, and new iOS9 keywords

1. Nonnull: cannot be null. usage

@property (nonnull, nonatomic, copy) NSString *name; @property (nonatomic, copy) NSString *__nonnull name; @property (nonatomic, copy) NSString *_Nonnull name; // Use the following methodCopy the code

2. Nullable indicates that it can be null. usage

@property (nullable, nonatomic, copy) NSString *gender; @property (nonatomic, copy) NSString * __nullable gender; @property (nonatomic, copy) NSString * _Nullable gender; // Use the following methodCopy the code
  • It’s cumbersome to write keywords for each property, so use the following method (uiImageView.h file).
NS_ASSUME_NONNULL_BEGIN

@class UIImage;

NS_CLASS_AVAILABLE_IOS(2_0) @interface UIImageView : UIView 

- (instancetype)initWithImage:(nullable UIImage *)image;
- (instancetype)initWithImage:(nullable UIImage *)image highlightedImage:(nullable UIImage *)highlightedImage NS_AVAILABLE_IOS(3_0);

@property (nullable, nonatomic, strong) UIImage *image; // default is nil
@property (nullable, nonatomic, strong) UIImage *highlightedImage NS_AVAILABLE_IOS(3_0); // default is nil
@property (nonatomic, getter=isUserInteractionEnabled) BOOL userInteractionEnabled; // default is NO

@property (nonatomic, getter=isHighlighted) BOOL highlighted NS_AVAILABLE_IOS(3_0); // default is NO

// these allow a set of images to be animated. the array may contain multiple copies of the same

@property (nullable, nonatomic, copy) NSArray<UIImage *> *animationImages; // The array must contain UIImages. Setting hides the single image. default is nil
@property (nullable, nonatomic, copy) NSArray<UIImage *> *highlightedAnimationImages NS_AVAILABLE_IOS(3_0); // The array must contain UIImages. Setting hides the single image. default is nil

@property (nonatomic) NSTimeInterval animationDuration;         // for one cycle of images. default is number of images * 1/30th of a second (i.e. 30 fps)
@property (nonatomic) NSInteger      animationRepeatCount;      // 0 means infinite (default is 0)

// When tintColor is non-nil, any template images set on the image view will be colorized with that color.
// The tintColor is inherited through the superview hierarchy. See UIView for more information.
@property (null_resettable, nonatomic, strong) UIColor *tintColor NS_AVAILABLE_IOS(7_0);

- (void)startAnimating;
- (void)stopAnimating;
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly, getter=isAnimating) BOOL animating;
#else
- (BOOL)isAnimating;
#endif

// if YES, the UIImageView will display a focused appearance when any of its immediate or distant superviews become focused
@property (nonatomic) BOOL adjustsImageWhenAncestorFocused UIKIT_AVAILABLE_TVOS_ONLY(9_0);

// if adjustsImageWhenAncestorFocused is set, the image view may display its image in a larger frame when focused.
// this layout guide can be used to align other elements with the image view's focused frame. @property(readonly,strong) UILayoutGuide *focusedFrameGuide UIKIT_AVAILABLE_TVOS_ONLY(9_0); @end NS_ASSUME_NONNULL_ENDCopy the code
  • Note: NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END must occur in pairs. Otherwise, an error is reported. Generally used in header files. h includes the declaration and adds nonnull modifier for all attributes

Null_resettable: setters can be null, getters cannot be null.

@property (null_resettable, nonatomic, strong) UIColor *tintColor NS_AVAILABLE_IOS(7_0);
Copy the code
  • When you see a property decorated with null_resettable, you should assume that the property was initialized lazily.

4, generics

  • For example, the following array can only hold objects of type Image. And be careful how you write it.
@property (nullable, nonatomic, copy) NSArray<UIImage *> *animationImages; // The array must contain UIImages. Setting hides the single image. default is nil
@property (nullable, nonatomic, copy) NSArray<UIImage *> *highlightedAnimationImages NS_AVAILABLE_IOS(3_0); // The array must contain UIImages. Setting hides the single image. default is nil
Copy the code

In addition to using system generics, we can also use custom generics. For example,

@property( nonatomic, copy) NSArray<UserMode *> *userModelArr;
Copy the code

5. Covariance and contravariance

__covariant - A child type that can be strongly converted to a parent type (Richter's substitution principle). __contravariant - Contravariant, the parent type can be strongly converted to a child typeCopy the code

For example,

@interface NSArray<__covariant ObjectType> : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>
Copy the code

__kindof and __kindof return NSArray, but return a subclass of NSArray, NSMutableArray. The call can also use this class or a subclass of this class to receive the return value of the method.

- (nullable __kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier;  // Used by the delegate to acquire an already allocated cell, in lieu of allocating a new one.
- (__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0); // newer dequeue method guarantees a cell is returned and resized properly, assuming identifier is registered
- (nullable __kindof UITableViewHeaderFooterView *)dequeueReusableHeaderFooterViewWithIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0);  // like dequeueReusableCellWithIdentifier:, but for headers/footers
Copy the code

7, * __weak *

__weak __typeof(self)weakSelf = self;
    AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
        __strong __typeof(weakSelf)strongSelf = weakSelf;

        strongSelf.networkReachabilityStatus = status;
        if(strongSelf.networkReachabilityStatusBlock) { strongSelf.networkReachabilityStatusBlock(status); }};Copy the code

__weak itself can avoid the problem of circular reference, but it will lead to the problem that the object cannot be accessed inside the block after the external object is released. We can point to weakObj by declaring a __strong variable inside the block. This allows external objects to be held within the block without the problem of circular references.

__block itself does not avoid circular references, but we can avoid circular references by manually assigning blockObj to nil inside the block. Another point is that __block modifiers are unique inside and outside the block, so be aware of the potential pitfalls of this feature.

But __block has one thing: this is only limited to ARC environments. In non-ARC, __block avoids reference loops

__unsafe_unretained __unsafe_unretained: The same as __weak, the only difference is that the pointer is not automatically null even though the object is destroyed. In this case, the pointer points to a useless wild address. If this pointer is used, the program throws a BAD_ACCESS exception.

__bridge, __bridge_transfer, __bridge_retained * Across iOS applications, we sometimes use CF as a Core Foundation object, such as Core Graphics, Core Text, and so on. The compiler does not automatically manage the memory of the CF object in the ARC environment. Therefore, when we create a CF object, we need to use CFRelease to release it manually. Then how to manage the memory of the CF object and OC object when converting each other? __bridge,__bridge_transfer,__bridge_retained (1)__bridge:CF and OC object translation only involves the type of the object, but not the ownership of the object.

NSURL *url = [[NSURL alloc] initWithString:@"http://www.baidu.com"];
CFURLRef ref = (__bridge CFURLRef)url;
Copy the code

(2)__bridge_transfer: When CF objects are converted into OC objects, the ownership of CF objects is handed over to OC objects, at which point ARC can automatically manage the memory;

CFStringRef cfString= CFURLCreateStringByAddingPercentEscapes(
                                                                  NULL,
                                                                  (__bridge CFStringRef)text,
                                                                  NULL,
                                                                  CFSTR(! "" * '(); : @ & = + $, /? % # []"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
NSString *ocString = (__bridge_transfer CFStringRef)cfString;
Copy the code

__bridge_retained :(opposite __bridge_transfer) the ownership of the OC object is usually managed by the CF object when it is converted into a CF object. The _bridge_retained identifier means that OC should assign the ownership of the object to the CF object. Therefore, CFRelease should be used to manually release the CF object after the ref is used.

NSURL *url = [[NSURL alloc] initWithString:@"http://www.baidu.com"];
CFURLRef ref = (__bridge_retained CFURLRef)url;
CFRelease(ref);
Copy the code
6, NSTimer model enumerated value
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(repeat:) userInfo:@{@"key": @"value"} repeats:true];
Copy the code
dispatch_async(dispatch_get_global_queue(0, 0), ^{
        timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(repeat:) userInfo:@{@"key": @"value"} repeats:true];
        [[NSRunLoop currentRunLoop] run];

    });
Copy the code

In the cocoaTouch framework, only the main thread runLoop is opened by default. Other threads must be opened manually if needed, so if we want to add runloops to the main thread, There is no need to open RunLoop manually.

timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(repeat:) userInfo:@{@"key": @"value"} repeats:true];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
Copy the code

Why NSTimer stops working while scrollView is being rolled is covered in several modes of RunLoop.

Default Mode (NSDefaultRunLoopMode) The Default mode contains almost all input sources (except NSConnection). This mode should be used in general cases. Connection mode (NSConnectionReplyMode) processes events related to NSConnection objects. It is used internally by the system but not by users. Modal Mode (NSModalPanelRunLoopMode) Handles Modal panels events. Event Tracking Mode (UITrackingRunLoopMode) Is in this mode when dragging loops or other user interface tracking loops. This mode limits the processing of input events. For example, the finger is in this mode when holding down the UITableView drag. CommonMode (NSRunLoopCommonModes) This is a pseudo-mode, which is a set of Run loop Modes. Adding the input source to this mode means that it can be processed in all Modes included in CommonModes. In Cocoa applications, Common Modes by default include default Modes, Modal Modes, and Event Tracking Modes. You can add custom Modes to Common Modes using the CFRunLoopAddCommonMode method.Copy the code

The code above, including the first code, is the default mode NSDefaultRunLoopMode that was added to the Runloop after the NSTimer was created, And when we scroll the scrollView runloop will switch to UITrackingRunLoopMode, turn off the default mode, and our NSTimer unfortunately is in default mode, so of course it stops working, and our second code is also in default mode, But because you are not in the same thread as the main thread, you can continue to work. Instead of doing this as in the second code, we can also do this with NSTimer to make it work in any case:

timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(repeat:) userInfo:@{@"key": @"value"} repeats:true];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
Copy the code
7, operation and, operation or, three operations
0 ^ 1 = 1 1 ^ 1 = 0 0 ^ 0 = 0 1 ^ 0 = 1 1 ^ 0 = 1 & (true true = true, true false = false, true false = true) False false false) & 0 = 0 0 0 and 1 = 0, 1 and 0 = 0 1 & 1 = 1 * / / * the bitwise or operator (| |) 0 0 = 0, 0 | 1 = 1, | 0 = 1, 1 | 1 = 1 * /Copy the code

① Get the sum of two numbers without addition

int jw = a & b;
    int jg = a ^ b;
    while(jw)
    {
        int t_a = jg;
        int t_b = jw <<1;
        jw = t_a & t_b;
        jg = t_a ^ t_b;
    }
DebugLog(@"%d",jg);
Copy the code

② Exchange two values without using a third variable

int a = 3; int b = 5; /* a = 011 = 0 * 2^2 + 1 * 2^1 + 1 * 2^0 = 3 b = 101 = 1 * 2^2 + 0 * 2^1 + 1 * 2^0 = 5 */ a = a ^ b; //011 ^ 101 = 110 = 6 b = b ^ a; //101 ^ 110 = 011 = 3 a = a ^ b; //110 ^ 011 = 101 = 5Copy the code

Ternary operator

int max = (a > b? a : b) > c? (a > b? a:b):c; int min = (a > b? b : a) > c? c:(a > b? b:a); int mid = (a + b + c - max - min);printf("The middle value of these three numbers is :%d",mid);
Copy the code
8. Runtime principle

1. Runtime is a set of low-level PURE C LANGUAGE apis, belonging to a C language library, including many low-level C language apis. In the OC code we usually write, when the program runs, it is actually C language code converted to runtime, runtime is the OC behind the scenes. 2. RunTime refers to the mechanisms used by the system during operation, the most important of which is the message mechanism. 3. For C language, function calls will determine which function to call at compile time, and execute directly after compile, without any ambiguity. 4. The OC function call becomes message sending. Is a dynamic call procedure. It is not determined at compile time which function is actually called. (As it turns out, OC can call any function at compile time, even if the function is not implemented, as long as it is declared without error. C generates an error at compile time. 5, only in the real run time will find the corresponding function according to the name of the function to call.

  • Common role
1. Dynamically add object member variables and methods and modify attribute values and methods. 2. The realization of dynamic exchange two methods 3. The realization of classification can also add attributes 4. The realization of NSCoding automatic archiving and archiving 5. 6. Dynamically create a class (such as the underlying implementation of KVO)Copy the code

Simple use of runtime: www.jianshu.com/writer#/not…

9. KVC, KVO, NSNotificationCenter, Delegate

KVC overview

  • KVC is short for Key Value Coding. It is a mechanism by which class attributes can be accessed by the name of the string (key). Instead of calling Setter and Getter methods.

  • The key method is defined in NSKeyValueCodingProtocol

  • KVC supports class objects and built-in base data types. KVC use

  • Get valueForKey: The name of the NSString property passed in. ValueForKeyPath: path to the property, xx. Xx valueForUndefinedKey by default throws an exception and can be overridden for error handling

  • Modify the value setValue: forKey: setValue: forKeyPath: setValue: forUnderfinedKey: setNilValueForKey: nil to a class object attribute set call, an exception is thrown by default.

KVC uses ISa-Swizzing technology. Isa-swizzing is the type mixing pointer mechanism. KVC realizes its internal search and positioning through ISa-Swizzing. The ISA pointer (is kind of) points to the class that maintains the object of the subtable, which actually contains Pointers and other data to the methods in the implementation class.

KVO key-value observation key-value Observer is the Observer mode. Definition of observer pattern: A target object manages all observer objects that depend on it and actively notifies them of changes in its own state. This active notification is usually implemented by calling the interface methods provided by each observer object. The observer pattern perfectly decouples the target object from the observer object.

KVO can be used when you need to detect changes in attribute values of other classes, but you don’t want the class being observed to know about them, a bit like the FBI spying on suspects.

KVO, like KVC, relies on the dynamic mechanism of Runtime

Implementation analysis of KVO

Using the observer mode requires the cooperation of the observed, which notifies the observer of any changes in the observed state through a predefined interface (protocol). In the use of KVO, we don’t need to add extra code to the observed, so we can be notified when the observed properties change. How does this function work? Like KVC, it relies on the powerful Runtime mechanism.

The system has the following steps to achieve KVO:

  • When objects of class A are first observed, A derived class of class A is dynamically created at run time. Let’s call that B.
  • The setter methods of class A are overridden in derived class B, which implements the notification mechanism in the setter methods being overridden.
  • Class B overrides the class method, disguising itself as class A. Class B also overrides the dealloc method to free resources.
  • The system points all isa Pointers to objects of class A to objects of class B.

Like KVC, KVO is implemented by ISa-Swizzling technology. When the observer is registered as a property of an object, the isa pointer to the observed object is modified to point to an intermediate class rather than the real class. As a result, the value of the ISA pointer does not necessarily reflect the actual class of the instance.

NSNotificationCenter Notification: The notification center actually provides a mechanism for message broadcasting within a program. The notification center cannot communicate between processes. In fact, it is a setter who forwards the received message to the desired object according to an internal message forwarding. The notification center is based on the observer pattern and allows observers to be registered and deleted.

An NSNotificationCenter can have many notification messages, NSNotifications, and for each NSNotification there can be many Observer observers to receive notifications.

  • Notice Register notifications before sending them; otherwise, notifications cannot be received. Notification code is small and convenient to write, and notifications are used when you are not sure where to receive messages. Notification can be implemented one-to-many, that is, to send a notification, where necessary, as long as the notification is registered, you can perform corresponding operations.
  • Disadvantages of notifications: Too many notifications will complicate the management of notifications; if not, you will receive unintelligible messages that cannot be traced.

Delegate A’s tasks to B, declare B’s tasks in A delegate, and B follows A’s protocol to perform the tasks assigned by A. Usually one on one. It’s a little bit more efficient than notification.

  • Note that the delegate modifier uses weak to prevent cyclic references. Pointers are automatically set to nil if the object is nil to prevent wild Pointers.
10. Communication between threads
- (void)viewDidLoad {// 1. NSURL *url = [NSURL URLWithString:@"http://b.hiphotos.baidu.com/image/pic/item/e4dde71190ef76c666af095f9e16fdfaaf516741.jpg"]; / / 2. Open a thread to perform the download in the background method [self performSelectorInBackground: @ the selector (download) withObject: url]; } - (void) the download url: (NSURL *) {/ / the child thread download images NSData * data = [NSData dataWithContentsOfURL: url]; UIImage *image = [UIImage imageWithData:data]; // To set the image, execute self.imageViewsetImage: method / / [self imageView performSelectorOnMainThread: @ the selector (setImage:) withObject:image waitUntilDone:YES]; // Return to the main thread and execute the showImage: method, In this method, set the image [self performSelector:@selector(showImage:) onThread:[NSThread mainThread] withObject:imagewaitUntilDone:YES]; } -(void)showImage:(UIImage *)image {// update UI self.imageview. image = image; }Copy the code
dispatch_queue_t queue = dispatch_get_global_queue(0, 0); // 1. Dispatch_async (queue, ^{NSLog(@"% @", [NSThread currentThread]); NSURL * URL = [NSURL URLWithString:@"http://stimgcn1.s-msn.com/msnportal/ent/2015/08/04/7a59dbe7-3c18-4fae-bb56-305dab5e6951.jpg"]; / / 2. Through NSData download pictures NSData * data = [NSData dataWithContentsOfURL: url]; UIImage *image = [UIImage imageWithData:data]; Self. Imageview. image = image; // NSLog(@"UI update completed"); // Dispatch_sync (dispatch_get_main_queue(), ^{NSLog(@)); // dispatch_sync(dispatch_get_main_queue(), ^{NSLog(@))"% @", [NSThread currentThread]);
            self.imageView.image = image;
            NSLog(@"UI update completed");
        });
        NSLog(@"Other");
    });
Copy the code
// 1. Create a new queue NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue addOperationWithBlock:^{NSURL *url = [NSURL URLWithString:@"http://imgcache.mysodao.com/img2/M04/8C/74/CgAPDk9dyjvS1AanAAJPpRypnFA573_700x0x1.JPG"]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; [[NSOperationQueue mainQueue] addOperationWithBlock:^{self.imageView.image = image;}]; }]; The second method (add dependencies) / 1. Create a queue // Generally, when doing enterprise development, we define a global custom queue, NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 2. Add an operation to download the first image __block UIImage *image1 = nil; NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ NSURL *url = [NSURL URLWithString:@"http://imgcache.mysodao.com/img2/M04/8C/74/CgAPDk9dyjvS1AanAAJPpRypnFA573_700x0x1.JPG"]; NSData *data = [NSData dataWithContentsOfURL:url]; image1 = [UIImage imageWithData:data]; }]; __block UIImage *image2 = nil; NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{ NSURL *url = [NSURL URLWithString:@"http://imgcache.mysodao.com/img1/M02/EE/B5/CgAPDE-kEtqjE8CWAAg9m-Zz4qo025-22365300.JPG"];
        NSData *data = [NSData dataWithContentsOfURL:url];
        image2 = [UIImage imageWithData:data];
    }];
    // 4.添加一个操作合成图片
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        UIGraphicsBeginImageContext(CGSizeMake(200, 200));
        [image1 drawInRect:CGRectMake(0, 0, 100, 200)];
        [image2 drawInRect:CGRectMake(100, 0, 100, 200)];
        UIImage *res = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();

        // 5.回到主线程更新UI
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.imageView.image = res;
        }];
    }];

    // 6.添加依赖

    [op3 addDependency:op1];
    [op3 addDependency:op2];

    // 7.添加操作到队列中
    [queue addOperation:op1];
    [queue addOperation:op2];
    [queue addOperation:op3];
Copy the code
@try and @catch
  • Function: the developer will raise the exception code in the @try code block, the program abnormal use the @catch code block to catch; — The purpose of each code block is: @try code block stores the code that may fail, @catch code block exception handling logic, @finally code block recycling resources;

@try / @catch: A single @try block can correspond to multiple @catch blocks; — {} ellipsis problem: the curly braces of @try @catch @finally cannot be omitted;

Try and catch are rarely used in ios

To put it simply, Apple provides both error handling (NSError) and exception handling (Exception) mechanisms, but Apple encourages developers to use NSError to handle recoverable errors during program execution. Exceptions are recommended to handle unrecoverable errors.

For several reasons, exception is prone to memory management issues in non-GC situations (it is documented that it is not safe even under ARC). Exception uses blocks causing extra overhead, less efficiency, and so on.

Try {//1: the code that threw the exception //2: the code}catch(){//3: code //4: throws an exception}finally{//5: code} //6: codeCopy the code

The first thing to be clear about is that a finally block executes whether or not a try throws an exception.

The entire try,catch,finally execution has the following cases:

1: The try block does not throw an exception. If this is the case, the program executes the code after the try,finally block;

2: The try block throws an exception and the catch has a matching exception. When an exception is thrown in a try, the rest of the code in the try block is not executed and jumps to the catch block.

There are two cases here. First, if the exception thrown is caught by a subsequent catch and no new exception is thrown, the order of execution is 1356. Second, if a catch throws a new exception, order 1345, and the new exception is returned to the method caller, 6 is not executed.

3: The try block throws an exception, but the catch following it has no matching exception. The statements in try and finally, 15, are executed, and the exception is returned to the method caller without 6. If an exception cannot be caught, finally{} statements are not executed. Finally {} statements must be executed.

Sometimes we add a global breakpoint that doesn’t allow us to jump to the exception block, and we don’t allow any exception information, and we find the exception block based on the context of the exception but we don’t know what the exception is, so we can put a try catch on that exception block, Then print the contents of the exception in the catch so you can see exactly what happened. Whenever there is a bug or crash, we are used to adding NSLog or single step debugging.

Let’s look at a piece of code inside AF

if ([keyPath isEqualToString:NSStringFromSelector(@selector(state))]) {
            if ([(NSURLSessionTask *)object state] == NSURLSessionTaskStateCompleted) {
                @try {
                    [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(state))];

                    if (context == AFTaskCountOfBytesSentContext) {
                        [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesSent))];
                    }

                    if (context == AFTaskCountOfBytesReceivedContext) {
                        [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesReceived))];
                    }
                }
                @catch (NSException * __unused exception) {}
            }
        }
Copy the code

Ali Cloud inside a piece of code

@try {
            result = block(self);
        } @catch (NSException *exception) {
            tcs.exception = exception;
            return;
        }
Copy the code
Extern, const, static, extern

① The difference between const and macro

  • Const const const const const const const const const const const const const const const

    • Compile-time: macros are precompiled (processed before compilation) and const is compile-time.

    • Compile-checking: macros do not check and do not report compilation errors, just replace, const compiles check and report compilation errors.

    • Macros can define functions and methods. Const can’t.

    • Disadvantages of macros: The use of a large number of macros, easy to cause long compilation time, need to be replaced every time. ② Const limits the type

  • 1. Const only modifies variables on the right (base p, pointer *p)

  • 2. Variables decorated with const are read-only.

Int a = 1; // A = 20; Const int b = 20; const int b = 20; // b: read-only int const b = 20; // b: read-only variable // the value b = 1 is not allowed to change; Const *p = &a; // const *p = &a; // const *p = &a; int c = 10; p = &c; *p = 20; *p = 20; // const int *p1; // const int *p1; // *p1: const *p1; // *p1: const p1: const p1; // *p1: const const p1: const const p1; // *p1: const const * const p1; // *p1: constant p1: constantCopy the code

(3) the static

  • Modify local variables:
1. Extend the life cycle of local variables and destroy them at the end of the program. 2. Local variables generate only one copy of memory and are initialized only once. 3. Change the scope of local variables.Copy the code
  • Modify global variables
1. The global variable can be accessed only in this file. The global variable scope is modified. Avoid redefining global variablesCopy the code

Extern is used to get the value of a global variable (including a global static variable). It cannot be used to define a variable. ⑤ Static is used with const

static  NSString * const key = @"name";
Copy the code

Use extern with const in development scenarios: Extern and const are extern and extern constants that are often used in multiple files. Tatic combined with const: A static global variable needs to be defined in each file. Extern with const: Only one global variable is defined, and multiple files are shared.

#import #include and @class

#include <> : a reference to a system file that the compiler looks up in the system file directory.

#include “xx.h”: used to refer to user-defined files. The compiler looks first in the user directory, then in the installation directory, and finally in the system directory.

Note: #include: if CLass A imports CLass B, then CLass B’s header imports CLass A’s header, which causes A circular reference. So we try not to import our own custom.h class file in our.h file (but if we have agents in our.h file we can import another one in our.h file or we can write the agents in a separate.h file)

#import Cross-import occurs if CLass A imports CLass B and CLass B’s header imports CLass A’s header. #import is basically the same as include, but it avoids the double reference problem. So we basically use import in OC.

At sign class is usually used when you want to define a property of a certain type in a dot h header file, to prevent you from importing another dot h file in a loop, But if you use @class in dot h, make sure to #import the corresponding.h file in dot m. Note: don’t import another class’s.m file in dot m

Static inline function

Prevent disassembly and improve operation efficiency

Call between functions, is between the memory address call, when the function call will return the address of the original function execution. Function calls have time overhead, and inline functions are designed to solve this problem. A function that does not use inline modifications, the call directive appears when assembled. Calling the call instruction involves (1) pushing the address of the next instruction onto the stack (2) sending the starting address of the subroutine to the PC (so that the next instruction from the CPU goes to execute the subroutine).Copy the code

Why inline replaces macros?

Advantages compared to functions: 1) Inline functions avoid the disadvantages of ordinary functions, which must call when assembly: eliminates the function parameter pressing, reduces the overhead of the call, and improves efficiency. Therefore, the execution speed is really faster than the general function. 2) Integrate the advantages of macros, when using directly with code replacement (like macros); Advantages over macros: 1) Avoids the disadvantage of macros: the need for precompilation. Since inline functions are also functions, no precompilation is required. 2) When an inline function is called, the compiler first checks the types of its arguments to ensure that the call is correct. It then performs a series of related checks, just as it would for any real function. This eliminates its pitfalls and limitations. 3) You can use protected members and private members of your class.Copy the code

Instructions for inline functions

1. Inline functions are just requests we provide to the compiler. The compiler does not necessarily call the function inline. Inline functions cannot carry a lot of code. If the function body of an inlined function is too large, the compiler automatically discards inlining. Inline functions must be defined before they are called.Copy the code

For example, the code inside AF

static inline void af_swizzleSelector(Class theClass, SEL originalSelector, SEL swizzledSelector) {
    Method originalMethod = class_getInstanceMethod(theClass, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(theClass, swizzledSelector);
    method_exchangeImplementations(originalMethod, swizzledMethod);
}

static inline BOOL af_addMethod(Class theClass, SEL selector, Method method) {
    return class_addMethod(theClass, selector,  method_getImplementation(method),  method_getTypeEncoding(method));
}
Copy the code

YYText inside the code

static inline CGSize YYTextClipCGSize(CGSize size) {
    if (size.width > YYTextContainerMaxSize.width) size.width = YYTextContainerMaxSize.width;
    if (size.height > YYTextContainerMaxSize.height) size.height = YYTextContainerMaxSize.height;
    return size;
}

static inline UIEdgeInsets UIEdgeInsetRotateVertical(UIEdgeInsets insets) {
    UIEdgeInsets one;
    one.top = insets.left;
    one.left = insets.bottom;
    one.bottom = insets.right;
    one.right = insets.top;
    return one;
}
Copy the code