[ios] iOS11의 이상한 uitableview 동작. 탐색 푸시 애니메이션과 함께 셀이 위로 스크롤됩니다.

최근에 일부 코드를 새로운 iOS 11 베타 5 SDK로 마이그레이션했습니다.

이제 UITableView에서 매우 혼란스러운 동작을 얻습니다. tableview 자체는 그렇게 화려하지 않습니다. 사용자 지정 셀이 있지만 대부분의 경우 높이입니다.

내 뷰 컨트롤러를 tableview와 함께 누르면 셀이 “스크롤 업”(또는 전체 테이블 뷰 프레임이 변경됨) 및 푸시 / 팝 탐색 애니메이션을 따라 아래로 이동하는 추가 애니메이션이 표시됩니다. gif를 참조하십시오 :

물결 모양의 tableview

나는 수동으로 만들 tableviewloadView있는 tableview의 슈퍼 뷰의 선도, 뒤, 위, 아래 동일하게 방법 및 설정 자동 레이아웃 제약. 수퍼 뷰는 뷰 컨트롤러의 루트 뷰입니다.

뷰 컨트롤러 푸시 코드는 매우 표준 적입니다. self.navigationController?.pushViewController(notifVC, animated: true)

동일한 코드가 iOS 10에서 정상적인 동작을 제공합니다.

무엇이 잘못되었는지 알려주시겠습니까?

편집 : 매우 간단한 테이블 뷰 컨트롤러를 만들었으며 동일한 동작을 재현 할 수 있습니다. 암호:

class VerySimpleTableViewController : UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
    }


    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 4
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

        cell.textLabel?.text = String(indexPath.row)
        cell.accessoryType = .disclosureIndicator

        return cell
    }


    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)

        let vc = VerySimpleTableViewController.init(style: .grouped)

        self.navigationController?.pushViewController(vc, animated: true)
    }
}

편집 2 : UINavigationBar의 사용자 지정으로 문제를 좁힐 수있었습니다. 다음과 같은 사용자 정의가 있습니다.

rootNavController.navigationBar.setBackgroundImage(createFilledImage(withColor: .white, size: 1), for: .default)

여기서 createFilledImage주어진 크기와 색상 사각형 이미지를 만듭니다.

이 줄을 주석 처리하면 정상적인 동작으로 돌아갑니다.

이 문제에 대한 의견을 부탁드립니다.



답변

이는 UIScrollView's (UITableView는 UIScrollview의 하위 클래스 임)contentInsetAdjustmentBehavior속성으로 .automatic인해 기본적으로 설정되어 있기 때문 입니다.

영향을받는 컨트롤러의 viewDidLoad에서 다음 스 니펫으로이 동작을 재정의 할 수 있습니다.

    tableView.contentInsetAdjustmentBehavior = .never

https://developer.apple.com/documentation/uikit/uiscrollview/2902261-contentinsetadjustmentbehavior


답변

Maggy의 답변 외에도

목표 -C

if (@available(iOS 11.0, *)) {
    scrollViewForView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}

이 문제는 safeAreaInsetsiOS 11.2에서 수정되어야하는 탐색 전환 중에보기 컨트롤러의보기가 잘못 설정된 iOS 11의 버그로 인해 발생했습니다 . 를 설정
contentInsetAdjustmentBehavior하는 것은 .never그 가능성이 다른 바람직하지 않은 부작용이 있기 때문에 좋은 해결 방법이 아니다. 해결 방법을 사용하는 경우 iOS 버전> = 11.2에 대해 제거해야합니다.

-smileyborg (Apple의 소프트웨어 엔지니어)가 언급 함


답변

예를 들어 didFinishLaunchingWithOptions에서 NSProxy를 사용하여 애플리케이션 전체에서이 동작을 한 번에 편집 할 수 있습니다.

if (@available(iOS 11.0, *)) {
      [UIScrollView appearance].contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
} 


답변

