# 一些布局小知识

1. LaunchScreen 会根据设备大小设置屏幕的显示范围；LaunchImage 则根据提供的启动图片设置App的可见范围
2. UITextView 可以设置显示范围
       textView.textContainerInset = UIEdgeInsetsMake(40, 0, 0, 0);
3. UITextView 可以设置像 Word 一样文字环绕在图片四周的效果。其中用到的属性就是exclusionPaths
   // Default value : empty array  An array of UIBezierPath representing the exclusion paths inside the receiver's bounding rect.
   @property (copy, NS_NONATOMIC_IOSONLY) NSArray<UIBezierPath *> *exclusionPaths NS_AVAILABLE(10_11, 7_0);
       NSString *str = @“xxx”;//xxx为文字内容
       textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 20, self.view.frame.size.width-20,    self.view.frame.size.height-30)];
       textView.text = str;
       [self.view addSubview:textView];
       
       imageView = [[UIImageView alloc] initWithFrame:CGRectMake(140, 280, 160, 100)]; imageView.backgroundColor = [UIColor orangeColor];  
       imageView.image = [UIImage imageNamed:@"mao.jpg"];    
       [self.view addSubview:imageView];
       textView.textContainer.exclusionPaths = @[[self translatedBezierPath]];
       
       - (UIBezierPath *)translatedBezierPath{
           CGRect imageRect = [textView convertRect:imageView.frame fromView:self.view];
           UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRect:CGRectMake(imageRect.origin.x+5, imageRect.origin.y, imageRect.size.width-5, imageRect.size.height-5)];
           return bezierPath;
       }																		
   1. 引申学习 CoreText
   2. 在读很多第方库的时候，经常会看到2个关键词：“IB_DESIGNABLE”和”IBInspectable“。如果你想让你纯代码写的 View 具有可以在 StoryBoard 和 xib 文件可预览，就要在自定义的 UIView 头文件加上 IB_DESIGNABLE
   3. 如果想让你自定义的 View 的参数可以在 xib 或者 storyboard 上 Attributes inspector  栏目中被看到且可以被修改，那么你需要在每个 property 前面加上  IBInspectable
       #import <UIKit/UIKit.h>
       
       IB_DESIGNABLE
       @interface DashView : UIView
       
       @property (nonatomic, copy) void(^TimerBlock)(NSInteger);
       
       @property (nonatomic, strong) IBInspectable UIColor *color;
       
       //跃动数字刷新
       - (void)refreshJumpNOFromNO:(NSString *)startNO toNO:(NSString *)toNO andTime:(NSString *)time;
       
       @end
   

4.UITabBarController 设置图片不能过大，不然不能显示

5.设置导航控制器的 NavigationBar 的  BackgroundImage 且 使用了 UIBarMetericsDefault 会导航控制器的子控制器的 view 的高度会减小 64。只有设置为 UIBarMetricsDefault 的时候给 NavigationBar 设置背景图片才会显示。UIBarMetricsCompact 意味着导航条是透明的

    [self.navigationBar setBackgroundImage:[UIImage imageNamed:@"Report_customreport"] forBarMetrics:UIBarMetricsDefault];

1. 在 iOS 6及之前的系统上默认都是 NO，在 iOS 7及其以后都是默认为 YES。效果表现为顶部的 NavigationBar 都是有透明度的效果
       @property(nonatomic,assign,getter=isTranslucent) BOOL translucent NS_AVAILABLE_IOS(3_0) UI_APPEARANCE_SELECTOR; // Default is NO on iOS 6 and earlier. Always YES if barStyle is set to UIBarStyleBlackTranslucent
   translucent 设置为 YES ，则布局 view  从屏幕的左上角开始计算，如果设置为 NO，那么布局从 NavigationBar 的下面开始布局。
2. 总结：需要让导航控制器里面的控制器的 view 从导航栏以下开始布局，有2种方法可以实现。
   - 设置导航控制器 setTranslucent = NO
   - 给导航控制器的 NavigationBar 设置背景图片，且 BarMetrics 需要设置为  UIBarMetricsDefault
3. + (void)load  和  + (void)initialize 的使用分析
   - initialize：第一次使用这个类或者它的子类的时候调用 
   - load ：这个方法在类加载的时候调用一次。 
       //window 下有一个导航控制器，导航控制器的根控制器是 ViewController ，点击屏幕跳转到 SubViewController（继承自 ViewController）
       
       //ViewController
       + (void)initialize{
           NSLog(@"%s",__func__);
       }
       + (void)load{
           NSLog(@"%s",__func__);
       }
       
       - (void)viewDidLoad {
           [super viewDidLoad];
           self.title = @"test";
           self.view.backgroundColor = [UIColor whiteColor];
       }
       - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
           SubViewController *vc = [[SubViewController alloc] init];
           [self.navigationController pushViewController:vc animated:YES];
       }
       //SubViewController
       + (void)initialize{
           [super initialize];
           NSLog(@"%s",__func__);
       }
       
       //这个方法在类加载的时候调用一次。
       + (void)load{
           NSLog(@"%s",__func__);
       }
       
       2018-07-19 11:26:04.621740+0800 Test[14617:1049502] +[ViewController load]
       2018-07-19 11:26:04.622463+0800 Test[14617:1049502] +[SubViewController load]
       2018-07-19 11:26:04.743541+0800 Test[14617:1049502] +[ViewController initialize]
       2018-07-19 11:26:07.648425+0800 Test[14617:1049502] +[ViewController initialize]
       2018-07-19 11:26:07.648610+0800 Test[14617:1049502] +[SubViewController initialize]
       
       
   结果分析来看，类都被加载了（调用了 load 方法，其中页面显示的是 ViewController 所以它的 initialize 被调用，点击屏幕跳转到  SubViewController，所以 SubViewController 的 initialize 方法会被调用，在调用的时候调用了 super 关键字，调用父类的 initialize 方法）
