iOS 很实在的干货

算前言吧:
不定期更新内容enmmmmm.....

站在巨人的肩膀上面向搜索引擎开发.jpg

一、 UIView使用self.navigationController进行跳转

经常会有各种嵌套,比如 table的cell中嵌套collection,需要点击collection的cell进行跳转
此时在table的cell中,已经无法使用self.navigationController了,因为
NS_CLASS_AVAILABLE_IOS(2_z0) @interface UINavigationController : UIViewController
持有navigationController的也需要是UIViewController的对象。
这种类似的情况下,可以给UIview写一个扩展:

  • .h :
- (UIViewController*)viewController;
- (UINavigationController *)navigationController;
  • .m :
- (UIViewController*)viewController {
    for (UIView* next = [self superview]; next; next = next.superview)
    {
        UIResponder* nextResponder = [next nextResponder];
        if ([nextResponder isKindOfClass:[UIViewController class]])
        {
            return (UIViewController*)nextResponder;
        }
    }
    return nil;
}
- (UINavigationController *)navigationController{
    UIViewController *viewController = [self viewController];
    if (viewController) {
        if (viewController.navigationController) {
            return viewController.navigationController;
        }
    }
    return nil;
}
  • 使用:导入头文件,👌了。只要是UIview的儿子,都可以使用self.navigationController进行跳转了。

不华丽的分割线


二、 清除图片缓存[方式之一]

新建一个继承NSObject的类(此处以 JHCleanCaches 为栗子)

  • .h :
/// 1.计算单个文件大小
+ (float)fileSizeAtPath:(NSString *)path;

/// 2.计算文件夹大小(要利用上面的1提供的方法)
+ (float)folderSizeAtPath:(NSString *)path;

/// 3.清除缓存
+ (void)clearCache:(NSString *)path;

  • .m :
// 1.计算单个文件大小
+ (float)fileSizeAtPath:(NSString *)path {
    NSFileManager *fileManager=[NSFileManager defaultManager];
    if([fileManager fileExistsAtPath:path]){
        long long size=[fileManager attributesOfItemAtPath:path error:nil].fileSize;
        return size/1024.0/1024.0;
    }
    return 0;
}

// 2.计算文件夹大小(要利用上面的1提供的方法)
+ (float)folderSizeAtPath:(NSString *)path {
    NSFileManager *fileManager=[NSFileManager defaultManager];
    float folderSize = 0.0;
    if ([fileManager fileExistsAtPath:path]) {
        NSArray *childerFiles=[fileManager subpathsAtPath:path];
        for (NSString *fileName in childerFiles) {
            NSString *absolutePath=[path stringByAppendingPathComponent:fileName];
            folderSize += [self fileSizeAtPath:absolutePath];
        }
        // SDWebImage框架自身计算缓存的实现
        folderSize+=[[SDImageCache sharedImageCache] getSize]/1024.0/1024.0;
        return folderSize;
    }
    return 0;
}

// 3.清除缓存
+ (void)clearCache:(NSString *)path {
    NSFileManager *fileManager=[NSFileManager defaultManager];
    if ([fileManager fileExistsAtPath:path]) {
        NSArray *childerFiles=[fileManager subpathsAtPath:path];
        for (NSString *fileName in childerFiles) {
            //如有需要,加入条件,过滤掉不想删除的文件
            NSString *absolutePath=[path stringByAppendingPathComponent:fileName];
            [fileManager removeItemAtPath:absolutePath error:nil];
        }
    }
    [[SDImageCache sharedImageCache] cleanDisk];
}
  • 使用:
- (void)cleanCaches{
    // 1.计算缓存大小
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *cachesDir = [paths objectAtIndex:0];
    float size = [JHCleanCaches folderSizeAtPath:cachesDir];
    
    [self showHint:[NSString stringWithFormat:@"已清理%.2lfM缓存", size]];
    // 清理缓存
    [JHCleanCaches clearCache:cachesDir];
}

不华丽的分割线


三、 Xcode自带动态分析工具[内存泄露,通过Call Tree -- 隐藏系统方法,来查看代码哪里出了问题]

  • 1、Xcode --> Open Developer Tool --> Instruments --> Leak[快捷键-Command+I]
  • 2、对应描述


    des
  • 3、具体用法(最好使用真机进行测试)
