[崩溃] -[MyBaseLayout myValidMargin:subview:calcPos:selfLayoutSize:]

#147 · closed · 2 comments

View on GitHub ↗

LinkRober

场景: 在ViewController中的`- (void)loadView`方法布局,容器是`UIScrollowView` 崩溃栈信息 ``` Kernel Triage: VM - Compressor failed a blocking pager_get Thread 0 name: Thread 0 Crashed: 0 libobjc.A.dylib 0x000000019b1025e0 objc_msgSend + 32 1 LeoaoApp 0x0000000105af3dc8 -[MyBaseLayout myValidMargin:subview:calcPos:selfLayoutSize:] + 12631496 (MyBaseLayout.m:2331) 2 LeoaoApp 0x0000000105b30750 -[MyLinearLayout myDoHorzOrientationLayoutWithContext:] + 12879696 (MyLinearLayout.m:982) 3 LeoaoApp 0x0000000105b2b1b4 -[MyLinearLayout calcLayoutSize:subviewEngines:context:] + 12857780 (MyLinearLayout.m:163) 4 LeoaoApp 0x0000000105af0144 -[MyBaseLayout myEstimateLayoutSize:inSizeClass:subviews:] + 12616004 (MyBaseLayout.m:0) 5 LeoaoApp 0x0000000105af5ec0 -[MyBaseLayout myWidthSizeValueOfSubviewEngine:withContext:] + 12639936 (MyBaseLayout.m:2649) 6 LeoaoApp 0x0000000105b2ee44 -[MyLinearLayout myDoHorzOrientationLayoutWithContext:] + 12873284 (MyLinearLayout.m:0) 7 LeoaoApp 0x0000000105b2b1b4 -[MyLinearLayout calcLayoutSize:subviewEngines:context:] + 12857780 (MyLinearLayout.m:163) 8 LeoaoApp 0x0000000105af0144 -[MyBaseLayout myEstimateLayoutSize:inSizeClass:subviews:] + 12616004 (MyBaseLayout.m:0) 9 UIKitCore 0x000000018531dae4 -[_UITAMICAdaptorView updateForAvailableSize] + 124 (_UITAMICAdaptorView.m:111) 10 UIKitCore 0x000000018562ba14 -[_UITAMICAdaptorView _geometryChanged:forAncestor:] + 84 (_UITAMICAdaptorView.m:130) 11 UIKitCore 0x00000001851754c0 -[UIView _notifyGeometryObserversWithChangeInfo:] + 280 (UIView.m:8875) 12 UIKitCore 0x000000018519668c -[UIView(Geometry) setFrame:] + 836 (UIView.m:10170) 13 LeoaoApp 0x0000000105aec794 -[MyBaseLayout setFrame:] + 12601236 (MyBaseLayout.m:1096) 14 LeoaoApp 0x0000000105aeecf4 -[MyBaseLayout doLayoutSubviews] + 12610804 (MyBaseLayout.m:1562) 15 LeoaoApp 0x0000000105aefe64 -[MyBaseLayout layoutSubviews] + 12615268 (MyBaseLayout.m:1722) 16 UIKitCore 0x000000018519ac6c -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2620 (UIView.m:18320) 17 QuartzCore 0x00000001868f4280 CA::Layer::layout_if_needed(CA::Transaction*) + 536 (CALayer.mm:10036) 18 QuartzCore 0x00000001868e6aa8 CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 144 (CALayer.mm:2478) 19 QuartzCore 0x00000001868fb0b0 CA::Context::commit_transaction(CA::Transaction*, double, double*) + 500 (CAContextInternal.mm:2584) 20 QuartzCore 0x0000000186904174 CA::Transaction::commit() + 680 (CATransactionInternal.mm:449) 21 QuartzCore 0x00000001868e621c CA::Transaction::flush_as_runloop_observer(bool) + 100 (CATransactionInternal.mm:941) 22 UIKitCore 0x0000000185551c28 _UIApplicationFlushCATransaction + 76 (UIApplication.m:0) 23 UIKitCore 0x00000001857ebad8 _UIUpdateSequenceRun + 84 (_UIUpdateSequence.mm:67) 24 UIKitCore 0x0000000185e63294 schedulerStepScheduledMainSection + 144 (_UIUpdateCycleScheduler.m:1204) 25 UIKitCore 0x0000000185e62760 runloopSourceCallback + 60 (_UIUpdateCycleScheduler.m:1292) 26 CoreFoundation 0x0000000182c1e030 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28 (CFRunLoop.c:1972) 27 CoreFoundation 0x0000000182c2ecf0 __CFRunLoopDoSource0 + 208 (CFRunLoop.c:2016) 28 CoreFoundation 0x0000000182b68ff8 __CFRunLoopDoSources0 + 268 (CFRunLoop.c:2053) 29 CoreFoundation 0x0000000182b6e804 __CFRunLoopRun + 820 (CFRunLoop.c:2951) 30 CoreFoundation 0x0000000182b823c8 CFRunLoopRunSpecific + 600 (CFRunLoop.c:3268) 31 GraphicsServices 0x000000019e39338c GSEventRunModal + 164 (GSEvent.c:2200) 32 UIKitCore 0x0000000185528060 -[UIApplication _run] + 1100 (UIApplication.m:3457) 33 UIKitCore 0x00000001852a5b8c UIApplicationMain + 2124 (UIApplication.m:5013) 34 LeoaoApp 0x0000000105235514 main + 3462420 (main.m:34) 35 dyld 0x0000000108835a24 start + 520 (dyldMain.cpp:876) ```

