解决在自定义tabbar的时候出现双tabbar的问题

最近有个项目需要自定义tabbar,

我自定义tabbar的一个思路就是完全取代系统自带的tabbar,生成一个继承自UIview的customTabbar,将生成的customTabbar完全覆盖到tabbar上,为了让我们自己生成的tabbar也能使用系统的一些方法,我们需要将customTabbar添加到系统的tabbar上,这就是我的一个大概思路(后期再添加自定义的相关逻辑和代码)

在自定义tabbar的时候出现的问题,在iOS7以后tabbar做了一些修改,如果我们将customTabbar直接添加到系统的tabbar后,我们会发现,在显示的时候出现我们自己的tabbar和系统的tabbar这种效果当然使我们不需要的,怎么解决呢?我提供一个我的思路:我的做法是将系统tabbar生成的UItabbarButton从他的父视图上面移除,

for (UIView *button in self.tabBar.subviews) {
        if ([button isKindOfClass:[LXQTabBar class]]) {
            NSLog(@"button == %@",button);
        } else {
            [button removeFromSuperview];
        }
    }

这样就完美解决了,但是在后期使用中又发现一个问题,当我们dismiss或则popToViewController的时候,还是会出现系统的tabbarbutton,什么原因呢?我也不清楚,我大概想到可能和view里面的layoutSubviews这个方法有关,(希望有大神能讲解一下这一块的东西,谢谢),但是tabbarController没有这个方法,只有viewwilllayoutsubviews和ViewWilldidlayoutsubsiews这两个方法,最后将删除系统tabbarbutton的方法添加到了ViewWillLayoutSubviews这个方法里面就解决了这个问题

后记:

在更新iOS 10以后又重新出现以前的情况,一时不知道该怎么去解决,后面想了想,一直在外部去修改还不如去内部修改,因此想到了runtime来解决这个问题,通过runtime去修改系统的方法下面列出代码:

一、打印UITabbar系统方法:

- (void)systemMethod{
    unsigned int count;
    NSMutableArray *array = [NSMutableArray array];
    Method *meths = class_copyMethodList([UITabBar class], &count);
    for (int i = 0; i < count; i ++) {
        Method meth = meths[i];
        SEL sel = method_getName(meth);
        const char *name = sel_getName(sel);
        NSString *str = [NSString stringWithFormat:@"-------------- > %s",name];
        [array addObject:str];
    }
    LOG(@"%@",array);
}