* 自行琢磨
* 百度

不华丽的分割线


四、 安利一个图片选择器,支持多选,仿微信TZImagePickerController


不华丽的分割线


五、cell的重用机制,导致的一些遗留问题

重用机制是用来减少过大的内存使用, 但在很多时候, 我们会自定义cell,这时就会出现一些我们不愿意看到的现象

  • 原代码(出现问题):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    CourierEvaluateCell  *cell = [tableView dequeueReusableCellWithIdentifier:[CourierEvaluateCell reuseIdentifier]];
    if (!cell) {
        cell = [[CourierEvaluateCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[CourierEvaluateCell reuseIdentifier]];
        
    }
    
    if (self.dataArr.count > indexPath.row) {
        cell.model = self.dataArr[indexPath.row];
    }
    return cell;
}
  • 防止重用的代码:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//    CourierEvaluateCell  *cell = [tableView dequeueReusableCellWithIdentifier:[CourierEvaluateCell reuseIdentifier]];
     CourierEvaluateCell *cell = [tableView cellForRowAtIndexPath:indexPath];//防止重用
    if (!cell) {
        cell = [[CourierEvaluateCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[CourierEvaluateCell reuseIdentifier]];
        
    }
    
    if (self.dataArr.count > indexPath.row) {
        cell.model = self.dataArr[indexPath.row];
    }
    return cell;
}
  • CourierEvaluateCell *cell = [tableView cellForRowAtIndexPath:indexPath];根据indexPath准确地取出一行,而不是从cell重用队列中取出。

不华丽的分割线


六、View部分圆角问题的解答

  • 先看效果:


    部分圆角.gif

由于项目需求,需要实现部分圆角,开始没想那么多,直接在GitHub上找了一个SKArchCutter,圆角效果是能出来的,但是我发现我btn的背景颜色存在问题,这下就只有自己再研究下了。

  • 实现代码:
/**
 按钮的圆角设置

 @param view view类控件
 @param rectCorner UIRectCorner要切除的圆角
 @param borderColor 边框颜色
 @param borderWidth 边框宽度
 @param viewColor view类控件颜色
 */
- (void)setupRoundedCornersWithView:(UIView *)view cutCorners:(UIRectCorner)rectCorner borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth viewColor:(UIColor *)viewColor{

    CAShapeLayer *mask=[CAShapeLayer layer];
    UIBezierPath * path= [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:rectCorner cornerRadii:CGSizeMake(15,10)];
    mask.path=path.CGPath;//从贝塞尔曲线获取到形状
    mask.frame=view.bounds;


    CAShapeLayer *borderLayer=[CAShapeLayer layer];
    borderLayer.path=path.CGPath;
    borderLayer.fillColor = [UIColor clearColor].CGColor;
    borderLayer.strokeColor = borderColor.CGColor;
    borderLayer.lineWidth = borderWidth;
    borderLayer.frame = view.bounds;
    view.layer.mask = mask;
    [view.layer addSublayer:borderLayer];
    
    
}
  • 至于怎么使用,相信大家一看也就明白了,写得比较片面,有更好的方法也请指正。

不华丽的分割线


七、UITextField中文字数限制的隐藏bug~~~

今儿个发现个奇怪的bug:在我输入用户名时,发现我全拼的名字拼音打不出来.....
当时就纳闷了,我限制的是字符长度,咋我拼音也......

  • 快乐上网后,才发现这是一个隐藏bug~~

  • 解决方法很多,发现了 梦里挑灯看键 的这片博文,简单粗暴,就在这里记录一下[我只是想整理一下~~没别的意思]

  • 给输入框绑定一个方法

[_nameTextField addTarget:self action:@selector(editChange:) forControlEvents:UIControlEventEditingChanged];


  • 方法内部