iOS 11에서 자동으로 삽입을 설정하도록 허용하면서이 문제를 해결하는 방법은 다음과 같습니다 . 나는 UITableViewController.

  • 스토리 보드의 뷰 컨트롤러 (또는 프로그래밍 방식 ) 에서 “상단 막대 아래 가장자리 확장”및 “불투명 막대 아래 가장자리 확장”을 선택합니다 . 안전 영역 삽입은보기가 상단 표시 줄 아래로 들어가는 것을 방지합니다.
  • 스토리 보드의 테이블보기에서 “안전 영역에 삽입”단추를 확인하십시오. (또는 tableView.insetsContentViewsToSafeArea = true)-이것은 필요하지 않을 수도 있지만 내가 한 일입니다.
  • 콘텐츠 삽입 조정 동작을 “Scrollable Axes”(또는 tableView.contentInsetAdjustmentBehavior = .scrollableAxes)로 설정합니다. .always작동 할 수도 있지만 테스트하지는 않았습니다.

다른 모든 방법이 실패 할 경우 시도 할 다른 한 가지 :

viewSafeAreaInsetsDidChange UIViewController스크롤보기 삽입을 안전 영역 삽입으로 강제 설정하도록 테이블보기를 가져 오는 메서드를 재정의 합니다. 이것은 Maggy의 대답의 ‘Never’설정과 관련됩니다.

- (void)viewSafeAreaInsetsDidChange {
    [super viewSafeAreaInsetsDidChange];
    self.tableView.contentInset = self.view.safeAreaInsets;
}

참고 : self.tableViewself.view에 같은 일해야한다UITableViewController


답변

이것은 의도 된 동작보다 버그처럼 보입니다. 내비게이션 바가 반투명하지 않거나 배경 이미지가 설정되어있을 때 발생합니다.

contentInsetAdjustmentBehavior를 .never로 설정하면 콘텐츠 삽입이 iPhone X에서 올바르게 설정되지 않습니다. 예를 들어 콘텐츠가 스크롤바 아래의 하단 영역으로 이동합니다.

다음 두 가지 작업을 수행해야합니다.
1. 푸시 / 팝시 scrollView 애니메이션을 방지합니다
. 2. iPhone X에 필요하므로 .automatic 동작을 유지합니다.이 기능이 없으면 예를 들어 세로 모드에서 콘텐츠가 하단 스크롤바 아래로 이동합니다.

새로운 간단한 솔루션 : XIB : 상단, 선행 및 후행을 superview로 설정하고 높이를 0으로 설정하여 기본보기 위에 새 UIView를 추가하기 만하면됩니다. 다른 하위보기 나 다른 항목에 연결할 필요가 없습니다.

이전 솔루션 :

참고 : 가로 모드에서 UIScrollView를 사용하는 경우 여전히 가로 삽입을 올바르게 설정하지 않으므로 (다른 버그?) scrollView의 선행 / 후행을 IB의 safeAreaInsets에 고정해야합니다.

참고 2 : 아래의 해결 방법은 tableView가 하단으로 스크롤되고 컨트롤러를 밀고 다시 팝하면 더 이상 하단에 있지 않는 문제가 있습니다.

override func viewDidLoad()
{
    super.viewDidLoad()

    // This parts gets rid of animation when pushing
    if #available(iOS 11, *)
    {
        self.tableView.contentInsetAdjustmentBehavior = .never
    }
}

override func viewDidDisappear(_ animated: Bool)
{
    super.viewDidDisappear(animated)
    // This parts gets rid of animation when popping
    if #available(iOS 11, *)
    {
        self.tableView.contentInsetAdjustmentBehavior = .never
    }
}

override func viewDidAppear(_ animated: Bool)
{
    super.viewDidAppear(animated)
    // This parts sets correct behaviour(insets are correct on iPhone X)
    if #available(iOS 11, *)
    {
        self.tableView.contentInsetAdjustmentBehavior = .automatic
    }
}


답변

iOS 11.1에서 버그를 재현 할 수 있지만 iOS 11.2부터 버그가 수정 된 것 같습니다. http://openradar.appspot.com/34465226 참조


답변

위의 코드와 함께 다음과 같이 추가 코드를 추가하십시오. 문제를 해결했습니다

override func viewDidLayoutSubviews() {
     super.viewDidLayoutSubviews()
     tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) // print(thisUISBTV.adjustedContentInset) 
}