当前位置 主页 > 网站技术 > 代码类 >

    iOS13原生端适配攻略(推荐)

    栏目:代码类 时间:2019-11-09 21:04

    随着iOS 13的发布,公司的项目也势必要着手适配了。现汇总一下iOS 13的各种坑

    1. KVC访问私有属性

    这次iOS 13系统升级,影响范围最广的应属KVC访问修改私有属性了,直接禁止开发者获取或直接设置私有属性。而KVC的初衷是允许开发者通过Key名直接访问修改对象的属性值,为其中最典型的 UITextField 的 _placeholderLabel、UISearchBar 的 _searchField。

    造成影响:在iOS 13下App闪退

    错误代码:

    // placeholderLabel私有属性访问
    [textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];
    [textField setValue:[UIFont boldSystemFontOfSize:16] forKeyPath:@"_placeholderLabel.font"];
    // searchField私有属性访问
    UISearchBar *searchBar = [[UISearchBar alloc] init];
    UITextField *searchTextField = [searchBar valueForKey:@"_searchField"];
    

    解决方案:

    使用 NSMutableAttributedString 富文本来替代KVC访问 UITextField 的 _placeholderLabel

    textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"placeholder" attributes:@{NSForegroundColorAttributeName: [UIColor darkGrayColor], NSFontAttributeName: [UIFont systemFontOfSize:13]}];
    
    

    因此,可以为UITextFeild创建Category,专门用于处理修改placeHolder属性提供方法

    #import "UITextField+ChangePlaceholder.h"
    
    @implementation UITextField (Change)
    
    - (void)setPlaceholderFont:(UIFont *)font {
    
     [self setPlaceholderColor:nil font:font];
    }
    
    - (void)setPlaceholderColor:(UIColor *)color {
    
     [self setPlaceholderColor:color font:nil];
    }
    
    - (void)setPlaceholderColor:(nullable UIColor *)color font:(nullable UIFont *)font {
    
     if ([self checkPlaceholderEmpty]) {
      return;
     }
    
     NSMutableAttributedString *placeholderAttriString = [[NSMutableAttributedString alloc] initWithString:self.placeholder];
     if (color) {
      [placeholderAttriString addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(0, self.placeholder.length)];
     }
     if (font) {
      [placeholderAttriString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, self.placeholder.length)];
     }
    
     [self setAttributedPlaceholder:placeholderAttriString];
    }
    
    - (BOOL)checkPlaceholderEmpty {
     return (self.placeholder == nil) || ([[self.placeholder stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0);
    }
    
    

    关于 UISearchBar,可遍历其所有子视图,找到指定的 UITextField 类型的子视图,再根据上述 UITextField 的通过富文本方法修改属性。

    #import "UISearchBar+ChangePrivateTextFieldSubview.h"
    
    @implementation UISearchBar (ChangePrivateTextFieldSubview)
    
    /// 修改SearchBar系统自带的TextField
    - (void)changeSearchTextFieldWithCompletionBlock:(void(^)(UITextField *textField))completionBlock {
    
     if (!completionBlock) {
      return;
     }
     UITextField *textField = [self findTextFieldWithView:self];
     if (textField) {
      completionBlock(textField);
     }
    }
    
    /// 递归遍历UISearchBar的子视图,找到UITextField
    - (UITextField *)findTextFieldWithView:(UIView *)view {
    
     for (UIView *subview in view.subviews) {
      if ([subview isKindOfClass:[UITextField class]]) {
       return (UITextField *)subview;
      }else if (subview.subviews.count > 0) {
       return [self findTextFieldWithView:subview];
      }
     }
     return nil;
    }
    @end