- (void)editChange:(UITextField*)textfield {
    NSString *toBeString = textfield.text;
    NSString *lang = [[UIApplication sharedApplication]textInputMode].primaryLanguage; // 键盘输入模
    if ([lang isEqualToString:@"zh-Hans"]) { // 简体中文输入,包括简体拼音,健体五笔,简体手写
        UITextRange *selectedRange = [textfield markedTextRange];
        //获取高亮部分
        UITextPosition *position = [textfield positionFromPosition:selectedRange.start offset:0];
        // 没有高亮选择的字,则对已输入的文字进行字数统计和限制
        if (!position) {
            if (toBeString.length > kMaxLength)
            {
                NSRange rangeIndex = [toBeString rangeOfComposedCharacterSequenceAtIndex:kMaxLength];
                if (rangeIndex.length == 1)
                {
                    textfield.text = [toBeString substringToIndex:kMaxLength];
                }
                else
                {
                    NSRange rangeRange = [toBeString rangeOfComposedCharacterSequencesForRange:NSMakeRange(0, kMaxLength)];
                    textfield.text = [toBeString substringWithRange:rangeRange];
                }
            }
        }
    }
    // 中文输入法以外的直接对其统计限制即可,不考虑其他语种情况
    else{
        if (toBeString.length > kMaxLength)
        {
            NSRange rangeIndex = [toBeString rangeOfComposedCharacterSequenceAtIndex:kMaxLength];
            if (rangeIndex.length == 1)
            {
                textfield.text = [toBeString substringToIndex:kMaxLength];
            }
            else
            {
                NSRange rangeRange = [toBeString rangeOfComposedCharacterSequencesForRange:NSMakeRange(0,kMaxLength)];
                textfield.text = [toBeString substringWithRange:rangeRange];
            }
        }
    }
    
}

不华丽的分割线


八、tableView刷新时,出现乱跳等错乱现象

  • 在iOS 11 Self-Sizing自动打开后,contentSize和contentOffset都可能发生改变。可以通过以下方式禁用:
* 在初始化tableView的时候加上

if (@available(iOS 11.0, *)){
            self.tableView.estimatedRowHeight = 0;
            self.tableView.estimatedSectionHeaderHeight = 0;
            self.tableView.estimatedSectionFooterHeight = 0;
        }

亲测有效~~


不华丽的分割线


九、简单的定时刷新

  • 第一步@property (nonatomic, strong) NSTimer * timer;
  • 第二步:
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(post_data) userInfo:nil repeats:YES];
_timer = timer;
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
  • 第三步:
-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    [_timer invalidate];
    _timer = nil;
}

不华丽的分割线


十、安利一个 抽屉效果 MMDrawerController


不华丽的分割线


十一、按钮简单富文本

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@"登录即代表你同意“XXXX使用条款”"];
    NSRange range1 = NSMakeRange(0, attributedString.length - 10);
    NSRange range2 = NSMakeRange(attributedString.length - 10, 10);
    [attributedString addAttributes:@{NSFontAttributeName:[UIFont fontWithName:ThemeFontFamilyBlod size:16.0],NSForegroundColorAttributeName:ThemeFontColor2} range:range1];
    [attributedString addAttributes:@{NSFontAttributeName:[UIFont fontWithName:ThemeFontFamilyBlod size:16.0],NSForegroundColorAttributeName:[UIColor redColor]} range:range2];
    [agreedBtn setAttributedTitle:attributedString forState:UIControlStateNormal];
    [self.otherLoginView addSubview:agreedBtn];

不华丽的分割线


十二、iOS 11.0后的tableView、scrollView顶部留白处理

    //self.automaticallyAdjustsScrollViewInsets = NO;//失效
    if (@available(iOS 11.0, *)) {
        self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    } else {
        
        self.automaticallyAdjustsScrollViewInsets = NO;
    }
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,686评论 8 265
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,161评论 1 32
  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明AI阅读 16,024评论 3 119
  • “愿每一段短暂的漫长的沉默的坦诚的心意都能为人所知,被珍视记取,被小心安放。他了然于心,你念念不忘”。 非常喜欢这...
    汤水阅读 328评论 0 0
  • 下周就是父亲节了,今晚在写父亲节的文案,写着写着情绪就有些起伏了。我已经有很久没有父亲在身边陪伴了,上初一的第一个...
    anergo阅读 654评论 0 50