升级到 iOS18 之后项目中遇到了几个Crash 的问题,在此记录一下,也希望能帮助到大家。
-
问题1:Set maskView,是由 QMUIToastView中的maskView 导致的,断点在这个didInitialize 方法中
- (void)didInitialize {
self.tintColor = UIColorWhite;
self.toastPosition = QMUIToastViewPositionCenter;
// 顺序不能乱,先添加backgroundView再添加contentView
self.backgroundView = [self defaultBackgrondView];
self.contentView = [self defaultContentView];
self.opaque = NO;
self.alpha = 0.0;
self.backgroundColor = UIColorClear;
self.layer.allowsGroupOpacity = NO;
_maskView = [[UIView alloc] init];
self.maskView.backgroundColor = UIColorClear;
[self addSubview:self.maskView];
[self registerNotifications];
}
控制台报错信息:
Thread 1: "Set `maskView` (<UIView: 0x130d21980; frame = (0 0; 0 0);
backgroundColor = UIExtendedSRGBColorSpace 1 1 1 0,
RGBA(255, 255, 255, 0.00), #00ffffff; layer = <CALayer: 0x143e9ee80>>) to `nil` before adding it as a subview of
<QMUITips: 0x11a9ab980;frame = (0 0; 375 812); alpha = 0; opaque = NO; tintColor = UIExtendedSRGBColorSpace 1 1 1 1,
RGBA(255, 255, 255, 1.00), #ffffffff; backgroundColor = UIExtendedSRGBColorSpace 1 1 1 0,
RGBA(255, 255, 255, 0.00), #00ffffff; layer = <CALayer: 0x144921b80>>"
解决办法:将.h文件和.m文件中的maskView修改成其它命名
@property(nonatomic, strong, readonly) UIView *qmui_maskView;
_qmui_maskView = [[UIView alloc] init];
self.maskView.backgroundColor = UIColorClear;
[self addSubview:self.maskView];
-
问题2:Crash using NSMutableAttributedString with an HMTL document inside a collection view
我出错的代码
- (NSMutableAttributedString *)attributeStrWithSize:(CGFloat)size {
NSString *htmlString = [NSString stringWithFormat:@"<html><body> %@ <font size=\"%f\"> </body></html>",self,size];
NSMutableAttributedString *attibuteStr = [[NSMutableAttributedString alloc] initWithData:
[htmlString dataUsingEncoding:NSUnicodeStringEncoding] options:@{NSDocumentTypeDocumentAttribute:
NSHTMLTextDocumentType} documentAttributes:nil error:nil];
return attibuteStr;
}
解决办法:将它加入到主线程即可
- (NSMutableAttributedString *)attributeStrWithSize:(CGFloat)size {
NSMutableAttributedString *attibuteStr = [[NSMutableAttributedString alloc] initWithString:self];
dispatch_async(dispatch_get_main_queue(), ^{
NSString *htmlString = [NSString stringWithFormat:@"<html><body> %@ <font size=\"%f\"> </body></html>",self,size];
NSMutableAttributedString *attibuteStr = [[NSMutableAttributedString alloc] initWithData:
[htmlString dataUsingEncoding:NSUnicodeStringEncoding] options:@{NSDocumentTypeDocumentAttribute:
NSHTMLTextDocumentType} documentAttributes:nil error:nil];
attibuteStr = attibuteStr;
});
return attibuteStr;
}
-
问题3:这个是很多人遇到最多的问题,大概的意思就是执行了多次dequeueReusableCell,我这里的报错信息如下:
UICollectionView _updateVisibleCellsNow
Exception NSException * "Expected dequeued view to be returned to the collection view in preparation for display.
When the collection view's data source is asked to provide a view for a given index path, ensure that a single view
is dequeued and returned to the collection view. Avoid dequeuing views without a request from the collection view. For retrieving an existing view in the collection view,
use -[UICollectionView cellForItemAtIndexPath:] or -[UICollectionView supplementaryViewForElementKind:atIndexPath:].
Dequeued view: <UICollectionReusableView: 0x116113200; frame = (0 301.333; 393 50); layer = <CALayer: 0x1161852c0>>;
Collection view: <UICollectionView: 0x109ec4000; frame = (0 0; 393 754.333); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x10cb33930>;
backgroundColor = <UIDynamicProviderColor: 0x10cacbe20; provider = <__NSMallocBlock__: 0x10c833fc0>>; layer = <CALayer: 0x10cacbcc0>;
contentOffset: {0, 0}; contentSize: {393, 1029.105}; adjustedContentInset: {0, 0, 83, 0}>, contentInset = {0, 0, 0, 0; layout: <YKCollect"... 0x00000001161777b0
但是断点断在了MJRefresh的UIScrollView+MJExtension
里面
- (void)setMj_insetT:(CGFloat)mj_insetT
{
UIEdgeInsets inset = self.contentInset;
inset.top = mj_insetT;
#ifdef __IPHONE_11_0
if (respondsToAdjustedContentInset_) {
inset.top -= (self.adjustedContentInset.top - self.contentInset.top);
}
#endif
self.contentInset = inset;
}
就很奇怪,摸不着头脑,上GitHub找MJRefresh的issue也没有类似的,又各种百度、google,终于在https://developer.apple.com/forums/上面找到了解决方案。每个人的具体需要改的代码位置不一样,有可能在- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
中,也有可能在- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
中,所以你需要注意的是不要多次加载dequeueReusableCell。
解决方案如下:
改动前
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
//这个地方就是多次调用了dequeueReusableSupplementaryViewOfKind
UICollectionReusableView *view = [self.collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:collectionNilSectionHeader forIndexPath:indexPath];
WS(weakSelf);
if (self.tagbqArray.count != 0) {
YKSectionHeaderCollectionReusableView *sliderView = [self.collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:collectionSliderSectionHeader forIndexPath:indexPath];
static NSString *collectionNilSectionFooter = @"collectionNilSectionFooter";
[weakSelf updateShopData:model];
};
return sliderView;
}
return view;
}
改动后
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
WS(weakSelf);
if (self.tagbqArray.count != 0) {
YKSectionHeaderCollectionReusableView *sliderView = [self.collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:collectionSliderSectionHeader forIndexPath:indexPath];
static NSString *collectionNilSectionFooter = @"collectionNilSectionFooter";
[weakSelf updateShopData:model];
};
return sliderView;
} else {
UICollectionReusableView *view = [self.collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:collectionNilSectionHeader forIndexPath:indexPath];
return view;
}
}
如何把 UITabBar 移到底部?UITabBarController 的 sideBar
iPadOS 18.1 + Xcode 16.1 仅仅设置self.mode = UITabBarControllerModeTabBar不起作用
// 在UITabBarController子类里
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 180000
if (@available(iOS 18.0, *)) {
if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
self.mode = UITabBarControllerModeTabBar;
self.traitOverrides.horizontalSizeClass = UIUserInterfaceSizeClassCompact;
[self.view addSubview:self.tabBar];
NSString *tabContainerClassName = [NSString stringWithFormat:@"%@%@%@", @"_UITab", @"Container", @"View"];
for (UIView *subview in self.view.subviews) {
if ([NSStringFromClass(subview.class) isEqualToString:tabContainerClassName]) {
[subview setHidden:YES];
}
}
}
}
#endif
如果你也遇到了类似问题,但还是没有解决好,可以在下面回复我,我来帮你一起解决。