Preface:

There was no permission for the original work in the nuggets community before, so this article was shared through the link before, but now there is permission for the original work, so for the convenience of re-uploading the article! In the last article I believe to help a lot of small partners, so in this article I hope to help you!

1. The meaning of using weakSelf and strongSelf together in Block

We all declare a weak reference to be used in a block to prevent circular references. So what is the purpose of using weakSelf with strongSelf? First, define two macros:

#define LRWeakSelf(type)  __weak typeof(type) weak##type = type;
#define LRStrongSelf(type)  __strong typeof(type) type = weak##type;Copy the code

We create a shop and use a weak reference LRWeakSelf(shop) in the shop.myBlock;

LRShop *shop = [[LRShop alloc]init]; shop.string = @"welcome to our company"; // Weak reference LRWeakSelf(shop); shop.myBlock = ^{ NSLog(@"%@",weakshop.string); }; shop.myBlock();Copy the code

LRWeakSelf(shop); With LRStrongSelf (shop); Used together

LRShop *shop = [[LRShop alloc]init]; shop.string = @"welcome to our company"; // Weak reference LRWeakSelf(shop); Shop.myblock = ^{// Strong LRStrongSelf(shop) NSLog(@"%@",shop.string); }; shop.myBlock();Copy the code

String = shop.string = shop.string = shop.string = shop.string = shop.string = shop.string = shop.string = shop.string = shop.string = shop.string

Just use LRWeakSelf(shop); And adding a delay of 3 seconds to myBlock will cause problems in the output, even though the object is destroyed and the output value is null

// Weak reference LRWeakSelf(shop); Shop. myBlock = ^{dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"%@",weakshop.string); }); }; shop.myBlock();Copy the code

If LRWeakSelf (shop); With LRStrongSelf (shop); With the output shop.string has a value, the object is destroyed, I will not screenshots for you to see!

// Weak reference LRWeakSelf(shop); MyBlock = ^{LRStrongSelf(shop) dispatch_after(dispatch_time(DISPATCH_TIME_NOW), (int64_t) (3.0 * NSEC_PER_SEC)), dispatch_get_main_queue (), ^ {NSLog (@ "% @" shop. String); }); }; shop.myBlock();Copy the code

Through the above pile of explanations, we obviously find that LRWeakSelf(shop); With LRStrongSelf (shop); The advantage of using them together is not only to print the values I want, but also not to create circular references, so the two methods can be used as needed in development!

2. Notice problems using UIAppearance

If you are not familiar with UIAppearance, the purpose of UIAppearance is to set the global display style. If you take the macro UI_APPEARANCE_SELECTOR, you can use UIAppearance like this:

We know that UIBarButtonItem is stateful like UIControlStateNormal or UIControlStateDisabled If setting the color in UIControlStateDisabled via UIAppearance is bad, because there is some lag when using appearance, which causes the color to be bad in different states, we can just force a refresh:

/ / refresh [self. NavigationController. NavigationBar layoutIfNeeded];Copy the code

In the future, when using UIAppearance to set color, font, etc. in a certain state, you need to refresh the corresponding position with layoutIfNeeded.

3. Note how to use UITextField

How to set the color of the placeholder text in UITextField. The color of the placeholder text does not work without setting the placeholder text first:

Textfield. placeholder = @" Placeholder color can be set only after placeholder content is set "; / / placeholder text color [textField setValue: [UIColor redColor] forKeyPath: @ "_placeholderLabel. TextColor"].Copy the code

You can use a proxy to listen for changes in UITextField text:

#pragma mark - - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range ReplacementString :(NSString *)string {// here to listen for text changes return YES; }Copy the code

However, this proxy method listener has problems as shown below:

So we’re going to listen for text changes in the UITextField instead of using a proxy, we’re going to listen for text with addTarget

[textField addTarget:self action:@selector(textEditingChanged) forControlEvents:UIControlEventEditingChanged];Copy the code

4.UITextView adds placeholder text correctly

UITextView placeholder text belongs to its internal a function, we in the controller or use proxy to deal with placeholder text some functions are unreasonable, so we want to customize UITextView to the relevant internal things are encapsulated! (1) Provide placeholder text and placeholder text color to the outside world:

/** placeholder */ @property (nonatomic, copy)NSString *placeholder; */ @property (nonatomic, strong)UIColor *placeholderColor;Copy the code

(2) Set the default value of the placeholder text. If you do not set the default value, the method provided by the outside world will crash.

// Set the default font self.font = [UIFont systemFontOfSize:17]; // set the default placeholderColor self.placeholderColor = [UIColor grayColor];Copy the code

(3) Add placeholder text label internally:

/** taglabel */ @property (nonatomic, weak) UILabel * tag; Mydb - (UILabel *) tagLabel {if (_tagLabel == nil) {UILabel * tagLabel = [[UILabel alloc] init]; placeholderLabel.numberOfLines = 0; [self addSubview:placeholderLabel]; _placeholderLabel = placeholderLabel; } return _placeholderLabel; }Copy the code

(4) Display or hide placeholder text by monitoring text changes:

/ / listening text [[NSNotificationCenter defaultCenter] addObserver: self selector: @ the selector (textDidChangeNotification) name:UITextViewTextDidChangeNotification object:nil]; / / listening method - (void) textDidChangeNotification {/ / a placeholder text text is hidden self. PlaceholderLabel. Hidden = self. HasText; }Copy the code

