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


116

최근에 일부 코드를 새로운 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주어진 크기와 색상 사각형 이미지를 만듭니다.

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

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


탐색 모음의 사용자 정의와 관련된 문제가 아닐 수 있습니다. 나는 사용자 정의없이 동일한 문제를 겪고있었습니다 (허용되는 대답이 이것을 해결했습니다). UITableViewController를 사용하는 대신 하위보기로 수동으로 생성 될 때 iOS가 tableview를 처리하는 방식에 문제가 될 수 있다고 생각합니다.
마크 레너드

2
내가 설정 한 경우에만이 문제를보고 있어요 navigationBar.isTranslucent에를 false, 그렇지 않으면 벌금을 작동합니다.
b_ray

5
이것은 iOS11 GM의 버그 인 것 같습니다.이 문제가 Apple로부터주의를 끌 수 있도록 해당 버그 보고서를 속이십시오
b_ray

1
이 문제는 iOS 11.2 베타에서 수정 된 것으로 보입니다. contentInsetAdjustmentBehavior를 절대로 설정하지 않을 것입니다. 화면 하단에 패딩을 제공하지 않아 iPhone X 스크롤 뷰가 깨지기 때문입니다. 콘텐츠보기 하단은 iPhone X의 홈 "버튼"아래에 있습니다.
batu '

답변:


150

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

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

    tableView.contentInsetAdjustmentBehavior = .never

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


2
UIScrollViewContentInsetAdjustmentBehavior.automatic의 정의에 대한이 주석은 다음과 같이 말합니다. "... 스크롤 여부에 관계없이 탐색 컨트롤러 내에서 automaticAdjustsScrollViewInsets = YES가있는 뷰 컨트롤러가 스크롤 뷰를 소유 할 때 이전 버전과의 호환성을 위해 top & bottom contentInset도 조정합니다. 보기는 스크롤 가능합니다. " 내 이론은 내비게이션 바의 contentInset이 배경 이미지를 설정함으로써 영향을 받고 동적으로 조정된다는 것입니다.
Maggy Hillen

8
스토리 보드로도 할 수 있습니다. 크기 검사기-> 콘텐츠 삽입-> '안함'으로 설정합니다.
Woongbi 김

4
콘텐츠가 탭 막대 뒤로 확장되면 비활성화 tableView.contentInsetAdjustmentBehavior하면 삽입이 깨집니다.
kean

4
또한이 기능을 비활성화하면 iPhone X의 (상단 기즈모) 뒤에 가로로 스크롤 표시기가 배치됩니다. 이 동작의 요점은 스크롤 뷰의 콘텐츠 영역을 조정하여 직사각형이 아닌 화면에 표시되도록하는 것입니다. 현재 iPhone X Sim에서만 볼 수 있다고 생각합니다.
PhoneyDeveloper

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

23

Maggy의 답변 외에도

목표 -C

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

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

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


6

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

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

1
이것은 UIImagePickerController와 같은 시스템의 컨트롤러를 망가뜨릴 것입니다
galway

6

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


이 스레드에서 거의 모든 것을 시도했으며 이것은 나를 위해 일했습니다. TabBarVC에 포함 된 TableViewVC. 감사합니다!
Josh Wolff

3

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

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
    }
}

parentView 란 무엇입니까?
PhoneyDeveloper

보기 컨트롤러의 기본보기, 답변을 업데이트했습니다. 고마워.
El Horrible

UITableViewController를 사용할 때 tableView는 뷰 컨트롤러의 뷰입니다. 또한 장치를 회전 할 때 삽입도 달라야합니다. 조정을 원합니다. tableView가 처음 나타날 때 애니메이션이 마음에 들지 않습니다.
PhoneyDeveloper 2017 년

귀하의 경우에는 UITableView가 컨트롤러의 뷰이므로 safeAreaInsets.bottom = 34 (세로) 여야하므로 tableView.contentInset = tableView.safeAreaInsets를 설정할 수 있습니다.
El Horrible

그것은 나를 위해 작동하지 않습니다. viewDidLoad에서 모든 삽입은 0입니다. viewWillLayoutSubviews에서 해당 코드를 사용하려고하면 스크롤 표시기가 삽입되지만 tableView 자체는 가로로 스크롤 할 수있게됩니다. 조정을 비활성화하지 않고 viewWillLayoutSubviews의 삽입물을 보면 하단 adjustContentInset은 21이되고 그게 전부 변경되는 것 같습니다.
PhoneyDeveloper


2

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

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

이것만으로도 문제가 해결되었습니다 !! 감사합니다. 이 문제에 너무 많은 시간을 낭비했습니다!
무라트 Yasar

2

또한 탭 바를 사용하는 경우 컬렉션보기의 하단 내용 삽입은 0이됩니다. 이를 위해 viewDidAppear에 아래 코드를 넣으십시오.

if #available(iOS 11, *) {
    tableView.contentInset = self.collectionView.safeAreaInsets
}

2

제 경우에는 이것이 작동했습니다 (viewDidLoad에 넣으십시오).

self.navigationController.navigationBar.translucent = YES;

1

collectionView또는 상단의 추가 공간 제거tableView

    if #available(iOS 11.0, *) {
        collectionView.contentInsetAdjustmentBehavior  = .never
        //tableView.contentInsetAdjustmentBehavior  = .never
    } else {
        automaticallyAdjustsScrollViewInsets = false
    }

코드 위 collectionView또는 tableView탐색 모음 아래로 이동합니다.
아래 코드는 컬렉션 뷰가 탐색 아래로 이동하는 것을 방지합니다.

    self.edgesForExtendedLayout = UIRectEdge.bottom

하지만 UICollectionView에 대한 논리와 코드를 사용하는 것을 좋아합니다.

모서리 삽입 값이 사각형에 적용되어 해당 사각형이 나타내는 영역을 축소하거나 확장합니다. 일반적으로 모서리 삽입은 뷰 레이아웃 중에 뷰의 프레임을 수정하는 데 사용됩니다. 양수 값은 프레임이 지정된 양만큼 삽입 (또는 축소)되도록합니다. 음수 값은 프레임이 지정된 양만큼 시작 (또는 확장)되도록합니다.

collectionView.contentInset = UIEdgeInsets(top: -30, left: 0, bottom: 0, right: 0)
//tableView.contentInset = UIEdgeInsets(top: -30, left: 0, bottom: 0, right: 0)

UICollectionView를 위한 가장 좋은 방법

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return UIEdgeInsets(top: -30, left: 0, bottom: 0, right: 0)
}

0

이 코드를 삭제하십시오.

self.edgesForExtendedLayout = UIRectEdgeNone

0
  if #available(iOS 11, *) {
        self.edgesForExtendedLayout = UIRectEdge.bottom
  }

테이블보기가있는 사용자 지정 resultsControllers와 함께 UISearchController를 사용하고있었습니다. 결과 컨트롤러에 새 컨트롤러를 푸시하면 tableview가 검색됩니다.

위에 나열된 코드가 문제를 완전히 해결했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.