iOS 系统适配

695 阅读3分钟

iOS 26

UIBarButtonItemhidesSharedBackground 隐藏玻璃背景。

iOS 18

# iOS/Flutter: Only Xcode16 Can Do (问题收集)

iOS 17

YYLabel的YYAsyncLayer获取到invalid size导致崩溃

Xcode15在UIGraphicsBeginImageContextWithOptions(size, opaque, contentsScale);加了断言,如果传入sizewidth或者height其中一个为0,会崩溃。并且提示使用UIGraphicsImageRenderer可以解决此问题。

Swift不允许继承自OC的类使用+load方法

在OC类中使用+load方法

[NSURL URLWithString:string]对齐NSURLComponents的转换方式

17之前: URLWithString判断参数string,如国有非法字符(包含中文字符)就返回nil
17之后: URLWithString默认对非法字符(包含中文字符)进行%转义。如果没有非法字符,那URL中原有的转义字符%不会再次转义,如果有非法字符,那URL中原有的转义字符%会再次转义,导致无法兼容出现BUG。
方案一:

+ (instancetype)wt_URLWithString:(NSString *)URLString {
    if (@available(iOS 17.0, *)) {
        return [self URLWithString:URLString encodingInvalidCharacters:NO];// 不推荐的做法
    } else {
        return [self wt_URLWithString:URLString];
    }
}

方案二:
iOS17 NSURL解析异常处理

iOS 16

屏幕旋转API更换

方案:

UIDeviceOrientationDidChangeNotification 通知好像失效了,待确认

方案:

- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator {
    [super willTransitionToTraitCollection:newCollection withTransitionCoordinator:coordinator];
    [coordinator animateAlongsideTransition:^(id <UIViewControllerTransitionCoordinatorContext> context) {
        if (newCollection.verticalSizeClass == UIUserInterfaceSizeClassCompact) {
            xxView.frame = CGRectMake(0, 32, self.view.frame.size.width, self.view.frame.size.height - 32);
        } else {
            xxView.frame = CGRectMake(0, 64, self.view.frame.size.width, self.view.frame.size.height - 64);
        }

        [self.view setNeedsLayout];
    } completion:nil];
}

使用YYTextView后无法旋转

方案: juejin.cn/post/714604…

UINavigationItem.titleView

需要提供Frame,否则约束异常 方案:提供大小

- (CGSize)intrinsicContentSize {
    return UILayoutFittingExpandedSize; // 表示在可用范围内尽可能给予最大可用尺寸 
}

无法设置比透明度颜色等 方案:包一层UIView

self.titleView.frame = CGRectMake(0, 0, width, height);
if (@available(iOS 16.0, *)) {
    UIView *titleViewBG = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)]; 
    [titleViewBG addSubview:self.titleView]; 
    self.navigationItem.titleView = titleViewBG; 
} else { 
    self.navigationItem.titleView = self.titleView;
} 

self.titleView.alpha = xxxxx; // 透明度生效

设置 self.navigationItem.rightBarButtonItem 爆内存后崩溃

NSMutableDictionary 增加了空安全的防护,交换了系统的setObject:forKeyedSubscript: 方法。发现这个会导致在iOS16系统上面,设置 self.navigationItem.rightBarButtonItem = 时出现内存爆增,导致Crash。
因为setObject:forKeyedSubscript:等价于下标修改
当Object为nil时,Dictionary会将key对应的obj移除;
当key为空时,会抛出NSInvalidArgumentException异常;

不要在系统UIKit库的分类(Categroy)中重写 + (void)initialize方法

Xcode 14会报错

iOS 16.1.x无法使用密码自动填充功能(貌似整个iOS 16都受系统键盘弹出的奔溃影响)

/// 该系统版本会产生crash,在此版本去除该功能(暂行)     
if (![versionStr isEqualToString:@"16.1.1"]) {         
    _pwdTextField.secureTextEntry = YES;   
}

iOS键盘相关的崩溃溃就3个
修复键盘崩溃问题
我给 iOS 系统打了个补丁——修复 iOS 16 系统键盘重大 Crash(附补丁源码)

iOS 15

UITableView 分区之间有间隔,区头有留白

if (@available(iOS 15.0, *)) {
    self.tableView.sectionHeaderTopPadding = 0;
    [UITableView appearance].prefetchingEnabled = NO; // 预加载属性不适配的话可以关闭
}

iOS 14

iOS 13

iOS 12

iOS 11

UITextFeild

无法释放导致内存泄漏,解决方案如下:

方案一

extension UITextField {
    open override func removeFromSuperview() {
        if iOS11 {// 切记判断系统,否则奔溃
            let view = self.value(forKey: "textContentView") as? UIView
            if (view != nil) {
                view?.removeFromSuperview()
                self.setValue(nil, forKey: "textContentView")
            }
        }
    }
}

其他方案方,无法彻底解决

/// 关闭纠错
autocorrectionType = .no
/// 关闭密码框
secureTextEntry = false

刘海屏安全区顶部高度是47,margin的高度是13 灵动到安全区顶部高度是59,如果是用statusbar拿到的却是54,margin的高度是11