UISearchBar height on iOS8 when showsScopeBar=YES

2019-02-03 13:22发布

问题:

I'm using UISearchBar in my app, with showsScopeBar=YES. When running under iOS8 (both in the simulator and on a device) the scope bar is hidden and the search bar's height remains at 44 instead of the expected 88. Using the new view debugger in Xcode 6 I can see that the scope bar is actually present, but remains hidden behind the text field.

The only way I've found so far is to manually set the search bar's height to 88, which of course is a terrible hack.

Am I missing some documented incompatibility, or is this a bug?

回答1:

I ran into this problem too. After searching on Apples developer forum I found this thread: https://devforums.apple.com/thread/235803?start=0&tstart=0

And apparently the SearchBar don't automatically does a sizeToFit when it's supposed too. So it's height stays at 44 instead of adjusting to the scope buttons. The bug is not fixed in the iOS8 GM.

I did a simple [self.searchBar sizeToFit] in my viewWillAppear: and that solved it.



回答2:

This issue is occurring in the iOS 8 release version as well. I added these 2 lines in my viewWillAppear: and that solved it.

- (void)adjustSearchBarToShowScopeBar{ [self.searchBar sizeToFit]; self.tableView.tableHeaderView = self.searchBar; } Just adding [self.searchBar sizeToFit] was covering up my tableview's first row. Just refreshing the tableview header fixed the issue perfectly.



回答3:

This seems to be not an iOS 8 bug but a Xcode 6 GM compiled Storyboard bug as it happens on iOS 6/7 as well.

As suggested it is fixed by calling sizeToFit on the search bar in viewWillAppear.

If you want to do it from a view instead of a controller you can try to place it inside willMoveToWindow.


This bug seems to affect Xcode 5.x builds on iOS 8 and Xcode 6 GM builds on all systems.



回答4:

Using Janne's answer, I thought it would be helpful to share how to do this automatically with method swizzling.

@implementation UISearchBar (iOS8)

static dispatch_once_t dispatchOnceToken;

+ (void)load {
    if([[[UIDevice currentDevice] systemVersion] floatValue] >= 8)
    {
        dispatch_once(&dispatchOnceToken, ^{
            Class class = [self class];

            SEL originalViewWillAppearSelector = @selector(layoutSubviews);
            SEL swizzledViewWillAppearSelector = @selector(swizzled_layoutSubviews);

            Method originalViewWillAppearMethod = class_getInstanceMethod(class, originalViewWillAppearSelector);
            Method swizzledViewWillAppearMethod = class_getInstanceMethod(class, swizzledViewWillAppearSelector);

            if(class_addMethod(class, originalViewWillAppearSelector, method_getImplementation(swizzledViewWillAppearMethod), method_getTypeEncoding(swizzledViewWillAppearMethod)))
            {
                class_replaceMethod(class, swizzledViewWillAppearSelector, method_getImplementation(originalViewWillAppearMethod), method_getTypeEncoding(originalViewWillAppearMethod));
            }
            else
            {
                method_exchangeImplementations(originalViewWillAppearMethod, swizzledViewWillAppearMethod);
            }
        });
    }
}

- (void)swizzled_layoutSubviews
{
    [self swizzled_layoutSubviews];
    [self sizeToFit];
}

@end