code

UITableViewCell이 빠르게 뒤로 스 와이프해도 선택 해제되지 않습니다.

codestyles 2020. 12. 7. 08:10
반응형

UITableViewCell이 빠르게 뒤로 스 와이프해도 선택 해제되지 않습니다.


이제 세 가지 앱을 iOS 7로 업데이트했지만 세 앱 모두 코드를 공유하지 않음에도 불구하고 사용자가 뒤로 버튼을 누르는 대신 내비게이션 컨트롤러에서 빠르게 돌아갈 수있는 문제가 있습니다. , 셀은 선택된 상태로 유지됩니다.

세 앱의 경우 하나는 프로그래밍 방식으로 만든 사용자 지정 셀을 사용하고 다른 하나는 스토리 보드에서 만든 사용자 지정 셀을 사용하고 세 번째 앱은 스토리 보드에서도 UITableView의 매우 기본적인 하위 클래스에있는 기본 셀을 사용합니다. 세 가지 경우 모두 셀은 스스로 선택을 취소하지 않습니다. 사용자가 천천히 스 와이프하거나 뒤로 버튼을 누르면 정상적으로 선택 해제됩니다.

이것은 내 iOS 7 앱에서만 발생하며, Apple의 자체 앱 및 iOS 7 용으로 업그레이드 된 타사 앱은 모두 정상적으로 작동하는 것 같습니다 (셀 선택 해제 속도에 약간의 차이가 있음).

내가 뭘 잘못하고있는 게 분명한데 뭔지 모르겠어?


나는 지금 같은 문제를 다루고 있습니다. Apple UICatalog 샘플은 더러운 솔루션을 가져 오는 것 같습니다.

정말 저를 전혀 행복하게하지 않습니다. 앞에서 언급했듯이 [self.tableView deselectRowAtIndexPath:tableSelection animated:NO];현재 선택된 행을 선택 취소하는 데 사용 합니다.

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

    // this UIViewController is about to re-appear, make sure we remove the current selection in our table view
    NSIndexPath *tableSelection = [self.tableView indexPathForSelectedRow];
    [self.tableView deselectRowAtIndexPath:tableSelection animated:NO];

    // some over view controller could have changed our nav bar tint color, so reset it here
    self.navigationController.navigationBar.tintColor = [UIColor darkGrayColor];
}

샘플 코드는 IOS 7 iOS 8 iOS 9 iOS 10 지원


나를 혼란스럽게하는 것은 UITableViewController Class Reference입니다 .

테이블 뷰가 처음로드 될 때 나타나려고 할 때 테이블 뷰 컨트롤러는 테이블 뷰의 데이터를 다시로드합니다. 또한 테이블 뷰가 표시 될 때마다 선택 항목 (요청에 따라 애니메이션 포함 또는 제외)을 지 웁니다. UITableViewController클래스는 슈퍼 클래스의 방법이 구현 viewWillAppear:. clearsSelectionOnViewWillAppear속성 의 값을 변경하여이 동작을 비활성화 할 수 있습니다 .

이것이 내가 기대하는 동작과 정확히 일치하지만 작동하지 않는 것 같습니다. 당신도 나도 마찬가지입니다. 우리는 정말로 "더러운"해결책을 사용해야하고 우리 스스로해야합니다.


이것은 나를 위해 가장 잘 작동했습니다.

- (void)viewDidLoad {
    [super viewDidLoad];
    self.clearsSelectionOnViewWillAppear = NO;
}

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:animated];
}

천천히 뒤로 스 와이프하는 동안 훨씬 더 나은 선택 해제 페이딩을 얻었습니다.


Fabio의 대답은 잘 작동하지만 사용자가 약간 스 와이프 한 다음 마음이 바뀌면 올바른 모양을 제공하지 않습니다. 이 경우를 올바르게하려면 선택한 인덱스 경로를 저장하고 필요할 때 재설정해야합니다.

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    self.savedSelectedIndexPath = nil;
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    if (self.savedSelectedIndexPath) {
        [self.tableView selectRowAtIndexPath:self.savedSelectedIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
    }
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    self.savedSelectedIndexPath = self.tableView.indexPathForSelectedRow;

    if (self.savedSelectedIndexPath) {
        [self.tableView deselectRowAtIndexPath:self.savedSelectedIndexPath animated:YES];
    }
}

UITableViewController를 사용하는 경우 기본 제공 지우기를 비활성화해야합니다.

self.clearsSelectionOnViewWillAppear = NO;

savedSelectedIndexPath에 대한 속성을 추가합니다.

@property(strong, nonatomic) NSIndexPath *savedSelectedIndexPath;

몇 가지 다른 클래스에서이 작업을 수행해야하는 경우 헬퍼에서 분할하는 것이 좋습니다. 예를 들어이 요점에서 한 것처럼 https://gist.github.com/rhult/46ee6c4e8a862a8e66d4


이 솔루션은 전환 조정자와 함께 행 선택 취소를 애니메이션 (사용자 주도 VC 해제의 경우)하고 사용자가 전환을 취소하면 선택을 다시 적용합니다. Swift의 Caleb Davenport 의 솔루션에서 수정되었습니다 . iOS 9에서만 테스트되었습니다. 사용자 주도 (스 와이프) 전환과 이전 스타일의 "뒤로"버튼 탭 모두에서 작동하는 것으로 테스트되었습니다.

에서 UITableViewController서브 클래스 :

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

    // Workaround. clearsSelectionOnViewWillAppear is unreliable for user-driven (swipe) VC dismiss
    NSIndexPath *indexPath = self.tableView.indexPathForSelectedRow;
    if (indexPath && self.transitionCoordinator) {
        [self.transitionCoordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
            [self.tableView deselectRowAtIndexPath:indexPath animated:animated];
        } completion:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
            if ([context isCancelled]) {
                [self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
            }
        }];
    }
}