Comments

youngsoft

从这个崩溃栈以及结合的代码来看,应该是为MyLayoutPos对象设置的最大最小值的类型不被支持导致的: //约束冲突:无效的边界设置方法 NSCAssert(0, @"Constraint exception!! %@ has invalid lBound or uBound setting", subview); 对于MyLayoutPos中的lBound或者uBound方法来说,只支持最大最小值为具体的某个数字或者另外一个MyLayoutPos对象,而不支持MyLayoutSize对象,问题可能是你设置某个位置的最大最小值是某个尺寸对象,这是不自持的。

LinkRober

从下图看,像是野指针的问题,如果是类型不对应该每次都崩溃,下面是线上灰度,testflight收集到的崩溃。 <img width="1141" alt="B11D840B-B564-458F-AA23-E48A6C1072E7" src="https://user-images.githubusercontent.com/7357189/139418953-ec5b93e6-0023-44aa-8fbe-9355e88f1f22.png"> 布局代码 ``` - (void)setUpView { CALayer *bgLayer = [CALayer layer]; bgLayer.backgroundColor = [UIColor lk_colorWithHexString:@"#4A445C"].CGColor; bgLayer.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight / 2.0); [self.view.layer addSublayer:bgLayer]; self.view.backgroundColor = [UIColor lk_colorWithHexString:@"#F5F5F5"]; CGRect rect = self.view.bounds; rect.origin.y = kNavBarHeight; rect.size.height -= (kNavBarHeight + kTabBarHeight); UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:rect]; scrollView.backgroundColor = [UIColor clearColor]; scrollView.delegate = self; self.scrollView = scrollView; LKAdjustsScrollViewInsetsNO(scrollView, self); [self.view addSubview:scrollView]; _loadingView = [[LKLoading alloc] initWithFrame:CGRectMake((rect.size.width - 100) / 2.0, (rect.size.height - 100) / 2.0, 100, 100)]; [self.view addSubview:_loadingView]; /// 容器 MyLinearLayout *contentLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; contentLayout.backgroundColor = [UIColor lk_colorWithHexString:@"#F5F5F5"]; contentLayout.padding = UIEdgeInsetsMake(8, 16, 10, 16); //设置布局内的子视图离自己的边距. contentLayout.myHorzMargin = 0; //同时指定左右边距为0表示宽度和父视图一样宽 contentLayout.heightSize.lBound(scrollView.heightSize, 10, 1); //高度虽然是自适应的。但是最小的高度不能低于父视图的高度加10. contentLayout.gravity = MyGravity_Vert_Top | MyGravity_Horz_Stretch; [scrollView addSubview:contentLayout]; self.contentLayout = contentLayout; /// 背景 LKRadianView *radianView = [LKRadianView new]; radianView.direction = LKRadianDirectionBottom; radianView.radian = 10; radianView.backgroundColor = [UIColor lk_colorWithHexString:@"#4A445C"]; radianView.frame = CGRectMake(0, -1, kScreenWidth, 114); radianView.useFrame = YES; [contentLayout insertSubview:radianView atIndex:0]; /// 头部运动数据卡片 MyLinearLayout *topCardLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; topCardLayout.myHorzMargin = 0; topCardLayout.subviewHSpace = 7; topCardLayout.gravity = MyGravity_Horz_Fill | MyGravity_Vert_Stretch; topCardLayout.myHeight = MyLayoutSize.wrap; [contentLayout addSubview:topCardLayout]; self.sportDaysCardView = [LKSportMainSportDataCardView new]; self.sportDaysCardView.weight = 1; self.sportDaysCardView.myHeight = 120; [self.sportDaysCardView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapSportDays:)]]; self.sportWeightCardView = [LKSportMainHealthDataCardView new]; self.sportWeightCardView.weight = 1; self.sportWeightCardView.myHeight = 120; [self.sportWeightCardView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapWeight:)]]; [topCardLayout addSubview:self.sportDaysCardView]; [topCardLayout addSubview:self.sportWeightCardView]; //教练 MyRelativeLayout *coachPageViewLayout = [MyRelativeLayout new]; coachPageViewLayout.backgroundColor = UIColor.whiteColor; coachPageViewLayout.layer.cornerRadius = 6; coachPageViewLayout.myHeight = 0; coachPageViewLayout.myTop = 8; _coachPageViewLayout = coachPageViewLayout; [contentLayout addSubview:coachPageViewLayout]; LKPagerView *pageView = [LKPagerView new]; pageView.interitemSpacing = 8; pageView.delegate = self; pageView.dataSource = self; pageView.automaticSlidingInterval = 0; [pageView registerClass:LKSportMainCoachPageViewCell.class forCellWithReuseIdentifier:NSStringFromClass(LKSportMainCoachPageViewCell.class)]; _coachPageView = pageView; pageView.widthSize.equalTo(coachPageViewLayout.widthSize); pageView.heightSize.equalTo(coachPageViewLayout.heightSize); [coachPageViewLayout addSubview:pageView]; LKPageControl *pControl = [LKPageControl new]; pControl.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; [pControl setItemSpacing:10 forState:UIControlStateNormal]; [pControl setItemSpacing:18 forState:UIControlStateSelected]; pControl.interitemSpacing = 3; pControl.hidesForSinglePage = YES; [pControl setStrokeColor:[UIColor lk_colorWithHexString:@"#F2F2F2"] forState:UIControlStateNormal]; [pControl setFillColor:[UIColor lk_colorWithHexString:@"#F2F2F2"] forState:UIControlStateNormal]; [pControl setStrokeColor:[UIColor lk_colorWithHexString:@"#F2F2F2"] forState:UIControlStateSelected]; [pControl setFillColor:[UIColor lk_colorWithHexString:@"#F2F2F2"] forState:UIControlStateSelected]; UIBezierPath *path11 = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, (10 - 2) / 2.0, 10, 2) cornerRadius:2]; [pControl setPath:path11 forState:UIControlStateNormal]; UIBezierPath *path22 = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, (18 - 2) / 2.0, 18, 2) cornerRadius:2];; [pControl setPath:path22 forState:UIControlStateSelected]; _coachPageControl = pControl; pControl.widthSize.equalTo(coachPageViewLayout.widthSize); pControl.heightSize.equalTo(@2); pControl.bottomPos.equalTo(coachPageViewLayout.bottomPos).offset(7); [coachPageViewLayout addSubview:pControl]; /// 运动日历 MyLinearLayout *sportCalendaLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; sportCalendaLayout.backgroundColor = [UIColor whiteColor]; sportCalendaLayout.layer.cornerRadius = 8; sportCalendaLayout.layer.masksToBounds = YES; sportCalendaLayout.myHorzMargin = 0; sportCalendaLayout.myHeight = MyLayoutSize.wrap; sportCalendaLayout.myTop = 12; sportCalendaLayout.gravity = MyGravity_Horz_Stretch; _sportCalendaLayout = sportCalendaLayout; [contentLayout addSubview:sportCalendaLayout]; // logo MyLinearLayout *logoLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; logoLayout.myHorzMargin = 0; logoLayout.myHeight = MyLayoutSize.wrap; logoLayout.gravity = MyGravity_Vert_Center | MyGravity_Horz_Between; logoLayout.padding = UIEdgeInsetsMake(22, 16, 5, 21); UIImageView *logoImageView = [UIImageView new]; logoImageView.image = [UIImage lk_imageNamed:@"sport_tab_sport_calendar_logo_image" inBundleClass:self.class subBundleName:@"LKSportCalendar"]; logoImageView.mySize = CGSizeMake(75, 21); [logoLayout addSubview:logoImageView]; // 我的课程按钮 MyLinearLayout *myCourseLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; myCourseLayout.gravity = MyGravity_Vert_Center; myCourseLayout.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); UILabel *myCourseLabel = [UILabel new]; myCourseLabel.text = @"我的课程"; myCourseLabel.font = [UIFont pingFangSCRegularFontOfSize:14]; myCourseLabel.textColor = [UIColor lk_colorWithHexString:@"#333333"]; myCourseLabel.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); UIImageView *myCourseArrowImageView = [UIImageView new]; myCourseArrowImageView.image = [[UIImage lk_imageNamed:@"sport_tab_main_right_arrow_icon" inBundleClass:self.class subBundleName:@"LKSportTabMain"] imageByTintColor:[UIColor lk_colorWithHexString:@"#BBBBBB"]]; myCourseArrowImageView.myLeft = 0; myCourseArrowImageView.mySize = CGSizeMake(MyLayoutSize.wrap, MyLayoutSize.wrap); [myCourseLayout addSubview:myCourseLabel]; [myCourseLayout addSubview:myCourseArrowImageView]; [myCourseLayout addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapCourseHistory:)]]; [logoLayout addSubview:myCourseLayout]; [sportCalendaLayout addSubview:logoLayout]; // 日期菜单 _dateCourseMenu = [LKDateCourseMenu new]; _dateCourseMenu.delegate = self; _dateCourseMenu.showBottomLine = NO; _dateCourseMenu.myHorzMargin = 0; NSString *deviceType = [UIDevice currentDevice].model; if ([deviceType isEqualToString:@"iPad"]) { _dateCourseMenu.myHeight = 57 * LKPoint(); } else { _dateCourseMenu.myHeight = 58; } [sportCalendaLayout addSubview:_dateCourseMenu]; // 行程布局 _calendarLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Horz]; _calendarLayout.myHorzMargin = 0; _calendarLayout.heightSize.equalTo(@(128)); _calendarLayout.myTop = 12; [sportCalendaLayout addSubview:_calendarLayout]; // 行程列表 _pageContentView = [[LKPageContentView alloc] init]; _pageContentView.delegate = self; _pageContentView.mySize = CGSizeMake(MyLayoutSize.fill, MyLayoutSize.fill); [_calendarLayout addSubview:_pageContentView]; /// 自律空间 MyLinearLayout *disciplineSpaceLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert]; disciplineSpaceLayout.myHorzMargin = 0; disciplineSpaceLayout.myHeight = MyLayoutSize.wrap; disciplineSpaceLayout.myTop = 20; disciplineSpaceLayout.gravity = MyGravity_Horz_Stretch; _disciplineSpaceLayout = disciplineSpaceLayout; [contentLayout addSubview:disciplineSpaceLayout]; UILabel *disciplineSpaceLabel = [UILabel new]; disciplineSpaceLabel.text = @"自律空间"; disciplineSpaceLabel.font = [UIFont pingFangSCMediumFontOfSize:20]; disciplineSpaceLabel.textColor = [UIColor lk_colorWithHexString:@"#333333"]; disciplineSpaceLabel.mySize = CGSizeMake(MyLayoutSize.wrap, 20); [disciplineSpaceLayout addSubview:disciplineSpaceLabel]; // banner MyRelativeLayout *bannerLayout = [MyRelativeLayout new]; CGFloat width = kScreenWidth - 16 * 2; bannerLayout.mySize = CGSizeMake(width, width / 335.0 * 100.0); bannerLayout.myTop = 12; bannerLayout.visibility = MyVisibility_Gone; _bannerLayout = bannerLayout; [disciplineSpaceLayout addSubview:bannerLayout]; LKPagerView *pagerView = [LKPagerView new]; pagerView.interitemSpacing = 18; pagerView.delegate = self; pagerView.dataSource = self; pagerView.automaticSlidingInterval = 3.5; pagerView.isInfinite = YES; pagerView.removesInfiniteLoopForSingleItem = YES; [pagerView registerClass:LKPagerViewCell.class forCellWithReuseIdentifier:NSStringFromClass(LKPagerViewCell.class)]; _banner = pagerView; pagerView.widthSize.equalTo(bannerLayout.widthSize); pagerView.heightSize.equalTo(bannerLayout.heightSize); [bannerLayout addSubview:pagerView]; LKPageControl *pageControl = [LKPageControl new]; pageControl.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; [pageControl setItemSpacing:10 forState:UIControlStateNormal]; [pageControl setItemSpacing:18 forState:UIControlStateSelected]; pageControl.interitemSpacing = 3; pageControl.hidesForSinglePage = YES; [pageControl setStrokeColor:[UIColor lk_colorWithHexString:@"#FFFFFF"] forState:UIControlStateNormal]; [pageControl setFillColor:[UIColor lk_colorWithHexString:@"#FFFFFF"] forState:UIControlStateNormal]; [pageControl setStrokeColor:[UIColor lk_colorWithHexString:@"#FFFFFF"] forState:UIControlStateSelected]; [pageControl setFillColor:[UIColor lk_colorWithHexString:@"#FFFFFF"] forState:UIControlStateSelected]; UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, (10 - 2) / 2.0, 10, 2) cornerRadius:2]; [pageControl setPath:path forState:UIControlStateNormal]; UIBezierPath *path1 = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, (18 - 2) / 2.0, 18, 2) cornerRadius:2];; [pageControl setPath:path1 forState:UIControlStateSelected]; _pageControl = pageControl; pageControl.widthSize.equalTo(bannerLayout.widthSize); pageControl.heightSize.equalTo(@2); pageControl.bottomPos.equalTo(bannerLayout.bottomPos).offset(7); [bannerLayout addSubview:pageControl]; /// 领取乐币,饮食打卡,健身赚现金,走跑赢勋章 MyFlowLayout *disciplineSpaceContentLayout = [MyFlowLayout flowLayoutWithOrientation:MyOrientation_Vert arrangedCount:2]; disciplineSpaceContentLayout.myHeight = MyLayoutSize.wrap; disciplineSpaceContentLayout.gravity = MyGravity_Horz_Fill; //所有子视图水平填充,也就是所有子视图的宽度相等。 disciplineSpaceContentLayout.padding = UIEdgeInsetsMake(14, 0, 16, 0); disciplineSpaceContentLayout.subviewHSpace = 12; disciplineSpaceContentLayout.subviewVSpace = 12; _disciplineSpaceContentLayout = disciplineSpaceContentLayout; [disciplineSpaceLayout addSubview:disciplineSpaceContentLayout]; } ```