4. UIAppearance appearanceWhenContainedInInstancesOfClasses  : 这个方法可以控制让自定义的导航控制器的 appearance 只修改自己需要修改的样式，不至于对于全部的导航控制器的 navigationBar 全部修改。
5. UIImage 与 UIImageRenderingMode
   在 iOS 系统中经常会用到 UIImage 来渲染一些控件，比如 UITabBar 和 UIBarButtonItem 
   在日常开发的时候我们可以为 UITabBar 设置 items 属性。其中可以指定 UITabBar 的 image 和 selectedImage。此时你可以提供2张图片，比如下面的代码
       [homeBar setImage:[UIImage imageNamed:@"Tab_home"]];
       [homeBar setSelectedImage:[UIImage imageNamed:@"Tab_home_selected"]];
   你也可以按照下面的写法
       [homeBar setImage:[UIImage imageNamed:@"Tab_home"]];
       [homeBar setSelectedImage:[UIImage imageNamed:@"Tab_home"]];
   这是因为系统会渲染。如果不为 UIImage 设置渲染模式，系统会在合适的地方根据上下文渲染，比如在这个地方的 UITabBar 就会根据上下文渲染出选中的效果。我们不必要必须设置选中的颜色。	
   当然你也可以指定 UIImage 的渲染模式。下面看看官方文档讲的 UIImage 的渲染模式
       // Create a version of this image with the specified rendering mode. By default, images have a rendering mode of UIImageRenderingModeAutomatic.
       - (UIImage *)imageWithRenderingMode:(UIImageRenderingMode)renderingMode NS_AVAILABLE_IOS(7_0);
       @property(nonatomic, readonly) UIImageRenderingMode renderingMode NS_AVAILABLE_IOS(7_0);
       
       
       
       /* Images are created with UIImageRenderingModeAutomatic by default. An image with this mode is interpreted as a template image or an original image based on the context in which it is rendered. For example, navigation bars, tab bars, toolbars, and segmented controls automatically treat their foreground images as templates, while image views and web views treat their images as originals. You can use UIImageRenderingModeAlwaysTemplate to force your image to always be rendered as a template or UIImageRenderingModeAlwaysOriginal to force your image to always be rendered as an original.
        */
       typedef NS_ENUM(NSInteger, UIImageRenderingMode) {
           UIImageRenderingModeAutomatic,          // Use the default rendering mode for the context where the image is used
           
           UIImageRenderingModeAlwaysOriginal,     // Always draw the original image, without treating it as a template
           UIImageRenderingModeAlwaysTemplate,     // Always draw the image as a template image, ignoring its color information
       } NS_ENUM_AVAILABLE_IOS(7_0);
   UIImage 的渲染模式共有3种值可以选择
   - UIImageRenderingModeAutomatic：根据所使用的环境和绘图上下文自动调整渲染模式
   - UIImageRenderingModeAlwaysOriginal：始终绘制图片原始状态，不使用 tintColor
   - UIImageRenderingModeAlwaysTemplate：始终根据tintColor绘制图片，不管图片本身的颜色状态
   
6.下面举个例子。在 UITabBarController 设置 tabBar
 
     [homeBar setImage:[UIImage imageNamed:@"Tab_home"]];
     [homeBar setSelectedImage:[UIImage imageNamed:@"Tab_home_selected"]];
     

 从 iconfont 网站上面随便选择1个彩色 icon 用来做对比实验
     
 ![iconfont小图标](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/WX20180719-135721.png)
     
     
 - 实验1
       
      [homeBar setImage:[UIImage imageNamed:@"Tab_home"]];
      [homeBar setSelectedImage:[[UIImage imageNamed:@"Tab_home_selected"] imageWithRenderingMode:UIImageRenderingModeAutomatic]];

    ![UIImageRenderingModeAutomatic模式](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/WX20180719-135617@2x.png)
     
     
- 实验2
     
     [homeBar setImage:[UIImage imageNamed:@"Tab_home"]];
     [homeBar setSelectedImage:[[UIImage imageNamed:@"Tab_home_selected"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
   
     ![UIImageRenderingModeAlwaysOriginal模式](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/WX20180719-135552@2x.png)
     
     
- 实验3
     [homeBar setImage:[UIImage imageNamed:@"Tab_home"]];
     [homeBar setSelectedImage:[[UIImage imageNamed:@"Tab_home_selected"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]];

     ![UIImageRenderingModeAlwaysTemplate模式](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/WX20180719-135552@2x.png)
  
结论：对于 UIImage 来说如果不指定渲染模式的话则默认使用**UIImageRenderingModeAutomatic**，则会根据渲染的环境和上下文进行渲染。如果指定了模式，则根据具体的模式开启渲染。**UIImageRenderingModeAlwaysOriginal：**则绘制图片的原始信息，不使用**tintColor**。**UIImageRenderingModeAlwaysTemplate：**则始终根据**tintColor**绘制图片，忽略图片本身的信息。



<hr>
![引用自网络的图片](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/4673_140117110629_1.png)