的使用场景

2019-09-11 16:07栏目:专项工作
TAG:

iOS函数响应型编程

参考链接(个人小结,不喜请绕行,勿喷!)

图片 11453882015855158.png

  • GitHub
  • GitBook

UITableview是iOS开发中使用最频繁的一个控件,在实际开发中,我们经常需要定制cell,让cell显示图片、文字等。由于cell包含的图片和文字是根据服务器返回的数据进行填充的,这就导致cell包含的内容的高度是不定的。四种方法计算cell的高度:1、iOS8的自动计算机制,需要autolayout(适用iOS8之后系统)2、iOS6之后系统API结合autolayout进行计算(适用于iOS6之后的系统)3、手动计算(适用于iOS6之后的系统)4、借助于第三方框架自动计算(适用于iOS6之后的系统)

runtime的文档网上多的一塌糊涂,细节原理就不讲了这里只是简单整理下,平时可能会用到的一些场景

禅与 Objective-C 编程艺术

本篇就是采用第一种方法。由于红包model里 限标的类型和限红包使用设备有可能是null,这个时候不予显示,也就是说cell的高度是动态的。

申明:大部分代码来自:文/明仔Su: 原文链接在此感谢

  • GitHub
  • GitBook
  • GitBook-En

使用AutoLayout对xib布局

正如参考链接文章所说,此方法必须使用autolayout,这里我是用的xib设置的,当然也可以使用第三方框架masonry设置。设置约束的时候必须注意每个控件在垂直方向上必须都有约束(遵循从左到右从上到下的原则),这样cell才可以计算出来高度。

图片 2cell整体布局

对cell整体布局的几点说明:

  1. 注册红包及下面的5个使用条件label 都是放在vBg这个辅助view里面的。对于label的约束,可以全部选中,上下左右设置0,不选margin,之后对注册红包label距底设置20,这样比较高效(红包的name,限额和期限还有日期是一定会有的)

  2. 人民币符号布局

    图片 3

  3. 红包金额布局

    图片 4

  4. 虚线布局

    图片 5注意:这里用的是通过设置view的背景颜色来加载相应的图片。若用imageview加载图片,会出现cell自动变得很大的问题,初步猜测是因图片本身size太大,imageview自适应导致。

//暂时用uiview的方式加载虚线图片,若用imageview,使用autolayout动态计算cell的高度时,会以imageview为准,使cell 高度变得很大 self.vXxLine.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"HorizontalCoupleLine"]];

2017/11/16补充更新若用imageview来加载虚线的话,如下设置content hugging和content compressive resistance 为低优先级即可(也就是说让虚线去适应右边总label的高度)

图片 6布局小结:观察以上布局能发现不管是从左到右还是从上到下,size都约束好了。

哪里涉及到runtime

核心代码

viewcontroller里面

//注册cell[self.mainTabelView registerNib:[UINib nibWithNibName:NSStringFromClass([RedPacketCell class]) bundle:nil] forCellReuseIdentifier:RedPacketIdentifer];//使用autolayout自动计算cell高度(must确定动态label垂直方向的约束) self.mainTabelView.estimatedRowHeight = 223; self.mainTabelView.rowHeight = UITableViewAutomaticDimension;//iOS8及以后默认值,可以不设置#pragma mark- tableview datasource/delegate- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ RedPacketCell *cell = [tableView dequeueReusableCellWithIdentifier:RedPacketIdentifer]; [cell configWithModel:self.maData[indexPath.section]]; cell.selectionStyle = UITableViewCellSeparatorStyleNone; return cell;}

RedPacketCell.m里面(注意注释,在h里面关联需要使用的控件)

