Элементы UITabBar, переходящие на обратную навигацию на iOS 12.1 - PullRequest
0 голосов
/ 31 октября 2018

У меня есть приложение для iOS с UITabBarController на главном экране, переход к подробному экрану, скрывающее UITabBarController с настройкой hidesBottomBarWhenPushed = true.

Возвращаясь к главному экрану, UITabBarController делает странный «прыжок», как показано на этом GIF:

enter image description here

Это происходит только на iOS 12.1 , а не на 12.0 или 11.x.

Похоже на ошибку в iOS 12.1, потому что я заметил другие приложения, такие как FB Messenger с таким поведением, но мне было интересно, есть ли какое-то решение для этого?

Ответы [ 12 ]

0 голосов
/ 24 февраля 2019

В моем случае (iOS 12.1.4) я обнаружил, что это странное сбойное поведение было вызвано модалами, представленными с .modalPresentationStyle = .fullScreen

После обновления их стиля презентации до .overFullScreen глюк исчез.

0 голосов
/ 21 января 2019

Если вы все еще хотите сохранить прозрачность панели вкладок, вам нужно создать подкласс из UITabBar и переопределить свойство safeAreaInsets

class MyTabBar: UITabBar {

private var safeInsets = UIEdgeInsets.zero

@available(iOS 11.0, *)
override var safeAreaInsets: UIEdgeInsets {
    set {
        if newValue != UIEdgeInsets.zero {
            safeInsets = newValue
        }
    }
    get {
        return safeInsets
    }
} 

}

Идея состоит в том, чтобы не разрешать системе устанавливать zero вставки, поэтому панель вкладок не будет прыгать.

0 голосов
/ 10 февраля 2019

Вы можете переопределить метод - (UIEdgeInsets)safeAreaInsets для нескольких подрывных операций iOS 12 с помощью этого:

- (UIEdgeInsets)safeAreaInsets {
    UIEdgeInsets insets = [super safeAreaInsets];
    CGFloat h = CGRectGetHeight(self.frame);
    if (insets.bottom >= h) {
        insets.bottom = [self.window safeAreaInsets].bottom;
    }
    return insets;
}
0 голосов
/ 20 ноября 2018

Я столкнулся с точно такой же проблемой, когда приложение было спроектировано с одним контроллером навигации на вкладку. Самым простым нехакерским способом, который я нашел, чтобы это исправить, было поместить UITabBarController внутрь UINavigationController и удалить отдельных UINavigationController s.

До:

                   -> UINavigationController -> UIViewController
                   -> UINavigationController -> UIViewController
UITabBarController -> UINavigationController -> UIViewController
                   -> UINavigationController -> UIViewController
                   -> UINavigationController -> UIViewController

После того, как:

                                             -> UIViewController
                                             -> UIViewController
UINavigationController -> UITabBarController -> UIViewController
                                             -> UIViewController
                                             -> UIViewController

Используя внешний UINavigationController, вам не нужно скрывать UITabBar при помещении контроллера вида в стек навигации.

Оговорка:

Единственная проблема, которую я до сих пор обнаружил, заключается в том, что установка элементов заголовка или кнопок правой / левой панели на каждом UIViewController не имеет такого же эффекта. Чтобы преодолеть эту проблему, я применил изменения через UITabBarControllerDelegate, когда изменилось видимое UIViewController.

func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
    guard let topItem = self.navigationController?.navigationBar.topItem else { return }
    precondition(self.navigationController == viewController.navigationController, "Navigation controllers do not match. The following changes might result in unexpected behaviour.")
    topItem.title = viewController.title
    topItem.titleView = viewController.navigationItem.titleView
    topItem.leftBarButtonItem = viewController.navigationItem.leftBarButtonItem
    topItem.rightBarButtonItem = viewController.navigationItem.rightBarButtonItem
}

Обратите внимание, что я добавил preconditionFailure, чтобы поймать любой случай, когда архитектура навигации была изменена

0 голосов
/ 07 декабря 2018

Apple исправила это в iOS 12.1.1

0 голосов
/ 06 ноября 2018

В вашем UITabBarController установите isTranslucent = false

0 голосов
/ 15 ноября 2018

вот быстрый код

extension UIApplication {
open override var next: UIResponder? {
    // Called before applicationDidFinishLaunching
    SwizzlingHelper.enableInjection()
    return super.next
}

}

