zoukankan      html  css  js  c++  java
  • iOS笔记056

    九宫格布局

    UICollectionViewController

    创建控制器一定要指定默认的布局样式。

    // 加载一个九宫格布局的控制器,必须指定布局样式

    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];

    vc = [[SLQGuideCollectionController alloc] initWithCollectionViewLayout:layout];

    也可以重写控制器的init方法

    - (instancetype)init

    {

        UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];

        // 初始化必须指定默认的布局样式

        return [super initWithCollectionViewLayout:layout];

    }

    在指定布局时可以设置各种属性

    - (instancetype)init

    {

        UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];

        // cell大小

        layout.itemSize = SLQScreenBounds.size;

        // 水平间距

    //    layout.minimumInteritemSpacing = 0;

        // 垂直间距

        layout.minimumLineSpacing = 0;

        // 每一组距离四面的距离

    //    layout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0);

        // 滚动方向

        layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;

        

        // 初始化必须指定默认的布局样式

        return [super initWithCollectionViewLayout:layout];

    }

    如果想显示控件,那么使用方法和UITableView非常相似。使用代理设置每个CollectionView

    // 一共多少组

    - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView

    {

        return 1;

        

    }

    // 某组多少元素

    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section

    {

        return  4;

    }

    // cell 的内容

    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

    {

        // 只能以这种方式创建cell,首先注册xib或者类,然后去缓存池中取,如果缓存池没有就自己创建一个新的cell

        SLQGuideCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:IDforIndexPath:indexPath];

        // 设置cell内容

        NSString *imageName = [NSString stringWithFormat:@"guide%ldBackground",indexPath.item + 1];

        cell.image = [UIImage imageNamed:imageName];

        return cell;

    }

     运行时 - runtime

    首先包含头文件,然后使用里面的方法即可

    // 运行时对象

    #import <objc/runtime.h>

     

        // 遍历某个类里面所有属性 Ivar:表示成员属性

        // copyIvarList只能获取哪个类下面的属性,并不会越界(不会把它的父类的属性给遍历出来)

        // Class 获取哪个类的成员属性

        // count:告诉你当前类里面成员属性的总数

        //    unsigned int count = 0;

        //    // 返回成员属性的数组

        //

        int count = 0;

        Ivar *name =   class_copyIvarList([UIGestureRecognizer class], &count);

        for (int i = 0; i < count; i ++) {

            Ivar ivar = name[i];

            // 获取属性名

            NSString *proName = @(ivar_getName(ivar));

             NSLog(@"%@",proName);

        }

     

    //<UIScreenEdgePanGestureRecognizer: 0x7fb6ba46f1c0; state = Possible; delaysTouchesBegan = YES; view = <UILayoutContainerView 0x7fb6ba7481b0>; target= <(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7fb6ba46d8e0>)>>

    //UIScreenEdgePanGestureRecognizer:手势类型

    //target - _UINavigationInteractiveTransition

    //action - handleNavigationTransition

    可以看到系统默认在滑动手势时作的一些事情,指定了手势的target和action,可以利用这些方法来自定义自己的手势。

    自定义系统默认生成的手势

    1、首先要找到这个手势相关联的属性和方法。因为是私有的,不能直接看到,所以只能通过运行时机制获取属性名

    先通过运行时机制的一些函数,观察属性名,然后确定在自己要得。

    int count = 0;

    Ivar *name =   class_copyIvarList([UIGestureRecognizer class], &count);

    for (int i = 0; i < count; i ++) {

        Ivar ivar = name[i];

        // 获取属性名

        NSString *proName = @(ivar_getName(ivar));

         NSLog(@"%@",proName);

    }

    屏幕快照 2015 07 03 15 47 58

    2、找出属性名并添加手势

    // 找到属性名

    NSArray *arr = [self.interactivePopGestureRecognizer valueForKey:@“_targets"];

    // 获取属性

    id objc = [arr firstObject]; //  -(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7f7f93f5adf0>)

    // 获取方法target

    id target = [objc valueForKey:@"_target"]; //

    // 添加自定义手势,指定方法位系统内部私有的方法handleNavigationTransition:

    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self.interactivePopGestureRecognizer.delegate action:@selector(handleNavigationTransition:)];

    pan.delegate = self;

    [self.view addGestureRecognizer:pan];

    3、实现代理方法-只要不是根控制器就使用手势

    // UIGestureRecognizerDelegate 代理方法

    // 是否开始手势,如果是不是根控制器就开始手势

    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer

    {

          // 判断下当前控制器是否是跟控制器

        return (self.topViewController != [self.viewControllersfirstObject]);

    }

     

    高斯模糊实现

    这个方法是别人封装好的,直接拿来使用即可。

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    {

        if (indexPath.section == 2 && indexPath.row == 0) {

             // 弹出窗口,指定frame

            SLQSettingBlurView *blur = [[SLQSettingBlurView alloc] initWithFrame:SLQScreenBounds];

            [SLQKeyWindow addSubview:blur];

            // 弹出提示窗口

            [MBProgressHUD showSuccess:@"没有最新版本"];

            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

                // 隐藏高斯窗口

                [blur removeFromSuperview];

            });

        }

    }

     

     block 循环利用

        // block会把代码里所有强指针全部强引用

        // 解决循环利用的问题

        

        //    __weak XMGScoreViewController *weakSelf = self;

        

        // typeof获取括号里面的类型

        __weak typeof(self) weakSelf = self;

        

        // iOS7之后只要在cell上添加textField都自动做了键盘处理

        item.itemUpdate = ^(NSIndexPath *indexPath)

        {

            

            // 获取当前选中的cell

            UITableViewCell *cell = [weakSelf.tableView cellForRowAtIndexPath:indexPath];

            

            // 弹出键盘

            UITextField *textField = [[UITextField alloc] init];

            

            [textField becomeFirstResponder];

            

            [cell addSubview:textField];

            

        };

        

     json文件

    文件中保存的时字典数据

    [

      {

        "title" : "如何领奖?",

        "html" : "help.html",

        "id" : "howtoprize"

      },

      {

        "title" : "如何充值?",

        "html" : "help.html",

        "id" : "howtorecharge"

      },

    ]

     直接当做普通文件读取就行

    - (NSMutableArray *)items

    {

        if (_items == nil) {

            _items = [NSMutableArray array];

            NSString *fullPath = [[NSBundle mainBundle] pathForResource:@"help.json" ofType:nil];

     

            NSData *data = [NSData dataWithContentsOfFile:fullPath];

            // 从文件读取数据

            NSDictionary *allData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];

            for (NSDictionary *dict in allData) {

                SLQHtmlItem *item = [SLQHtmlItem itemWithDict:dict];

                [_items addObject:item];

            }

    //        NSLog(@"%@",allData);

            

        }

    //    NSLog(@"%@",_items);

        return _items;

    }

     关键一句话是使用 NSJSONSerialization 对文件进行解析

      NSDictionary *allData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];

    文件中读取的关键字和系统保留字有冲突

    那么读取时就要进行修正,使用KVC进行字典读取要保证,模型中得属性和字典中元素数量和名称一致,不能有任何差别。

    现在的问题就是,文件中又一项数据的key是id,这个和系统的保留字id冲突,必须对id进行转换。所以声明属性是大写ID。

    @property (strong, nonatomic) NSString *ID;

     然后是初始化方法,使用 KVC进行读取

    + (instancetype)itemWithDict:(NSDictionary *)dict

    {

        SLQHtmlItem *item = [[self alloc] init];

        // KVC,会出问题,id ID无法自动转换

        [item  setValuesForKeysWithDictionary:dict];

        // 使用通用方法更加方便,抽出分类

    //    SLQHtmlItem *item  = [SLQHtmlItem objectWithDict:dict mapDict:@{@"ID":@"id"}];

        

        return item;

    }

     

    重写setvalue方法,在方法里进行转换,这个可以应对数量较少的键值对冲突,如果有十几个或者更多,使用起来就很麻烦,要写一堆if语句。

     

    // json文件中得字典key id,与系统关键字冲突,手动判断再返回正确的值

    - (void)setValue:(id)value forKey:(NSString *)key

    {

        // 判断是不是id

        if ( [key isEqualToString:@"id"]) {

            

            [self setValue:value forKey:@"ID"];

            

        }

        else

        {

            [super setValue:value forKey:key];

        }

    }

    更加方便的方法是抽出一个 分类,因对更加复杂的情况,如果有10个key和系统关键字重复,这个分类比较好使。

    // 快速进行字典转模型

    // mapDict:模型中的哪个属性名跟字典里面的key对应

    + (instancetype)objectWithDict:(NSDictionary *)dict mapDict:(NSDictionary *)mapDict

    {

        id obj = [[self alloc] init];

        // 运行时遍历模型中得属性

        unsigned int count = 0;

        Ivar *ivar = class_copyIvarList(self, &count);

        for (int i = 0 ; i < count ; i ++) {

            // 取出

            Ivar var = ivar[i];

            // 取出模型

            NSString *name = @(ivar_getName(var));

            // s输入如下,有一个_,直接去掉就可得到属性名

            // 菜皮[61496:622121] _title

            // 菜皮[61496:622121] _html

            // 菜皮[61496:622121] _ID

            // 去除下划线

            name = [name substringFromIndex:1];

            

            id value = dict[name];

            

            // 需要由外界通知内部,模型中属性名对应字典里面的哪个key

            // ID -> id

            if (value == nil) {

                //

                if(mapDict)

                {

                    // 获取真实的key

                    NSString *key = mapDict[name];

                    value = dict[key];

                }

            }

            [obj setValue:value forKey:name];

            

    //        NSLog(@"%@",name);

        }

        return obj;

    }

     

    使用方法,要初入一个冲突的字典

    SLQHtmlItem *item  = [SLQHtmlItem objectWithDict:dict mapDict:@{@"ID":@"id"}];

     

  • 相关阅读:
    saltstack笔记
    saltstack学习篇
    tomcat学习篇
    memcache笔记
    sed、awk学习篇
    javascript function call
    jvm性能调优工具
    spring boot 单元测试
    activemq 分布式事务
    sringboot 集成dobbo2.5.3
  • 原文地址:https://www.cnblogs.com/songliquan/p/4623479.html
Copyright © 2011-2022 走看看