打印的结果:

 (
    "-------------- > remove_layoutSubviews",
    "-------------- > setDelegate:",
    "-------------- > layoutSubviews",
    "-------------- > _populateArchivedSubviews:",
    "-------------- > hitTest:withEvent:",
    "-------------- > _intrinsicSizeWithinSize:",
    "-------------- > _contentHuggingDefault_isUsuallyFixedHeight",
    "-------------- > sizeThatFits:",
    "-------------- > traitCollectionDidChange:",
    "-------------- > _backgroundView",
    "-------------- > setSemanticContentAttribute:",
    "-------------- > setTranslatesAutoresizingMaskIntoConstraints:",
    "-------------- > touchesBegan:withEvent:",
    "-------------- > touchesMoved:withEvent:",
    "-------------- > touchesEnded:withEvent:",
    "-------------- > touchesCancelled:withEvent:",
    "-------------- > _setVisualAltitude:",
    "-------------- > _setVisualAltitudeBias:",
    "-------------- > isTranslucent",
    "-------------- > isLocked",
    "-------------- > didUpdateFocusInContext:withAnimationCoordinator:",
    "-------------- > preferredFocusedItem",
    "-------------- > setTintColor:",
    "-------------- > _isEligibleForFocus",
    "-------------- > canBecomeFocused",
    "-------------- > removeConstraint:",
    "-------------- > addConstraint:",
    "-------------- > _didMoveFromWindow:toWindow:",
    "-------------- > hitTest:forEvent:",
    "-------------- > _didChangeFromIdiom:onScreen:traverseHierarchy:",
    "-------------- > _subclassImplementsDrawRect",
    "-------------- > backgroundImage",
    "-------------- > shadowImage",
    "-------------- > setShadowImage:",
    "-------------- > _appearanceStorage",
    "-------------- > _accessibilityButtonShapesParametersDidChange",
    "-------------- > _effectiveBarTintColor",
    "-------------- > setItems:animated:",
    "-------------- > setLocked:",
    "-------------- > setBarStyle:",
    "-------------- > _hidesShadow",
    "-------------- > _backdropViewLayerGroupName",
    "-------------- > _setBackdropViewLayerGroupName:",
    "-------------- > _shadowView",
    "-------------- > _setBackgroundView:",
    "-------------- > _shadowAlpha",
    "-------------- > _setShadowAlpha:",
    "-------------- > _disableBlurTinting",
    "-------------- > _setDisableBlurTinting:",
    "-------------- > setBarTintColor:",
    "-------------- > _setHidesShadow:",
    "-------------- > barStyle",
    "-------------- > setTranslucent:",
    "-------------- > barTintColor",
    "-------------- > _accessoryView",
    "-------------- > _isTranslucent",
    "-------------- > _setBarOrientation:",
    "-------------- > _setAccessoryView:",
    "-------------- > setSelectedItem:",
    "-------------- > _setPreferredFocusHeading:",
    "-------------- > _setFocusedItemHightlightShouldBeVisible:",
    "-------------- > _setHiddenAwaitingFocus:",
    "-------------- > beginCustomizingItems:",
    "-------------- > isCustomizing",
    "-------------- > setBackgroundImage:",
    "-------------- > _sendAction:withEvent:",
    "-------------- > _barMetrics",
    "-------------- > _imageStyle",
    "-------------- > _setBarMetrics:",
    "-------------- > _setImageStyle:",
    "-------------- > selectionIndicatorImage",
    "-------------- > selectedImageTintColor",
    "-------------- > _effectiveUnselectedTabTintColorConsideringView:",
    "-------------- > _buttonDown:",
    "-------------- > _buttonUp:",
    "-------------- > _buttonCancel:",
    "-------------- > _showsHighlightedState",
    "-------------- > _setShowsHighlightedState:",
    "-------------- > _scrollsItems",
    "-------------- > itemPositioning",
    "-------------- > itemWidth",
    "-------------- > itemSpacing",
    "-------------- > _configureItems:",
    "-------------- > _setBackgroundNeedsUpdate:",
    "-------------- > _blurEnabled",
    "-------------- > _preferredFocusHeading",
    "-------------- > selectedItem",
    "-------------- > _focusedItemHighlightShouldBeVisible",
    "-------------- > _setBlurEnabled:",
    "-------------- > setSelectionIndicatorImage:",
    "-------------- > setSelectedImageTintColor:",
    "-------------- > _configureTabBarReplacingItem:withNewItem:swapping:",
    "-------------- > _positionAllItems",
    "-------------- > setItemWidth:",
    "-------------- > setItemSpacing:",
    "-------------- > _setScrollsItems:",
    "-------------- > setItemPositioning:",
    "-------------- > _accessibilityButtonShapesEnabledDidChangeNotification:",
    "-------------- > setUnselectedItemTintColor:",
    "-------------- > _doCommonTabBarInit",
    "-------------- > _effectiveBarOrientation",
    "-------------- > _updateBackgroundColorForTraitCollection:",
    "-------------- > _customizeWithAvailableItems:",
    "-------------- > _dismissCustomizeSheet:",
    "-------------- > _updateTintedImages:selected:",
    "-------------- > _effectiveBarTintColorDidChange",
    "-------------- > unselectedItemTintColor",
    "-------------- > _effectiveUnselectedTintColor",
    "-------------- > _isHiddenAwaitingFocus",
    "-------------- > _buttonDownDelayed:",
    "-------------- > _adjustButtonSelection:",
    "-------------- > _customizeDoneButtonAction:",
    "-------------- > _totalDimensionForItems:spacing:dimension:scaleFactor:",
    "-------------- > _setBackgroundImage:",
    "-------------- > _setSelectionIndicatorImage:",
    "-------------- > _setLabelFont:",
    "-------------- > _setLabelTextColor:selectedTextColor:",
    "-------------- > _setLabelShadowColor:",
    "-------------- > _setLabelShadowOffset:",
    "-------------- > _setVibrantLabels:",
    "-------------- > _vibrantLabels",
    "-------------- > _nextSelectionSlideDuration",
    "-------------- > _setNextSelectionSlideDuration:",
    "-------------- > _backgroundNeedsUpdate",
    "-------------- > _setTabBarSizing:",
    "-------------- > _setTabButtonWidth:",
    "-------------- > _tabButtonWidth",
    "-------------- > _setInterTabButtonSpacing:",
    "-------------- > _interTabButtonSpacing",
    "-------------- > _barOrientation",
    "-------------- > endCustomizingAnimated:",
    "-------------- > _makeCurrentButtonFirstResponder",
    "-------------- > _setDividerImage:forLeftButtonState:rightButtonState:",
    "-------------- > _dividerImageForLeftButtonState:rightButtonState:",
    "-------------- > _pendingFocusAction",
    "-------------- > _setPendingFocusAction:",
    "-------------- > _focusedTabBarItem",
    "-------------- > _tabBarFinishedAnimating",
    "-------------- > dismissCustomizeSheet:",
    "-------------- > _scaleFactorForItems:spacing:dimension:maxWidth:",
    "-------------- > _updateTabBarItemView:",
    "-------------- > _tabBarSizing",
    "-------------- > isElementAccessibilityExposedToInterfaceBuilder",
    "-------------- > _autolayoutSpacingAtEdge:inContainer:",
    "-------------- > _autolayoutSpacingAtEdge:nextToNeighbor:",
    "-------------- > _hasCustomAutolayoutNeighborSpacing",
    "-------------- > encodeWithCoder:",
    "-------------- > initWithCoder:",
    "-------------- > delegate",
    "-------------- > setBounds:",
    "-------------- > .cxx_destruct",
    "-------------- > dealloc",
    "-------------- > initWithFrame:",
    "-------------- > setFrame:",
    "-------------- > items",
    "-------------- > setItems:",
    "-------------- > drawRect:"
)
我接触iOS的时间也不长,不能从这对堆结果中去找到具体设置tabbarbutton的方法,但是我知道layoutSubviews是布局子视图的方法,然后就用runtime替换掉UItabbar中的layoutSubviews方法,在布局子视图的时候将系统自带的UItabbarbutton给移除掉,贴代码:

这段代码是写在UItabbar的分类中的:

+ (void)load{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        SEL systemSel = @selector(layoutSubviews);
        SEL lxqSel = @selector(remove_layoutSubviews);
        
        Method systemMethod = class_getInstanceMethod([self class], systemSel);
        Method lxqMethod = class_getInstanceMethod([self class], lxqSel);
        BOOL isAdd = class_addMethod(self, systemSel, method_getImplementation(lxqMethod), method_getTypeEncoding(lxqMethod));
        if (isAdd) {
            class_replaceMethod(self, lxqSel, method_getImplementation(systemMethod), method_getTypeEncoding(systemMethod));
        } else {
            method_exchangeImplementations(systemMethod, lxqMethod);
        }
    });
}

- (void)remove_layoutSubviews{
    NSArray *subviews = self.subviews;
    for (UIView *subview in subviews) {
        if ([subview isKindOfClass:[LXQTabBar class]]) {
            
        } else {
            [subview removeFromSuperview];
        }
    }
    
}

这样就完美解决了iOS10 以及以前系统的问题了,不过就是不知道这样做了之后会不会出现审核不通过的问题!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值