美文网首页
iOS项目笔记

iOS项目笔记

作者: 字节码 | 来源:发表于2017-01-11 05:20 被阅读140次

    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中展示九宫格布局的情况:
    比如

    屏幕快照 2017-01-12 下午6.44.17.png

    由于,此界面是由一个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

    解决方法:

    1. 在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)

        }
    

    相关文章

      网友评论

          本文标题:iOS项目笔记

          本文链接:https://www.haomeiwen.com/subject/ppykbttx.html