1.根据服务端返回的json 字符串中的 \n 让label的文字换行
UIFont *ltextFont = [UIFont systemFontOfSize:14];
NSString *str = @"活动时间:2016年12月23日--2017年1月6日\n作品要求:设计稿,形式体裁不限,作品尺寸为A4纸。将作品以图文的形式参与话题,文字注明城市与名字,自建话题无效。\n评选方式:平台用户以点赞方式投票\n活动奖励:前三名的作品除平台金币奖励外,还会获得超牛逼涂鸦书籍。";
CGSize size = [str sizeWithFont: ltextFont constrainedToSize:CGSizeMake(CGRectGetWidth([UIScreen mainScreen].bounds), MAXFLOAT)lineBreakMode:NSLineBreakByWordWrapping];
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0,200,size.width,size.height)];
label.numberOfLines = 0; // 最关键的一句
label.text = str;
label.font = ltextFont;
[self.view addSubview:label];
2.显示时间(几分钟前,几小时前,几天前)
+ (NSString *)compareCurrentTime:(NSString *)str {
NSString *timeStr = @"2016-02-22 19:27:38";
// 将时间字符串转换为NSDate
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyy-MM-dd HH:mm:ss"];
NSDate *timeDate = [dateFormatter dateFromString:timeStr];
// 获取当前时间
NSDate *currentDate = [NSDate date];
// 获取当前时间距离timeStr的时间差
NSTimeInterval timeInterVal = [currentDate timeIntervalSinceDate:timeDate];
long temp = 0;
NSString *resultStr;
if (timeInterVal / 60 < 1) {
resultStr = @"刚刚";
} else if ((temp = timeInterVal / 60) < 60) {
resultStr = [NSString stringWithFormat:@"%ld分钟前", temp];
} else if ((temp = temp / 60) < 24) {
resultStr = [NSString stringWithFormat:@"%ld小时前", temp];
} else if ((temp = temp / 24) < 30) {
resultStr = [NSString stringWithFormat:@"%ld天前", temp];
} else if ((temp = temp / 30) < 12) {
resultStr = [NSString stringWithFormat:@"%ld月前", temp];
} else {
temp = temp / 12;
resultStr = [NSString stringWithFormat:@"%ld年前", temp];
}
return resultStr;
}
3.中文斜体
经查阅资料-- iOS中不支持中文字体倾斜,只有设置倾斜角度
// 1.设置反射。倾斜15度
CGAffineTransform matrix = CGAffineTransformMake(1, 0, tanf(15 * (CGFloat)M_PI / 180), 1, 0, 0);
// 2.取得系统字符并设置反射
UIFontDescriptor *desc = [ UIFontDescriptor fontDescriptorWithName:[UIFont systemFontOfSize :18].fontName matrix:matrix];
// 3.获取字体
UIFont *font = [UIFont fontWithDescriptor:desc size:18];
self.rankingBtn.titleLabel.font = font;
// 4.设置文字的字体,可以画出来
[string. text drawInRect :dr withFont :font lineBreakMode : NSLineBreakByTruncatingTail ];
// 也可以直接设置,比如
// [self.rankingBtn setTitle:viewModel.item.ranking forState:UIControlStateNormal];
通过以上方法--绘制出斜体字。
4.iOS四种切除圆角的方法
- 通过shapeLayer设置
通过bezizerpath设置一个路径,加到目标视图的layer上。代码如下
// 创建一个view
UIView *showView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
[self.view addSubview:showView];
showView.backgroundColor = [UIColor whiteColor];
showView.alpha = 0.5;
// 贝塞尔曲线(创建一个圆)
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(100 / 2.f, 100 / 2.f)
radius:100 / 2.f
startAngle:0
endAngle:M_PI * 2
clockwise:YES];
CAShapeLayer *layer = [CAShapeLayer layer];
layer.frame = showView.bounds;
layer.path = path.CGPath;
[showView.layer addSublayer:layer];
- 通过view的layer设置
- (UIImageView *)avatarImage {
if (!_avatarImage) {
_avatarImage = [[UIImageView alloc] initWithFrame:CGRectMake(20,10, avatarDiameter, avatarDiameter)];
_avatarImage.backgroundColor = [UIColor grayColor];
_avatarImage.contentMode = UIViewContentModeScaleAspectFit;
_avatarImage.layer.cornerRadius = avatarDiameter/2.0;
_avatarImage.layer.masksToBounds = YES;
[_avatarImage setImage:[UIImage imageNamed:@"test.jpg"]];
}
return _avatarImage;
}
- 通过BezierPath设置
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
}
return self;
}
// 自定义一个类继承自UIView,使用drawRect画圆
- (void)drawRect:(CGRect)rect {
// Drawing code
CGRect bounds = self.bounds;
[[UIColor whiteColor] set];
UIRectFill(bounds);
[[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:CGRectGetWidth(bounds)/2.0] addClip];
[self.image drawInRect:bounds];
}
- 通过贴图的方式设置
贴图的方式是利用一张中间为透明圆形的图片来进行遮盖,注意:要让圆形图片所在的cell的背景颜色与贴图的背景颜色相同, 代码如下:
// 头像控件
self.headerView = [UIButton buttonWithType:UIButtonTypeCustom];
self.headerView.backgroundColor = kColorGlobalCell;
self.headerView.hidden = NO;
self.headerView.tag = NSIntegerMax;
self.headerView.clipsToBounds = YES;
[self.contentView addSubview:self.headerView];
// 镂空的圆形图片盖在头像上面,目的是让头像显示为圆形,
self.cornerImageView = [[UIImageView alloc] init];
self.cornerImageView.center = self.headerView.center;
self.cornerImageView.image = [UIImage imageNamed:@"corner_circle"];
self.cornerImageView.tag = NSIntegerMax;
[self.contentView addSubview:self.cornerImageView];
self.headerView.frame = self.viewModel.headerFrame;
self.cornerImageView.frame = CGRectMake(0, 0, CGRectGetWidth(self.viewModel.headerFrame)+5, CGRectGetHeight(self.viewModel.headerFrame)+5);
self.cornerImageView.center = self.headerView.center;
利用透明圆形的图片来进行遮盖,会引起blending,但性能仍然很高的
Blending:
在iOS的图形处理中,blending主要指的是混合像素颜色的计算。最直观的例子就是,我们把两个图层叠加在一起,如果第一个图层的透明的,则最终像素的颜色计算需要将第二个图层也考虑进来。这一过程即为Blending。
会导致blending的原因:
layer(UIView)的Alpha < 1
UIImgaeView的image含有Alpha channel(即使UIImageView的alpha是1,但只要image含透明通道,则仍会导致Blending)
为什么Blending会导致性能的损失?
原因是很直观的,如果一个图层是不透明的,则系统直接显示该图层的颜色即可。而如果图层是透明的,则会引入更多的计算,因为需要把下面的图层也包括进来,进行混合后颜色的计算。
下面是一个镂空的圆形图片
corner_circle@2x.png
5 将NSInteger类型的秒,转换为00:00:00格式
- (NSString *)coverTime:(NSInteger)secondCount {
// 时
NSString *tmphh = [NSString stringWithFormat:@"%ld",secondCount / 3600];
NSLog(@"tmphh--%@", tmphh);
if ([tmphh length] == 1){
tmphh = [NSString stringWithFormat:@"0%@",tmphh];
}
// 分
NSString *tmpmm = [NSString stringWithFormat:@"%ld",(secondCount / 60) % 60];
if ([tmpmm length] == 1) {
tmpmm = [NSString stringWithFormat:@"0%@",tmpmm];
}
// 秒
NSString *tmpss = [NSString stringWithFormat:@"%ld",secondCount % 60];
if ([tmpss length] == 1)
{
tmpss = [NSString stringWithFormat:@"0%@",tmpss];
}
// NSLog(@"%@:%@", tmphh, tmpmm);
return [NSString stringWithFormat:@"%@:%@:%@",tmphh,tmpmm,tmpss];
}
6 当需要在tableView中展示九宫格布局的情况:
比如
由于,此界面是由一个tableView构成的,现在要在原有的基础上添加添加一个子标题,点击后就是这种九宫格布局,为了在原因基础上搭建界面,最好在tableViewCell中嵌套一个collectionView,用collectionViewCell展示每一个九宫格数据,而且这样tableView直接把数据源给collectionView,方便其展示数据:
- 首先tableViewCell只需要一个即可,将collectionView添加到- tableViewCell的contenView中,
- 将collectionView的scrollEnabled设置为 NO,直接让tableView接受滚动事件,
- 最后需要计算tableViewCell的高度,其实tableViewCell的高度就是collectionView的contentSize,如果每个collectionViewCell高度相同,高度根据数据源的个数,以及需要每行展示几个来计算,
比如每行展示2个,那就是[ 行数(数据源的个数 / 2) * 每一行的高度],如果与2取余为1,也要加上一行
7 让创建出来的UILabel 上下左右有间隙
某些情况下,需要让UIlabel的上下左右有一定的间隙,有时候设置textAlignment并不能解决问题,比如文本已经设置了右对其了,但需求还是要让文本向左偏移一些,以下方法即可解决
解决方法:创建UILabel的子类使其能够让文字有上下左右的空隙,通过drawTextInRect方法实现
@implementation XYUserHomePageViewContentLabel {
UIEdgeInsets _insets;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.textColor = kColorNameTextBlack;
self.font = kFontWithSize(15);
self.textAlignment = NSTextAlignmentRight;
self.backgroundColor = [UIColor whiteColor];
// 根据情况设置UIEdgeInsets _insets属性
// 让文本向左偏移15的距离
_insets = UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 10.0f);
}
return self;
}
- (void)drawTextInRect:(CGRect)rect {
[super drawTextInRect:UIEdgeInsetsInsetRect(rect, _insets)];
}
8 自定义导航条后,侧滑手势失效问题:
8.1 第一种情况:恢复系统默认的侧滑手势
第一步:自定义一个导航栏,并重写它的 viewDidLoad方法
系统默认的手势为
interactivePopGestureRecognizer
当导航控制器响应的默认手势时,我们就重新设置手势的代理不再是系统的 UINavagtionController,而是我们自定义的这个导航控制器 , 再设置导航控制器的代理为它自己,因为一会还要监听它自己的代理方法
- (void)viewDidLoad {
[super viewDidLoad];
__weak typeof(self) weakSelf = self;
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.interactivePopGestureRecognizer.delegate = weakSelf;
self.delegate = weakSelf;
}
}
第二步 :重写导航控制器的pushViewController方法
重写 push 方法最主要的目的是让这个 pop 手势在 push 的时候变为不可用,因为可能在 push 过程中用户很快的进行了左滑动,那么就会造成 pop 栈中的混乱,导致画面卡顿,所以为了避免这个情况,我们必须要设置在 Push 过程中禁止这个手势的响应
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (self.childViewControllers.count > 0) {
[viewController setHidesBottomBarWhenPushed:YES];
// 自定义导航条左侧返回按钮
UIButton *backBarButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backBarButton setImage:[UIImage imageNamed:@"Login_backSel"].xy_originalMode forState:UIControlStateNormal];
backBarButton.contentEdgeInsets = UIEdgeInsetsMake(0, -20, 0, 0);
[backBarButton sizeToFit];
viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backBarButton];
// 如果自定义返回按钮后,
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.interactivePopGestureRecognizer.enabled = NO;
}
}
[super pushViewController:viewController animated:animated];
}
第三步 :监听导航控制器 是否显示完毕 的 代理方法
这个方法主要是监听导航栏是否显示完毕,当显示完毕的时候我们要进行一个判断,因为当控制器ViewController 数量为1的时候,用户如果进行了右滑,但问题是当前控制器数量只有一个,那个这个方法 POP 什么呢?根本就没法 POP 嘛,也会造成了 pop 栈中的混乱,导致画面一直卡顿,所以我们也要进行一个判断,判断控制器数量只有一个的时候,我们就禁止了这个手势,反之则开启
#pragma mark - UINavigationControllerDelegate
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (navigationController.childViewControllers.count == 1) {
self.interactivePopGestureRecognizer.enabled = NO;
} else {
self.interactivePopGestureRecognizer.enabled = YES;
}
}
当然,我们在自定义的导航条的左侧返回按钮时,监听返回的方法中,最好让返回按钮判断当前是 push 还是 modal显示的,根据当前情况进行 pop 和 disMiss
- (void)backBarButton {
// 判断两种情况: push 和 present
if ([self isPresent]) {
[self dismissViewControllerAnimated:YES completion:^{
}];
}else {
[[self navigationController] popViewControllerAnimated:YES];
}
}
- (BOOL)isPresent {
BOOL isPresent;
NSArray *viewcontrollers = self.viewControllers;
if (viewcontrollers.count > 1) {
if ([viewcontrollers objectAtIndex:viewcontrollers.count - 1] == self) {
isPresent = NO; //push方式
}
}
else{
isPresent = YES; // modal方式
}
return isPresent;
}
8.2 第二种情况,全屏滑动返回
自定义导航控制器
- (void)viewDidLoad {
[super viewDidLoad];
id target = self.interactivePopGestureRecognizer.delegate;
self.interactivePopGestureRecognizer.enabled = NO;
// 全屏滑动返回手势
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:target action:@selector(handleNavigationTransition:)];
[self.view addGestureRecognizer:pan];
pan.delegate = self;
self.interactivePopGestureRecognizer.enabled = NO;
}
- (void)pushViewController:(XYProfileBaseController *)viewController animated:(BOOL)animated {
if ([viewController isKindOfClass:[XYProfileBaseController class]]) {
if (viewController.isHiddenLeftButton) {
viewController.hiddenLeftButton = self.childViewControllers.count < 1;
}
if (self.childViewControllers.count) {
viewController.hidesBottomBarWhenPushed = YES;
viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:viewController action:@selector(leftBtnClick:)];
}
}
[super pushViewController:viewController animated:animated];
}
#pragma mark - <UIGestureRecognizerDelegate>
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
return self.viewControllers.count > 1;
}
9 项目中app账号与环信账号的管理 - 登录
第一种方法:只需要iOS与环信交互:用户在我们的app注册会员的时候,注册成功获得返回值,正确的返回值内去注册环信账号,而环信账号就是用户注册app的账号的uid,密码是写死的,例如
wiox8YvKZd23bbIYw
,任何用户注册时,传给环信的密码都是相同的,这样方便登录。如果环信返回给你是注册成功,此时需要在成功里创建NSUserDeafults存储你的环信账号,密码就不用存了,并且调用环信登录方法。每次登录时公司在环信的账号会返回access_token、user信息及expires_in。登录时,公司服务器也会返回一个登录信息的json,登录成功时其中就有imUser即时通讯账号,使用imUser登录环信用户账号密码即可。
如果不在AppDelegate里写登录,你的APP如果退出了,下次打开就没用了,所以必须时时刻刻登录。所以你需要在AppDelegate登录,账号就是你本地存储的账号。密码还是死的。如果正常流程来说就是:
1.注册自己APP账号-成功-注册环信账号,密码为死的-成功-登录环信账号。
2.登录自己APP账号-成功-登录环信
3.AppDelegate存储账号。
第二种方法:让iOS,服务器,环信交互:通过上面的那种方式,跟服务器唯一交互的就是密码,你需要在用户注册你自己产品的时候,密码也注册环信。注册成功,将密码post给服务器,登录的时候成功,服务器不光返回error,msg,还要加一个环信的password,这样你拿到password 可以再进行登录。当然注册的时候Phone和Password需都需要存储,方便在AppDelegate入口类登录。
1.注册自己APP账号-成功-注册环信账号,密码为注册APP的密码-成功-Post密码给服务器-成功-登录环信账号。
2.登录自己APP账号-成功-拿到服务器返回的Password,登录环信账号-成功。
3.AppDelegate存储账号和密码
// 在app启动后调用登录IM
- (void)loginImUserAccount {
// 读取用户登录后存储的登录信息
NSDictionary *loginInfo = [NSDictionary dictionaryWithContentsOfFile:kLoginInfoPath];
XYLoginInfoItem *item = [XYLoginInfoItem loginInfoItemWithDict:loginInfo];
// EMOptions设置配置信息 AppKey:注册环信的AppKey。
EMOptions *options = [EMOptions optionsWithAppkey:@"wuwo#ziwo"];
//apnsCertName:推送证书名(不需要加后缀)
options.apnsCertName = @"MeSelf_APNS_DistriBution";
// 初始化SDK
EMError *error = [[EMClient sharedClient] initializeSDKWithOptions:options];
if (!error) {
NSLog(@"初始化成功");
}
// 使用用户登录成功后,使用公司服务端返回imUser账号登录环信
error = [[EMClient sharedClient] loginWithUsername:item.iyidamUser.username password:item.imUser.password];
if (!error) {
NSLog(@"登录成功");
} else {
NSLog(@"登录失败-%@", error.errorDescription);
}
}
10 集成环信 3.2.3 相关问题
10.1 使用EaseUI 报错问题解决:
当把EaseUI拖入到项目后进行编译,后报很多错误: 比如连UIKit及NSString都找不到, 这是因为EaseUI中加入了.c文件,属于混编报错,等于把PCH中的代码都拷贝一份到.c文件中了,需要给导入到OC的文件加OBJC
解决方法:
- 在pch文件中在所有代码的头部加入
#ifdef __OBJC__
尾部加入#endif
如下:
#ifdef __OBJC__
// 中间放 之前所有的 代码
#endif```
2.环信内部集成的MBProgressHUD SDWebImage MJRefresh 与我们工程中集成的这几个第三方库发生冲突!删掉工程中自己集成的这些第三方库,或者删除环信EaseUI 里面的这些第三方库!
需要注意的是:如果删除的是环信集成的第三方库!由于环信在集成的第三方库中加了EM前缀! 记得删掉EaseUI 中使用方法的前缀,不然会报错!
[官方集成视频地址](http://www.imgeek.org/video/23)
10.2 聊天会话页面更换用户头像和昵称
![WechatIMG2.jpeg](https://img.haomeiwen.com/i2135374/9f4e0d13aa7145d0.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
经查看环信官网文档:
解决方法:在EaseMessageViewController或其子类方法中设置其数据源EaseMessageViewControllerDataSource,在以下数据源方法中 将EMMessage类型转换为符合<IMessageModel>协议的类型,设置用户信息,消息显示用户昵称和头像。
pragma mark - EaseMessageViewControllerDataSource
/*!
@method
@brief 将EMMessage类型转换为符合<IMessageModel>协议的类型
@discussion 将EMMessage类型转换为符合<IMessageModel>协议的类型,设置用户信息,消息显示用户昵称和头像
@param viewController 当前消息视图
@param EMMessage 聊天消息对象类型
@result 返回<IMessageModel>协议的类型
*/
-
(id<IMessageModel>)messageViewController:(EaseMessageViewController *)viewController
modelForMessage:(EMMessage *)message
{
//用户可以根据自己的用户体系,根据message设置用户昵称和头像
id<IMessageModel> model = nil;
model = [[EaseMessageModel alloc] initWithMessage:message];
// 根据头像所在的用户是否为发送方,设置对应的模型数据
if (model.isSender) { // 发送方
model.avatarImage = [UIImage imageNamed:@"EaseUIResource.bundle/user"];//默认头像
// 设置消息消息发送方的头像和昵称
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate ;model.avatarURLPath = [appDelegate.currentloginInfo.basePath stringByAppendingString:appDelegate.currentloginInfo.userInfo.head]; //头像网络地址 model.nickname = appDelegate.currentloginInfo.userInfo.name;//用户昵称
} else {
// 设置消息接收方的头像和昵称
model.avatarImage = [UIImage imageNamed:@"EaseUIResource.bundle/user"];//默认头像
model.avatarURLPath = self.user.headFullURL.absoluteString;//头像网络地址
model.nickname = self.user.name;//用户昵称
}return model;
}
10 集成友盟第三方登录
当第三方授权成功后,使用第三方平台获取的相关字段,再给服务器发送登录(一般需传入deviceToken、head、name、openPlatform、openPlatformId、os、osVersion、phoneModel、versionCode ),获取用户的loginInfo信息,服务器返回的code码为success为,就可以切换跟控制器了,再将loginInfo写入到本地保存,每次进入app后取出loginInfo进行判断用户是否登录,然后切换正确的跟控制器。
11 点赞、关注等接口的实现
当用户点赞时给服务器发送请求,传入相应的字段,当服务器响应成功时,根据code码判断是否点赞成功;当服务器返回的code为0时,点赞成功,此时应该修改对应的模型数据(比如把模型的isPraise修改为YES,点赞数据+1), 再调用reloadData刷新表格,在cell的模型的set方法中进行设置按钮的选中状态和按钮是否可以响应事件.
11 当界面需要按照服务端返回的前十个模型进行暂时排行榜单时,并且服务端并未返回排名
解决方法:首先给模型添加一个扩展属性ranking,用于作为榜单的id,在请求服务器数据完成时,开启子线程对数据进行处理,给前10个数据在模型中给ranking赋值,这里需要对数据源进行遍历,所以最好开启子线程处理,当处理到第10个数据时,停止遍历,并回到主线程中,刷新数据
代码如下:
/// 对模型进行处理 -- 为榜单前10个模型扩展排名属性
-
(void)processingModel:(void(^)())block {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
// 榜单数据 if (self.currentType == XYTopicTypeNewRanklist) { NSInteger i = 0; BOOL flag = YES; while (flag) { if (i>_dataList[@(self.currentType)].count-1 || _dataList[@(self.currentType)].count == 0) { flag = NO; break; } else { XYTopicViewModel *viewModel = _dataList[@(self.currentType)][i]; viewModel.item.ranking = [NSString stringWithFormat:@" NO.%ld", i+1]; if (i == 9) { flag = NO; break; } i++; } } // 要回到主线程中刷新数据源,不然会引发莫名其妙的更新榜单不显示的问题 [[NSOperationQueue mainQueue] addOperationWithBlock:^{ if (block) { block(); } }]; // 其他请求,也要回到主线程中 } else { [[NSOperationQueue mainQueue] addOperationWithBlock:^{ if (block) { block(); } }]; }
});
}
12 OC项目中怎么创建Swift文件及OC与Swift代码之间互相调用
首先在OC项目中创建一个类,Language选择为Swift,创建后会弹出一个桥接文件,点击创建即可,此时会产生一个```项目名-Bridging-Header.h```,此文件是为了swift代码中使用oc代码准备的桥接文件,如果swift想要使用oc的某个类,直接在这个桥接文件中导入oc头文件即可。
在OC需要使用到Swift类的类中导入```项目名-Swift.h```,然后就可以互相调用了,
13 Swift中获取String 字符串的长度
String结构体中没有Length的方法,但是可以通过Sting的扩展属性成员characters的count属性来获取
let title : String = "title"
let count = title.characters.count //获取String字符串的长度
print(count)
13 当导航控制器下的tableView的偏移量出现了问题时:
我设置了tableView的contentInset但是并未触发scrollViewDidScroll事件,虽然contentInset没有问题,但是导致初次进入界面时tableView的偏移量不对
self.automaticallyAdjustsScrollViewInsets = false
tableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0)
所以手动设置tableView.contentOffset
tableView.setContentOffset(CGPoint.init(x: 0, y: -64), animated: true)
14 Swift中使用Masonry布局的代码格式:
headerLine.mas_makeConstraints { (make) in
make?.left.right().equalTo()(self)?.setOffset(0)
make?.bottom.equalTo()(self)?.setOffset(-margin)
make?.height.equalTo()(44)
}
figureSpecialView.mas_makeConstraints { (make) in
make?.top.left().right().equalTo()(self)?.setOffset(0)
make?.bottom.equalTo()(self.headerLine.mas_top)?.setOffset(-margin)
}
网友评论