iOS-部分知识点小结

来源:互联网 发布:淘宝采集软件违法吗? 编辑:程序博客网 时间:2024/05/17 07:59

目录:
1.block的基本使用
2.ScrollView的底层实现
3.Bounds和Frame简介
4.assign和weak的区别
5.枚举中的位运算
6.Size和Center
7.通知的补充
8.通知多线程使用

block的基本使用

  • 1.block声明
    block声明:  返回值(^block变量名)(参数)#void(^block)()    --->无参无返回值
  • 2.block定义:三种方式 =^(参数){}
    // 第一种  void(^block1)() = ^{    };// 第二种  如果没有参数,参数可以隐藏,如果有参数,定义的时候必须写参数,而且必须要有参数变量名  void(^block2)(int) = ^(int = a){      };// 第三种 block返回可以省略,不管有没有返回值,都可以省略   int(^block3)() = ^int{         return 3;     };
  • 3.block类型
      // block类型: int(^)(NSString *)     int(^block4)(NSString *) = ^(NSString *name){     return 2;};
  • 4.block调用
     block1();
  • 5.block快捷方式
     inlineBlock - c Inline Block as Variable

ScrollView的底层实现

  • 思路分析:
    1.scrollView上下滚动时scrollView没有滚动,是上面的内容在滚动,通过该bounds实现滚动, 用代理方法去验证,设置代理,遵守协议,在crollViewDidScroll:(UIScrollView *)scrollView打印 NSLog(@"%@",NSStringFromCGRect(scrollView.bounds));,验证结果显示,bounds的y值一直在变化, 其实就是偏移量,向上移动时,y值增加,向下移动时,y值减少。在打印NSLog(@"%@",NSStringFromCGPoint(scrollView.contentOffset)); 进行对比,验证表明,偏移量就是从bounds中取的的。2.当我们手指网上拖时,内容往上走,y值是+,可视范围往下走。3.通过,点击UIScrollView查看底层,我们知道了scrollView要想滚动,是因为加上了两个手势,一个Pan,一个捏合手势。
  • 思路演示
       模仿系统控件 ==>怎么去用 ==> 滚动scrollView其本质是在滚动内容 ==>改bounds ==>验证  ==>手指网上拖动,bounds y++ ,内容才会往上走
  • 代码片段①

    #import "ViewController.h"@interface ViewController ()<UIScrollViewDelegate> @end@implementation ViewController - (void)viewDidLoad {    [super viewDidLoad]; //   模仿系统控件 ==>怎么去用 ==> 滚动scrollView其本质是在滚动内容 ==>改bounds ==>验证 //     ==>手指网上拖动,bounds y++ ,内容才会往上走  UIScrollView *scrollView = [[UIScrollView alloc]initWithFrame:self.view.bounds];  scrollView.contentSize = CGSizeMake(0, 1000);   //  内容在滚content  scrollView.delegate = self;  [self.view addSubview:scrollView];  UISwitch *switchView = [[UISwitch alloc]init];  [scrollView addSubview:switchView];   }  #pragma mark - UIScrollViewDelegate- (void)scrollViewDidScroll:(UIScrollView *)scrollView{  NSLog(@"%@",NSStringFromCGRect(scrollView.bounds));  NSLog(@"%@",NSStringFromCGPoint(scrollView.contentOffset));}
  • 用UIView模仿ScrollView

    #import "ViewController.h"@interface ViewController ()<UIScrollViewDelegate>@property(strong,nonatomic)UIView *scrollView;@end@implementation ViewController  - (void)viewDidLoad {    [super viewDidLoad];    UIView *scrollView = [[UIView alloc]initWithFrame:self.view.bounds];    [self.view addSubview:scrollView];    _scrollView = scrollView;    //  要想移动--添加手势    //  1.添加Pan手势    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];    [scrollView addGestureRecognizer:pan];    UISwitch *switchView = [[UISwitch alloc]init];    [scrollView addSubview:switchView];}//  pan手势- (void)pan:(UIPanGestureRecognizer *)pan{    /*  每次拖动的时候,都会改动bounds,但是我们应该指导你拖      动了多少     当往上拖时, NSLog(@"%@",NSStringFromCGPoint(transP));,经过打印     y是负的,按照正常来说y,网上拖应该是正的。这时候我们就要取反。继而     bounds.origin.y -= transP.y;但是每次减transP.y,也会出现问题,使scrollView会     滚的很远。所以要做个复位。     */     //   1. 获取手指的偏移量是多少---参数:手指在哪个View上的点        CGPoint transP =  [pan translationInView:pan.view];       NSLog(@"%@",NSStringFromCGPoint(transP));      //  2.修改bounds       CGRect bounds = _scrollView.bounds;       bounds.origin.y -= transP.y;     _scrollView.bounds = bounds;      //  3.复位    [pan setTranslation:CGPointZero inView:pan.view];}

Bounds和Frame简介

  • Frame:以父控件左上角为原点
  • Bounds:以自己的左上角为原点,boundsx,y永远为0,这个是错误的
    1.当我们修改某控件bounds的x,y坐标时,对于自己的位置是不会发生变化的。但是对,自己内部的子控件,还是有影响的。 (说明了bounds的x,y是可以加减的,并不是永远都为0。x,y坐标的改变,只针对于自己的子控件。)
  • frame和bounds都是用来描述一块区域
    frame:描述的可视范围bounds:可视范围,在内容的区域。
    所有的子控件都是相对于内容的。
    bounds:本质是修改了内容的原点。
    相对性:
      可视范围相对于父控件的位置永远不变  可视范围相对于内容,位置改变