класс SwizzlingHelper {

static func enableInjection() {
    DispatchQueue.once(token: "com.SwizzlingInjection") {
        //what to need inject
        UITabbarButtonInjection.inject()
    }

} больше информации https://github.com/tonySwiftDev/UITabbar-fixIOS12.1Bug

0 голосов
/ 05 ноября 2018

Спасибо за идею @ ElonChan , Я просто изменил встроенную функцию c на статический метод OC, так как я не буду слишком часто использовать это overrideImplementation. Кроме того, этот фрагмент теперь был настроен на iPhoneX.

static CGFloat const kIPhoneXTabbarButtonErrorHeight = 33;
static CGFloat const kIPhoneXTabbarButtonHeight = 48;


@implementation FixedTabBar


typedef void(^NewTabBarButtonFrameSetter)(UIView *, CGRect);
typedef NewTabBarButtonFrameSetter (^ImpBlock)(Class originClass, SEL originCMD, IMP originIMP);


+ (BOOL)overrideImplementationWithTargetClass:(Class)targetClass targetSelector:(SEL)targetSelector implementBlock:(ImpBlock)implementationBlock {
    Method originMethod = class_getInstanceMethod(targetClass, targetSelector);
    if (!originMethod) {
        return NO;
    }
    IMP originIMP = method_getImplementation(originMethod);
    method_setImplementation(originMethod, imp_implementationWithBlock(implementationBlock(targetClass, targetSelector, originIMP)));
    return YES;
}


+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (@available(iOS 12.1, *)) {
            [self overrideImplementationWithTargetClass:NSClassFromString(@"UITabBarButton")
                                         targetSelector:@selector(setFrame:)
                                         implementBlock:^NewTabBarButtonFrameSetter(__unsafe_unretained Class originClass, SEL originCMD, IMP originIMP) {
                return ^(UIView *selfObject, CGRect firstArgv) {
                    if ([selfObject isKindOfClass:originClass]) {
                        if (!CGRectIsEmpty(selfObject.frame) && CGRectIsEmpty(firstArgv)) {
                            return;
                        }
                        if (firstArgv.size.height == kIPhoneXTabbarButtonErrorHeight) {
                            firstArgv.size.height = kIPhoneXTabbarButtonHeight;
                        }
                    }
                    void (*originSelectorIMP)(id, SEL, CGRect);
                    originSelectorIMP = (void (*)(id, SEL, CGRect))originIMP;
                    originSelectorIMP(selfObject, originCMD, firstArgv);
                };
            }];
        }
    });
}

@end
0 голосов
/ 02 ноября 2018

Вот решение, которое может обрабатывать элементы поворота и панели вкладок, добавляемые или удаляемые:

class FixedTabBar: UITabBar {

    var buttonFrames: [CGRect] = []
    var size: CGSize = .zero

    override func layoutSubviews() {
        super.layoutSubviews()

        if UIDevice.current.systemVersion >= "12.1" {
            let buttons = subviews.filter {
                String(describing: type(of: $0)).hasSuffix("Button")
            }
            if buttonFrames.count == buttons.count, size == bounds.size {
                zip(buttons, buttonFrames).forEach { $0.0.frame = $0.1 }
            } else {
                buttonFrames = buttons.map { $0.frame }
                size = bounds.size
            }
        }
    }
}
0 голосов
/ 02 ноября 2018

есть два способа решить эту проблему, Во-первых, в вашем UITabBarController установите isTranslucent = false, например:

[[UITabBar appearance] setTranslucent:NO];

во-вторых, если первое решение не исправляет ваш вопрос, попробуйте так:

вот код Objective-C

// .h
@interface CYLTabBar : UITabBar
@end 

// .m
#import "CYLTabBar.h"

CG_INLINE BOOL
OverrideImplementation(Class targetClass, SEL targetSelector, id (^implementationBlock)(Class originClass, SEL originCMD, IMP originIMP)) {
   Method originMethod = class_getInstanceMethod(targetClass, targetSelector);
   if (!originMethod) {
       return NO;
   }
   IMP originIMP = method_getImplementation(originMethod);
   method_setImplementation(originMethod, imp_implementationWithBlock(implementationBlock(targetClass, targetSelector, originIMP)));
   return YES;
}
@implementation CYLTabBar

+ (void)load {

   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^{
       if (@available(iOS 12.1, *)) {
           OverrideImplementation(NSClassFromString(@"UITabBarButton"), @selector(setFrame:), ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP originIMP) {
               return ^(UIView *selfObject, CGRect firstArgv) {

                   if ([selfObject isKindOfClass:originClass]) {

                       if (!CGRectIsEmpty(selfObject.frame) && CGRectIsEmpty(firstArgv)) {
                           return;
                       }
                   }

                   // call super
                   void (*originSelectorIMP)(id, SEL, CGRect);
                   originSelectorIMP = (void (*)(id, SEL, CGRect))originIMP;
                   originSelectorIMP(selfObject, originCMD, firstArgv);
               };
           });
       }
   });
}
@end

Дополнительная информация: https://github.com/ChenYilong/CYLTabBarController/commit/2c741c8bffd47763ad2fca198202946a2a63c4fc

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...