오늘 직접이 문제를 경험 한 후, 이것이 UITableView에서 상당히 잘 알려진 문제라는 것을 알게되었습니다. 대화 형 탐색 전환에 대한 지원이 약간 손상되었습니다. Castro 뒤에있는 사람들은 이에 대한 훌륭한 분석과 해결책을 게시했습니다 : http://blog.supertop.co/post/80781694515/viewmightappear

취소 된 전환도 고려하는 솔루션을 사용하기로 결정했습니다.

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

    NSIndexPath *selectedRowIndexPath = [self.tableView indexPathForSelectedRow];
    if (selectedRowIndexPath) {
        [self.tableView deselectRowAtIndexPath:selectedRowIndexPath animated:YES];
        [[self transitionCoordinator] notifyWhenInteractionEndsUsingBlock:^(id<UIViewControllerTransitionCoordinatorContext> context) {
            if ([context isCancelled]) {
                [self.tableView selectRowAtIndexPath:selectedRowIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
            }
        }];
    }
}

설정을 시도 할 수 있습니다.

self.clearsSelectionOnViewWillAppear = YES;

UITableViewController 또는

[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:NO];

viewWillAppear에서 [super viewWillAppear : animated]를 호출하기 전에; UItableView가 UITableViewController 내에 있지 않은 경우 수동으로 셀을 선택 취소해야합니다.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES]; 
}

나는 사용하고있다

[tableView deselectRowAtIndexPath:indexPath animated:YES];

방법의 끝에서

(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

이렇게 :

(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

    //doing something according to selected cell...

    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

간단한 Swift 3/4 답변 :

override func viewWillAppear(_ animated: Bool) {
    if tableView.indexPathForSelectedRow != nil {
        self.tableView.deselectRow(at: tableView.indexPathForSelectedRow! as IndexPath, animated: true)
    }
}

사용하다

[tableView deselectRowAtIndexPath:indexPath animated:YES];

코드 입력

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method


이 문제에 대한 매우 간단한 해결책을 찾았습니다. 기본 동작이 제대로 작동하도록합니다. deselectRowAtIndexPath결과적인 시각 효과가 약간 다르기 때문에 관련 솔루션에 만족하지 못했습니다 .

이 이상한 동작을 방지하기 위해해야 ​​할 일은 뷰가 표시 될 때 테이블을 다시로드하는 것입니다.

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self.tableView reloadData];
}

Swift 3의 Codestage 답변notifyWhenInteractionEnds 은 더 이상 사용되지 않습니다.

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(true)

    if let indexPath = self.tableView.indexPathForSelectedRow {
        self.tableView.deselectRow(at: indexPath, animated: true)
        self.transitionCoordinator?.notifyWhenInteractionChanges { (context) in
            if context.isCancelled {
                self.tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
            }
        }
    }
}

You are probably not calling the super view's viewWillAppear method ([super viewWillAppear:animated];). When you do this and the UITableViewController's parameter clearsSelectionOnViewWillAppear is YES then the cells will be deselected on viewWillAppear.


Based on Rhult's code, I made a few changes.

This implementation allow user to cancel swipe back and still keep selected for future swipe back deselect animation

@property(strong, nonatomic) NSIndexPath *savedSelectedIndexPath;


- (void)viewDidLoad {
   [super viewDidLoad];
   self.clearsSelectionOnViewWillAppear = NO;
}

-(void) viewDidAppear:(BOOL)animated {
   [super viewDidAppear:animated];
   self.savedSelectedIndexPath = nil;
}

-(void) viewWillDisappear:(BOOL)animated {
   [super viewWillDisappear:animated];
   if (self.savedSelectedIndexPath && ![self.tableView indexPathForSelectedRow]) {
       [self.tableView selectRowAtIndexPath:self.savedSelectedIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
   } else {
      self.savedSelectedIndexPath = [self.tableView indexPathForSelectedRow];
   }
}

Rhult's solution works perfectly on iOS 9.2. This is the implementation in Swift:

Declare a variable in your MasterViewController to save the IndexPath:

var savedSelectedIndexPath: NSIndexPath?

Then you can put the code in an extension for clarity:

extension MasterViewController {
    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        self.savedSelectedIndexPath = nil
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        if let indexPath = self.savedSelectedIndexPath {
            self.tableView.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: .None)
        }
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        self.savedSelectedIndexPath = tableView.indexPathForSelectedRow
        if let indexPath = self.savedSelectedIndexPath {
            self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
        }
    }
}

Codestage provided by far the best looking answer, so I decided to convert it into Swift 2.

override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(true)

        let selectedRowIndexPath = self.tableView.indexPathForSelectedRow
        if ((selectedRowIndexPath) != nil) {
            self.tableView.deselectRowAtIndexPath(selectedRowIndexPath!, animated: true)
            self.transitionCoordinator()?.notifyWhenInteractionEndsUsingBlock({ context in
                if (context.isCancelled()) {
                    self.tableView.selectRowAtIndexPath(selectedRowIndexPath, animated: false, scrollPosition: UITableViewScrollPosition.None)
                }
            })
        }
    }

For swift

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    guard let indexPath = tableView.indexPathForSelectedRow else{
        return
    }
    tableView.deselectRowAtIndexPath(indexPath, animated: true)
}

참고URL : https://stackoverflow.com/questions/19379510/uitableviewcell-doesnt-get-deselected-when-swiping-back-quickly

반응형