assign和weak的区别

  • 解释weak,assgin什莫时候使用weak和assgin
      weak:  (__weak修饰)弱指针,不会让引用计数器+1,如果指向的对象被销毁,指针会自动清空。  ARC:   才有weak,这个东西。  MRC:    没有weak  assgin:(_unsafe_unretained修饰),不会让引用计数器+1,如果指向的对象被销毁,指针不会清空。会造成僵尸对象现象。

枚举中的位运算

只要枚举中,有位运算就可以使用并运算 |

  • 为什莫?
    代码:如一个方法监听了两个事件,编辑时,和值改变时。

        //1 << n,2^n 左移      int a = 1 << 0;   // 1      int b = 1 << 1;   // 2     #①          int c = 1 << 2;   // 4      int d = 1 << 3;   // 8 - (void)viewDidLoad {      [super viewDidLoad];   [_textField addTagrget:self action:@selector(textBegin) forControlEvents: UIConrtolEventEditingDidBegin | UIControlEventEditingChanged]     [self test:a | b];         #②把位运算传进去    }     - (void)textBegin{       NSLog(@"开始编辑的时候会调用");    } - (void)test: (int)value{    //  解析:value,判断下是否包含a,b,c,d    // &解析有没有包含a,b, c,d    //   NSLog(@"%d %d %d %d",value & a,value & b,value & c,value & d};      if (value & a)NSLog(@"包含了a");      if (value & b)NSLog(@"包含了b");      if (value & c)NSLog(@"包含了c");     #③ 解析      if (value & d)NSLog(@"包含了d");   }

    打印结果


    如图:


    左移计算


    [里面去做判断===》forControlEvents]

Size和Center

  • 先设置尺寸在设置center,否则控件控件的位置会不准确
     - 用frame设置时,先设置center,后设置size,会导致控件位置不准确,跑偏 - 用bounds,没事 # 推荐:先设置size在设置center
  • 原因:(如图)
          frame是从左上角,控件向下扩展      bounds是从中心点慢慢扩大

    frame
  • 建议:
    如果size,从frame取出来,先设置size,在设置center
    如果size,是从bounds取出来,就不用考虑center和size的区别

通知的补充

  • 通知(要学习的点):

     1.如何发出通知 2.监听通知 3.通知注意点
  • 代码

                                   (方式一)- (void)viewDidLoad{    [super viewDidLoad];     //   1.发出通知     //   Name:通知名称     //   object:谁发出的通知     [[NSNotificationCenter defaultCenter] postNotificationName: @"note" object:nil];  //  匿名发送      // 2.监听通知       //    addObserver:谁监听       //    selector: 只要一监听到通知,就会调用观察者这个方法       //   Name:通知名称       //   object:谁发出的通知      [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reciveNote) name:@"note" object:nil]; }     - (void)reciveNote{    NSLog(@"接受到通知");}   //  一个对象即将销毁的时候就会调用   - (void)dealloc{      //   3.移除通知       [[NSNotificationCenter defaultCenter] removeObserver:self];   }                               方式二       //  监听通知       /**          Name:通知名称          object:谁发出的通知          queue:队列          usingBlock:只要监听到通知,就会调用block         */         @property(nonatomic ,weak) id observe;      id observe =  [[NSNotificationCenter defaultCenter] addObserverForName:@"note"  object:nil          queue:nil   usingBlock:^(NSNotification * _Nonull note){           //  只要监听到通知,就会调用block           NSLog(@"%@",[NSThread currentThread]);           NSLog(@"%@",self);         ]};     系统观察,怎么去移除 - (void)dealloc{      // 3.移除通知       [[NSNotificationCenter defaultCenter] removeObserver:_observe];      }

上面一定监听不到通知,2要跟1调换顺序,先监听通知,发出通知。

  • 注意点
    1.通知顺序:一定要先监听,在发出
     bug:监听不到通知,马上想到有可能先发出通知,在监听通知
    2.一定要移除

通知多线程使用

  • 异步线程,不能监听到通知
  • 异步任务,执行顺序不确定
  • 下面代码验证:异步线程可以监听通知

    - (void)viewDidLoad{    [super viewDidLoad]; // 2.监听通知       //    addObserver:谁监听       //    selector: 只要一监听到通知,就会调用观察者这个方法       //   Name:通知名称       //   object:谁发出的通知 dispatch_async(dispatch_get_global_queue(0,0),^{      //  异步任务   [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reciveNote) name:@"note" object:nil]; };       }     - (void)touchesBegan:(NSSet<UITouch *>*)touches withEvent:(UIEvent *)event{     //   1.发出通知     //   Name:通知名称     //   object:谁发出的通知     [[NSNotificationCenter defaultCenter] postNotificationName: @"note" object:nil];  //  匿名发送     }      //  监听到通知就会调用      //  异步:监听通知  主线程:发出通知  接受通知代码在主线程       //  在接受通知代码中,可以加上主队列任务       // 总结:监听通知代码  由发布通知线程决定     - (void)reciveNote{    NSLog(@"接受到通知");    dispatch_sync(dispatch_get_main_queue(),^{     //  更新UI });}   //  一个对象即将销毁的时候就会调用   - (void)dealloc{      //   3.移除通知       [[NSNotificationCenter defaultCenter] removeObserver:self];   }
  • 总结:
        1. 异步:监听通知  主线程:发出通知  接受通知代码在主线程    2. 在接受通知代码中,可以加上主队列任务    3. 总结:监听通知代码  由发布通知线程决定
0 0