iOS-部分知识点小结

目录:
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. 总结:监听通知代码 由发布通知线程决定
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容