- awakeFromNib { [super awakeFromNib]; self.vBottomLine.backgroundColor = RGB(235, 60, 58); self.lbAmount.textColor = RGB(235, 60, 58); self.lbYuan.textColor = RGB(235, 60, 58); //暂时用uiview的方式加载虚线图片,若用imageview,使用autolayout动态计算cell的高度时,会以imageview为准,使cell 高度变得很大 self.vXxLine.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"HorizontalCoupleLine"]]; if (iPhone5SE) { self.lbName.font = SYSTEMFONT; self.lbMonth.font = SYSTEMFONT; self.lbLimitAmount.font = SYSTEMFONT; self.lbModelType.font = SYSTEMFONT; self.lbBidType.font = SYSTEMFONT; self.lbDate.font = SYSTEMFONT; }}- configWithModel:(redGiftItemModel *)model{ if  { return; } //红包金额固定宽度,暂不考虑4位数的红包(10000的红包,也不太可能) self.lbAmount.text = model.amount; self.lbName.text = model.name; self.lbLimitAmount.text = [NSString stringWithFormat:@"• 投资满%@元使用",model.limitAmount]; self.lbDate.text = [NSString stringWithFormat:@"• %@至%@",model.startDate,model.endDate]; if (model.month.floatValue==0) { self.lbMonth.text = @"• 不限投资期限"; }else{ self.lbMonth.text = [NSString stringWithFormat:@"• 投资%@个月及以上使用",model.month]; } //标的类型限制情况(当后台返回null的时候,需要赋值空字符串,autolayout才会自动计算高度为0; 不能手动设置label高度,否则当空字符串会保留高度; 与投资期限 分条写,这样一来UI不仅文案清晰简洁,同时也适配了小屏显示) if (!model.bidType) self.lbBidType.text = @""; if ([model.bidType isEqualToString:@"NEW"]) self.lbBidType.text = @"• 限新手标使用"; if ([model.bidType isEqualToString:@"HOUSE"]) self.lbBidType.text = @"• 限房标使用"; //终端类型 if (!model.modelType) self.lbModelType.text = @""; if ([model.modelType isEqualToString:@"PC"]) self.lbModelType.text = @"• 限PC端"; if ([model.modelType isEqualToString:@"MOBILE"]) self.lbModelType.text = @"• 限手机端"; if ([model.modelType isEqualToString:@"OTHER"]) self.lbModelType.text = @"• 其它";}

1.1 OC的方法调用流程

下面以实例对象调用方法[blackDog walk]为例描述方法调用的流程:

1、编译器会把`[blackDog walk]`转化为`objc_msgSend(blackDog,SEL)`,SEL为@selector。2、Runtime会在blackDog对象所对应的Dog类的方法缓存列表里查找方法的SEL3、如果没有找到,则在Dog类的方法分发表查找方法的SEL。(类由对象isa指针指向,方法分发表即methodList)4、如果没有找到,则在其父类(设Dog类的父类为Animal类)的方法分发表里查找方法的SEL(父类由类的superClass指向)5、如果没有找到,则沿继承体系继续下去,最终到达NSObject类。6、如果在234的其中一步中找到,则定位了方法实现的入口,执行具体实现7、如果最后还是没有找到,会面临两种情况:`` 如果是使用`[blackDog walk]`的方式调用方法```` 使用`[blackDog performSelector:@selector]`的方式调用方法`
  • GitBook

效果图

公司项目,就不给git demo了,附上一张效果图。

图片 7

参考链接:

1.2 消息转发流程

1、动态方法解析接收到未知消息时(假设blackDog的walk方法尚未实现),runtime会调用+resolveInstanceMethod:或者+resolveClassMethod:2、备用接收者如果以上方法没有做处理,runtime会调用- forwardingTargetForSelector:aSelector方法。如果该方法返回了一个非nil的对象,而且该对象实现了这个方法,那么这个对象就成了消息的接收者,消息就被分发到该对象。适用情况:通常在对象内部使用,让内部的另外一个对象处理消息,在外面看起来就像是该对象处理了消息。比如:blackDog让女朋友whiteDog来接收这个消息3、完整消息转发在- forwardInvocation:(NSInvocation *)anInvocation方法中选择转发消息的对象,其中anInvocation对象封装了未知消息的所有细节,并保留调用结果发送到原始调用者。比如:blackDog将消息完整转发給主人dogOwner来处理

图片 81444814548720164.png

''你知道成员变量的本质是什么吗?"答案在这里:OS runtime实战应用:成员变量和属性

2.1 json->model

原理描述:用runtime提供的函数遍历Model自身所有属性,如果属性在json中有对应的值,则将其赋值。核心方法:在NSObject的分类中添加方法

- (instancetype)initWithDict:(NSDictionary *)dict { if (self = [self init]) { //获取类的属性及属性对应的类型 NSMutableArray * keys = [NSMutableArray array]; NSMutableArray * attributes = [NSMutableArray array]; /* * 例子 * name = value3 attribute = T@"NSString",C,N,V_value3 * name = value4 attribute = T^i,N,V_value4 */ unsigned int outCount; objc_property_t * properties = class_copyPropertyList([self class], &outCount); for (int i = 0; i < outCount; i ++) { objc_property_t property = properties[i]; //通过property_getName函数获得属性的名字 NSString * propertyName = [NSString stringWithCString:property_getName encoding:NSUTF8StringEncoding]; [keys addObject:propertyName]; //通过property_getAttributes函数可以获得属性的名字和@encode编码 NSString * propertyAttribute = [NSString stringWithCString:property_getAttributes encoding:NSUTF8StringEncoding]; [attributes addObject:propertyAttribute]; } //立即释放properties指向的内存 free(properties); //根据类型给属性赋值 for (NSString * key in keys) { if ([dict valueForKey:key] == nil) continue; [self setValue:[dict valueForKey:key] forKey:key]; } } return self;}
  • GitHub

2.2 一键序列化

原理描述:用runtime提供的函数遍历Model自身所有属性,并对属性进行encode和decode操作。核心方法:在Model的基类中重写方法:

- initWithCoder:(NSCoder *)aDecoder { if (self = [super init]) { unsigned int outCount; Ivar * ivars = class_copyIvarList([self class], &outCount); for (int i = 0; i < outCount; i ++) { Ivar ivar = ivars[i]; NSString * key = [NSString stringWithUTF8String:ivar_getName]; [self setValue:[aDecoder decodeObjectForKey:key] forKey:key]; } } return self;}- encodeWithCoder:(NSCoder *)aCoder { unsigned int outCount; Ivar * ivars = class_copyIvarList([self class], &outCount); for (int i = 0; i < outCount; i ++) { Ivar ivar = ivars[i]; NSString * key = [NSString stringWithUTF8String:ivar_getName]; [aCoder encodeObject:[self valueForKey:key] forKey:key]; }}

版权声明:本文由ag真人发布于专项工作,转载请注明出处:的使用场景