Programing

UISearchDisplayController가 탐색 모음을 숨기지 못하도록 방지

crosscheck 2020. 11. 16. 07:50
반응형

UISearchDisplayController가 탐색 모음을 숨기지 못하도록 방지


사용자가 UISearchDisplayController의 검색 표시 줄 편집을 시작할 때마다 검색 컨트롤러가 활성화되고 검색 테이블보기를 표시하는 동안보기의 탐색 표시 줄을 숨 깁니다. UISearchDisplayController에서 다시 구현하지 않고 탐색 모음을 숨기는 것을 방지 할 수 있습니까?


UISearchControlleriOS 8에 도입 된 새 클래스 hidesNavigationBarDuringPresentation에는 탐색 모음을 계속 표시하려면 false로 설정할 수 있는 속성 이 있습니다 (기본적으로 숨겨져 있음).


방금 UISearchDisplayController로 약간 디버깅 한 결과 UINavigationController에서 개인 메서드를 호출하여 탐색 모음을 숨기는 것을 발견했습니다. 이것은 -setActive : animated :에서 발생합니다. UISearchDisplayController를 하위 클래스로 만들고이 메서드를 다음 코드로 덮어 쓰면 navigationBar가 이미 숨겨져있는 것처럼 위장하여 숨겨지는 것을 방지 할 수 있습니다.

- (void)setActive:(BOOL)visible animated:(BOOL)animated;
{
    if(self.active == visible) return;
    [self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
    [super setActive:visible animated:animated];
    [self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
    if (visible) {
        [self.searchBar becomeFirstResponder];
    } else {
        [self.searchBar resignFirstResponder];
    }   
}

이것이 당신에게 효과가 있는지 알려주십시오. 나는 또한 이것이 향후 iOS 버전에서 깨지지 않기를 바랍니다. iOS 4.0에서만 테스트되었습니다.


가장 간단한 솔루션이며 해킹이 없습니다.

@interface MySearchDisplayController : UISearchDisplayController

@end

@implementation MySearchDisplayController

- (void)setActive:(BOOL)visible animated:(BOOL)animated
{
    [super setActive: visible animated: animated];

    [self.searchContentsController.navigationController setNavigationBarHidden: NO animated: NO];
}

@end

위의 답변은 저에게 적합하지 않았습니다. 내 해결책은 UISearchDisplayController를 속여 UINavigationController가 없다고 생각하는 것입니다.

뷰 컨트롤러에서 다음 메서드를 추가하십시오.

- (UINavigationController *)navigationController {
    return nil;
}

정말 나쁜 생각처럼 보였음에도 불구하고 이것은 나에게 부적합한 부작용이 없었습니다. 네비게이션 컨트롤러에 가야한다면 [super navigationController].


iOS 8.0부터 UISearchControllerself.searchController.hidesNavigationBarDuringPresentation속성을 false 로 설정하여 동일한 동작을 수행 할 수 있습니다 .

Swift의 코드는 다음과 같습니다.

searchController.hidesNavigationBarDuringPresentation = false

UISearchDisplayController를 서브 클래 싱하지 않고 다른 방법으로 시도했습니다. UISearchDisplayController에 대한 대리자를 설정 한 UIViewController 클래스에서 searchDisplayControllerDidBeginSearch를 구현하고 사용을 추가하십시오.

[self.navigationController setNavigationBarHidden:NO animated:YES];

나를 위해 속임수를 썼습니다.


나는 약간 다른 문제를 해결하면서 이것을 만났습니다. UISearchDisplayController를 사용하는 동안 검색 막대가 탐색 막대 (아래가 아님) 에 있기 원합니다 .

탐색 표시 줄에 검색 표시 줄을 배치하는 것은 어렵지 않습니다 ( UISearchBar 및 UINavigationItem 참조 ). 그러나 UISearchDisplayController는 검색 표시 줄이 항상 내비게이션 표시 줄 아래에 있다고 가정하고 (여기에 설명 된대로) 검색을 입력 할 때 내비게이션 표시 줄을 숨기도록 고집하므로 상황이 끔찍해 보입니다. 또한 UISearchDisplayController는 검색 창을 평소보다 더 밝게합니다.

해결책을 찾았습니다. 트릭은 (반 직관적으로) UISearchDisplayController가 UISearchBar를 전혀 제어하지 못하도록하는 것입니다. xibs를 사용하는 경우 이는 검색 창 인스턴스를 삭제하거나 적어도 콘센트를 분리하는 것을 의미합니다. 그런 다음 고유 한 UISearchBar를 만듭니다.

- (void)viewDidLoad
{
    [super viewDidLoad];

    UISearchBar *searchBar = [[[UISearchBar alloc] init] autorelease];
    [searchBar sizeToFit]; // standard size
    searchBar.delegate = self;

    // Add search bar to navigation bar
    self.navigationItem.titleView = searchBar;
}

You will need to manually activate the search display controller when the user taps the search bar (in -searchBarShouldBeginEditing:) and manually dismiss the search bar when the user ends searching (in -searchDisplayControllerWillEndSearch:).

#pragma mark <UISearchBarDelegate>

- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
    // Manually activate search mode
    // Use animated=NO so we'll be able to immediately un-hide it again
    [self.searchDisplayController setActive:YES animated:NO];

    // Hand over control to UISearchDisplayController during the search
    searchBar.delegate = (id <UISearchBarDelegate>)self.searchDisplayController;

    return YES;
}

#pragma mark <UISearchDisplayDelegate>

- (void) searchDisplayControllerDidBeginSearch:(UISearchDisplayController
*)controller {
    // Un-hide the navigation bar that UISearchDisplayController hid
    [self.navigationController setNavigationBarHidden:NO animated:NO];
}

- (void) searchDisplayControllerWillEndSearch:(UISearchDisplayController
*)controller {
    UISearchBar *searchBar = (UISearchBar *)self.navigationItem.titleView;

    // Manually resign search mode
    [searchBar resignFirstResponder];

    // Take back control of the search bar
    searchBar.delegate = self;
}

Really nice solution, but it was crashing my app under iOS6. I had to make the following modification to get it work.

@implementation ICSearchDisplayController

    - (void)setActive:(BOOL)visible animated:(BOOL)animated
    {
        if (visible == YES) {
            [super setActive:visible animated:animated];
            [self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
        } else {
            [super setActive:NO animated:NO];
        }
    }

This seem to solve it for me. Tested in both iOS5/6.1. No visual issues that I could see.

- (void)viewDidAppear
{
    [super viewDidAppear];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillAppear:) name:UIKeyboardWillShowNotification object:nil];
}