(5) If the placeholder text is changed, the color is changed, and the font is changed, we need to rewrite the set method internally. If the textView text (not the placeholder text) is modified through the code, we also need to rewrite the set method without notification:

The wrapped custom TextView can be downloaded directly using :Demo

5. How to get the navigation controller to jump to the page in the custom control?

(1) If we had UITabBarController we would get the navigation controller like this:

UIViewController *viewC = [[UIViewController alloc]init]; UITabBarController *tabBarVc = (UITabBarController *)[UIApplication sharedApplication].keyWindow.rootViewController; //The view controller associated with The currently selected TAB item // UINavigationController *navC = (UINavigationController *)tabBarVc.selectedViewController; [navC pushViewController:viewC animated:YES];Copy the code

(2) If the controller is modal and UITabBarController does not work, we get the navigation controller like this:

UIViewController *viewC = [[UIViewController alloc]init]; / / get the final root controller UIViewController * rootC = [UIApplication sharedApplication]. KeyWindow. RootViewController; // If it was a modal controller, it would get the previous controller via presentedViewController UINavigationController *navC = (UINavigationController) *)rootC.presentedViewController; [navC pushViewController:viewC animated:YES];Copy the code

6. Modify leftBarButtonItem how to restore the system slide back function

In the development of the system leftBarButtonItem is not what we want, if we modify leftBarButtonItem then the system’s own slide back function will not work!

/ / set agent self. InteractivePopGestureRecognizer. Delegate = self; #pragma mark - // pragma mark - // NO: invalid gestures - (BOOL) gestureRecognizerShouldBegin: (gestureRecognizer UIGestureRecognizer *) {/ / when the number of navigation controller of controller is greater than 1 gestures return self.childViewControllers.count > 1; }Copy the code

7. Reacquaint Bounds

The origin of the Bounds is the upper left corner of the Bounds. The x value of the Bounds and the y value of the Bounds are 0, but the x value of the Bounds and the y value of the Bounds can be positive or negative, not necessarily 0. So what does the Bounds really mean?

  • Bounds: by oneselfcontentFor the origin of the coordinates, calculate your position and size
  • Frame: Calculates its position and size from the upper-left corner of the content of its parent class. What is content? First of all, the content is abstract. A control has not only a layer of rectangular boxes, but also many layers. This content can be abstracted into the inner layer of a control

  • Content: Something that is inside, and its child controls are also content, which means that if you modify the Buonds child controls, the position will change

Above, blue and green belong to the same control, but blue is the control itself, and green is the content of the control. We changed the x value of the control’s Bounds and y value to -20.

8. The meanings of some symbols related to enumeration

Pictured above is an apple official an enumeration, we mainly is to see < < use (it is in the C language arithmetic shift to the left), if the enumeration of as long as the < < the meaning of it is can be combined by | :

UITextField *field = [UITextField new]; / / can use UIControlEventEditingDidBegin | combination, UIControlEventValueChanged,UIControlEventEditingDidEnd [field addTarget:self action:@selector(textFieldDidChanged) forControlEvents:UIControlEventEditingDidBegin | UIControlEventValueChanged | UIControlEventEditingDidEnd]; [self.view addSubview:field];Copy the code

If enumerations can’t be combined without <<, what’s the rule? 1 << n stands for :2 to the power of n:

/ / 1 < < 16 representative: 2 of 16 power UIControlEventEditingDidBegin = 1 < < 16, / / 1 < < 17 representative: 2 of 17 photons UIControlEventEditingChanged = 1 < < 17, / / 1 < < 18 representative: 18 to the power of 2 UIControlEventEditingDidEnd = 1 < < 18, / / 1 < < 19 representative: 2 of 19 joules UIControlEventEditingDidEndOnExit = 1 < < 19,Copy the code

How did Apple know we were using multiple enumerations in combination?

NSUInteger controlEvents = UIControlEventEditingDidBegin | UIControlEventValueChanged | UIControlEventEditingDidEnd; /** // Use the ampersand symbol to determine if: UIControlEventEditingDidBegin, UIControlEventValueChanged, UIControlEventEditingDidEnd */ if (controlEvents & UIControlEventEditingDidBegin) { NSLog(@"UIControlEventEditingDidBegin"); }else if (controlEvents & UIControlEventValueChanged) { NSLog(@"UIControlEventValueChanged"); }else if (controlEvents & UIControlEventEditingDidEnd) { NSLog(@"UIControlEventEditingDidEnd"); }Copy the code

Through the above method can judge the combination of state, in the development of the << significance of the <<, if multiple conditions, any one of the conditions we can also use the enumeration with << combination to the outside world, just like Apple official add << use is the same!

9. Some questions about Xib

If the size of the view loaded by the XIB is incorrect, no matter how you set the view in the XIB, we will calculate the size of the child control by its width in layoutSubviews.

Void awakeFromNib {} - (void)layoutSubviews {[super] - (void)layoutSubviews {[super layoutSubviews]; // It is correct to get your own width here}Copy the code

So, what do we do if the view of our controller is also created by the XIB? No matter where the controller is created, it is always ok to calculate the size of the child control by simply getting the size of the controller in the viewDidLayoutSubviews method.

- (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; // Calculate the size here}Copy the code

Like a little partner please like it! If there is insufficient place, please help to correct and supplement in time, by the way talk about your proposal! Read the original