-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)keyboardWillAppear:(NSNotification *)notification
{
    [self.navigationController setNavigationBarHidden:NO animated:NO];
}

-(void)viewDidLayoutSubviews{
    [self.navigationController setNavigationBarHidden:NO animated:NO];
}

iOS 7 screws things up a bit... for me this worked perfectly:

/**
 *  Overwrite the `setActive:animated:` method to make sure the UINavigationBar 
 *  does not get hidden and the SearchBar does not add space for the statusbar height.
 *
 *  @param visible   `YES` to display the search interface if it is not already displayed; NO to hide the search interface if it is currently displayed.
 *  @param animated  `YES` to use animation for a change in visible state, otherwise NO.
 */
- (void)setActive:(BOOL)visible animated:(BOOL)animated
{
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
    [self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];

    [super setActive:visible animated:animated];

    [self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
    [[UIApplication sharedApplication] setStatusBarHidden:NO];
}

The reason for show/hide the statusbar


I think the best solution is to implement the UISearchDisplayController yourself.

It's not that difficult. You only need to implement UISearchBarDelegate for your UIViewController and include a UITableView to display your search results.


@Pavel's works perfectly well. However, I was trying to get this into a UIPopoverController and the text in the field gets pushed slightly when the search bar's text field becomes the first responder, and that looks a bit ugly, so I fixed it by calling the super method with animated set to NO.


As jrc pointed out "unhook UISearchDisplayController from controlling any UISearchBar" seems to work for me. If I pass nil as a parameter when creating UISearchDisplayController the navigation bar stays visible at all times:

searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:nil contentsController:self];

I was adding custom navigation bar on my ViewController which was getting hidden on search, a quick but not so good fix was

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
    [self.view addSubview:_navBar];
}

_navBar is UINavigationBar added programmatically, doing this helped me navigation bar from hiding.


Just wanted to add to stigi answer. When you cancel search and start search again - search results table won't be react to touches so you need to add next line

self.searchResultsTableView.alpha = 1;

So updated code looks next way

 - (void)setActive:(BOOL)visible animated:(BOOL)animated;
 {
    if(self.active == visible) return;
    if (visible) {
        [self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
        [super setActive:visible animated:animated];
        [self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
        self.searchResultsTableView.alpha = 1;
        [self.searchBar becomeFirstResponder];
    } else {
        [super setActive:visible animated:animated];
        [self.searchBar resignFirstResponder];
    }
}

참고URL : https://stackoverflow.com/questions/2813118/prevent-a-uisearchdisplaycontroller-from-hiding-the-navigation-bar

반응형