UITableview : 일부 행에 대해서는 선택을 비활성화하지만 다른 행에는 선택하지 않는 방법


298

tableviewXML에서 파싱 된 그룹 내용으로 표시하고 있습니다. 클릭 이벤트를 비활성화하고 싶습니다 (전혀 클릭 할 수 없어야 함). 테이블에는 두 그룹이 있습니다. 첫 번째 그룹의 선택 만 비활성화하고 두 번째 그룹은 선택 해제하고 싶습니다. navigates내 그룹에 두 번째 그룹의 첫 번째 행을 클릭합니다 player view.

특정 그룹이나 행만 선택 가능하게하려면 어떻게해야합니까?

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{
    if(indexPath.section!=0)
    if(indexPath.row==0)    

    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:tubeUrl]];   
}

감사.

답변:


499

이 코드를 넣어야합니다 cellForRowAtIndexPath

셀의 선택 속성을 비활성화하려면 : (셀을 탭하는 동안)

cell.selectionStyle = UITableViewCellSelectionStyleNone;

셀을 선택 (탭) 할 수있게하려면 : (셀을 탭)

// Default style
cell.selectionStyle = UITableViewCellSelectionStyleBlue;

// Gray style
cell.selectionStyle = UITableViewCellSelectionStyleGray;

셀이 selectionStyle = UITableViewCellSelectionStyleNone;있으면 didSelectRowAtIndexPath사용자가 터치해도 UI가 호출 됩니다. 이를 피하려면 아래 제안 된대로 설정하십시오.

cell.userInteractionEnabled = NO;

대신에. cell.textLabel.enabled = NO;항목을 회색으로 표시 하도록 설정할 수도 있습니다 .


1
이 방법은 스 와이프하여 삭제하려고하면 버그를 생성합니다.
Vive

116
이것은 해킹입니다! 그렇게하십시오, 아래 대답을 사용하십시오-nil을 반환하면서 willSelectRowAtIndexPath를 사용하십시오!
Peter Stajger

4
userInteractionEnabled 항목이 올바르지 않습니다. 사람들이 언급 한대로 willSelectRowAtIndexPath를 후크하십시오.
Jonny

23
iOS 6.0 이상에서는 전달 된 항목의 강조 표시 여부에 따라 기반 을 반환하는 tableView:shouldHighlightRowAtIndexPath:새로운 UITableViewDelegate메소드입니다 . 6.0 이상을 빌드하는 경우이 새로운 API를 강력히 권장합니다. BOOLindexPath
cbowns

3
Swift 에서이 작업을 수행하고 있고 문제가 있지만 여기서 cell!.selectionStyle = .None끝내면 셀을 풀 수있는 힘 을 설정해야 속성에 액세스 할 수 있습니다.
Marcos

371

행 (또는 행의 서브 세트) 을 선택 불가능하게 하려면 UITableViewDelegate메소드 -tableView:willSelectRowAtIndexPath:(TechZen에 의해 언급 됨)를 구현하십시오 . 을 선택할indexPath 수없는 경우을 반환 nil하고 그렇지 않으면를 반환합니다 indexPath. 기본 선택 동작을 얻으려면 indexPath전달 된 delegate메소드로 반환하지만 다른을 반환하여 행 선택을 변경할 수도 있습니다 indexPath.

예:

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // rows in section 0 should not be selectable
    if ( indexPath.section == 0 ) return nil;

    // first 3 rows in any section should not be selectable
    if ( indexPath.row <= 2 ) return nil;

    // By default, allow row to be selected
    return indexPath;
}

2
작은 세부 사항 : 당신은 <= 2, == 2가 아닙니다. 나쁜 스마일! :)
Jonas Byström

23
나는 이것이 정답이라고 덧붙이고 싶지만 cellForRowAtIndexPath에서 selectionStyle을 UITableViewCellSelectionStyleNone으로 설정해야합니다. 왜? 이 선택 스타일이 없으면 셀을 선택할 수 없지만 터치하면 여전히 "선택됨"으로 표시됩니다 (따라서 다른 셀에 대해 선택된 색상으로
변경됨

4
이것은 허용 된 답변보다 더 많은
투표를

2
이것이 대답이 받아 들여지지 않는 주된 이유는 대답이 더 쉬워지기 때문이라고 생각합니다. 테이블이 여전히 setSelected :를 호출하기 때문에 '가장 좋은 방법'은 아니지만 셀에서는 여전히 시각적으로 작동합니다. 이 대답은 여기에 더 많은 작업이 필요하지만 셀에서 setSelected : 호출하는 테이블의 예기치 않은 결과를 피하기 위해 (@TooManyEduardos 제안을 결합해야 함) 적절한 방법입니다.
Brian Sachetta

이 답변이 마음에 들지만 cellForRowAtIndexPath 및 willSelectRowAtIndexPath에서 논리를 복제하지 않으려면 willSelectRowAtIndexPath에서 cell.selectionStyle == none이 nil을 반환하는지 확인하십시오 (아래 답변 참조)
Eric D' Souza

61

iOS 6부터 사용할 수 있습니다

-tableView:shouldHighlightRowAtIndexPath:

을 반환 NO하면 선택 강조 표시와 해당 셀에 연결된 스토리 보드 트리거 된 segue가 모두 비활성화됩니다.

터치가 연속으로 내려 오면 메소드가 호출됩니다. NO해당 메시지 로 되돌아 가면 선택 프로세스가 중단되고 터치가 눌려져있는 동안 현재 선택된 행이 선택된 모양을 잃지 않습니다.

UITableViewDelegate 프로토콜 참조


3
동의했다. 아이폰 OS 및 7의 윗부분은 바람직한 방법이어야 (8 다른 방법 제대로 활용되지 않았다 iOS의 사실이다.)
race_carr

이것이 최고의 답변이어야합니다.
Cameron E

16

위의 답변에서 실제로 문제를 올바르게 해결하는 것은 없습니다. 그 이유는 셀 선택을 비활성화하고 셀 내부의 하위 뷰를 반드시 비활성화하지 않기 때문입니다.

필자의 경우 행 중간에 UISwitch를 제시하고 나머지 행 (비어 있음)은 선택하지 않고 스위치는 선택하지 않으려했습니다! 따라서 올바른 방법은 방법입니다

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath

여기서 양식의 진술

[cell setSelectionStyle:UITableViewCellSelectionStyleNone];

특정 셀에 대한 선택을 비활성화하는 동시에 사용자가 스위치를 조작하여 적절한 선택기를 사용할 수 있습니다. 누군가가

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

단지 셀을 준비하고 UISwitch와의 상호 작용을 허용하지 않는 방법.

또한, 방법을 사용하여

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

양식의 문으로 셀을 선택 해제하려면

[tableView deselectRowAtIndexPath:indexPath animated:NO];

사용자가 셀의 원래 contentView를 누를 때 선택된 행이 여전히 표시됩니다.

내 두 센트. 나는 이것이 많은 사람들이 이것을 유용하게 사용할 것이라고 확신한다.


동의하다. 그리고 nil in willSelectRowAtIndexPath을 반환 하면 동일한 문제가 발생하며 하위 뷰를 선택할 수 없습니다.
jeffjv

정적 테이블이있는 경우 인터페이스 빌더에서 선택을 없음으로 설정하여 셀을 표시하지 않을 수도 있습니다.
jeffjv

11

이러한 데이터 소스 방법으로 선택을 트랩합니다.

 tableView:willSelectRowAtIndexPath: 
 tableView:didSelectRowAtIndexPath: 
 tableView:willDeselectRowAtIndexPath: 
 tableView:didDeselectRowAtIndexPath:

이 방법에서는 선택한 행이 선택 가능한 행인지 확인합니다. 그렇다면, 조치를 취하십시오. 그렇지 않으면 조치를 취하지 마십시오.

불행히도 한 섹션에 대해서만 선택을 해제 할 수 없습니다. 그것은 전체 테이블이거나 아무것도 아닙니다.

그러나 테이블 셀 selectionStyle속성을로 설정할 수 있습니다UITableViewCellSelectionStyleNone . 나는 그것이 선택을 보이지 않게 할 것이라고 믿는다. 셀이 사용자의 관점에서 완전히 비활성으로 보이도록하는 위의 방법과 결합되었습니다.

편집 01 :

일부 행만 선택할 수있는 테이블이있는 경우 선택 가능한 행의 셀을 선택 불가능한 행과 시각적으로 구분해야합니다. 쉐브론 액세서리 버튼이 기본 방법입니다.

그러나 그렇게하면 사용자가 행을 선택하고 행이 아무것도하지 않기 때문에 앱이 잘못 입력되었다고 생각하는 것을 원하지 않습니다.


이러한 방법을 사용하는 방법을 자세히 설명하거나 샘플 프로그램 링크를 제공하십시오
Warrior

2
@Warrior : SDK를 설치 한 경우 Xcode를 열고로 이동 Help -> Developer documentation한 다음 해당 메소드 이름을 검색 필드에 복사하여 작동 방식을 확인할 수 있습니다. 개발자 문서에는 샘플 코드도 포함되어 있습니다.
kennytm


9

cellForRowAtIndexPath메소드 내에서 셀 선택을 사용하지 않으려면 다음과 같은 작업을 수행해야합니다 .

[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[cell setUserInteractionEnabled:NO];

셀이 회색으로 표시되도록하려면 tableView:WillDisplayCell:forRowAtIndexPath메소드 내에 다음을 입력하십시오 .

[cell setAlpha:0.5];

하나는 인터랙티비티를 제어하고 다른 하나는 UI 모양을 제어 할 수 있습니다.


5

일부 셀만 선택을 중지하려면 다음을 사용하십시오.

cell.userInteractionEnabled = NO;

선택을 방지 할뿐만 아니라 설정된 셀에 대해 tableView : didSelectRowAtIndexPath : 호출을 중지합니다.


1
이상한 일이 항상 일어납니다 : userInteractionEnabled하나의 셀에서 NO로 설정 하면 (더 명확하게는 하나의 indexPath) 일부 다른 셀의 사용자 상호 작용이 비활성화됩니다. userInteractionEnabled테이블 뷰 셀에서 사용할 때마다 왜 이런 일이 발생하는지 전혀 알 수 없습니다 . 알려진 버그입니까, 아니면 내가 잘못한 것입니까?
Philip007

3
@ Philip007 "NO"셀이 재사용되고 있습니까? 그렇다면 셀을 대기열에서 제외 할 때 "YES"로 설정해야합니다.
JosephH

1
왜 "YES"로 설정합니까? I 전형적인 예 I는 첫 번째 행 (의 사용자 상호 작용을 설정한다는 것이다 .. 그것이에 NO (해제하면 사용자 상호 작용)으로 할 if [indexPath row] == 0로) NOtableView:cellForRowAtIndexPath:있는 셀을 dequeueing 후. 일반적으로 처음에는 정상적으로 작동합니다. 그런 다음을 (를) 여러 번 호출 한 후 reloadData갑자기 다섯 번째 행은 상호 작용이 허용되지 않은 다음 네 번째 행은 허용되지 않습니다. 언제 발생하는지 알 수 없습니다. 모든 것이 무작위로 보입니다.
Philip007

6
당신이 세포를 재사용하는 경우 Philip007 @, 당신은 당신이 세포에 대해 "YES"로 재설정해야합니다 마십시오 인터랙티브가되고 싶어요. 그렇지 않으면 "NO"셀을 대화식으로 재사용하려는 행에서 재사용하면 여전히 사용 불가능하게됩니다. if [indexPath row] == 0) { set to NO } else { set to YES }
JosephH

5

tableView:willDisplayCell메소드를 사용하여 tableViewCell에 대한 모든 종류의 사용자 정의를 수행 할 수 있습니다 .

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
     [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
     [cell setUserInteractionEnabled:NO];

     if (indexPath.section == 1 && indexPath.row == 0)
     {
         [cell setSelectionStyle:UITableViewCellSelectionStyleGray];
         [cell setUserInteractionEnabled:YES];
     }
} 

이 코드에서 사용자는 tableView의 두 번째 섹션에서 첫 번째 행만 선택할 수 있습니다. 나머지 모든 행은 선택할 수 없습니다. 고마워요 ~



5

데이터 모델을 기반으로 한 내 솔루션 :

func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
    let rowDetails = viewModel.rowDetails(forIndexPath: indexPath)
    return rowDetails.enabled ? indexPath : nil
}

func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
    let rowDetails = viewModel.rowDetails(forIndexPath: indexPath)
    return rowDetails.enabled
}

5

신속한 4.0의 경우 트릭을 수행합니다. didSelectRowAtIndexPath 메서드에서 셀을 비활성화하지만 하위 뷰를 클릭 가능하게 유지합니다.

func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
         if (indexPath.row == clickableIndex ) { 
            return indexPath
         }else{
            return nil
        }
    }

또는 짧게 : return indexPath.row == clickableIndex ? indexPath : nil, 코드를 좀 더 깨끗하게 유지합니다. ;-)
Mark

1

이 기능을 사용하여 셀 이 비활성화되고 선택 불가능한 것처럼 보이게 합니다.

cell.selectionStyle = UITableViewCellSelectionStyleNone;

중요 : 이것은 스타일링 특성 일 뿐이며 실제로 셀을 비활성화하지는 않습니다. 그렇게하려면 델리게이트 구현 selectionStyle에서 확인해야합니다 didSelectRowAtIndexPath:.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    if(cell.selectionStyle == UITableViewCellSelectionStyleNone) {
        return;
    }

    // do your cell selection handling here
}

1

나는 Brian Chapados가 위의 답변을 좋아합니다. 그러나 이는 cellForRowAtIndexPath와 willSelectRowAtIndexPath 모두에서 로직이 중복되어 동기화가 쉽게 이루어지지 않을 수 있음을 의미합니다. 논리를 복제하는 대신 selectionStyle을 확인하십시오.

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    if (cell.selectionStyle == UITableViewCellSelectionStyleNone)
        return nil;

    else
        return indexPath;
}

1

정적 테이블과 동적 테이블 모두에서 작동하므로 편리합니다. 선택을 허용하려는 셀에만 공개 표시기를 설정했습니다.

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    if (cell.accessoryType != UITableViewCellAccessoryDisclosureIndicator) {
        return nil;
    }
    return indexPath;
}

1

코딩없이 Xcode 7에서 간단하게 다음을 수행 할 수 있습니다.

아웃 라인보기에서 테이블보기 셀을 선택하십시오. (셀은 테이블 뷰 컨트롤러 장면> 테이블 뷰 컨트롤러> 테이블 뷰 아래에 중첩되어 있습니다. 테이블 뷰 셀을 보려면 해당 객체를 공개해야 할 수도 있습니다)

속성 관리자에서 선택이라는 필드를 찾은 후 없음을 선택합니다. 속성 관리자이 옵션을 사용하면 사용자가 셀을 누를 때 셀이 시각적으로 강조 표시되지 않습니다.


0

단순한

그냥 사용 cell.userInteractionEnabled = YES;이 탐색 할 수있는 경우 셀에 cell.userInteractionEnabled = NO;다른


1
이것은 또한 셀 내에서 임의의 액세서리 뷰와의 상호 작용을 방지하는데, 이는 원하는 동작이 아닐 수 있습니다.
Greg Brown

0

tableView:willSelectRowAtIndexPath: 테이블의 데이터 소스에 메소드 만 구현 하십시오. 경로의 행을 강조 표시하려면 지정된 indexPath를 리턴하십시오. 그렇지 않으면 nil을 반환하십시오.

내 앱의 예 :

- (NSIndexPath *)tableView:(UITableView *)tableView
    willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    MySelectableObj* obj = [self objectAtPath:indexPath];
    if(obj==nil) return nil;
    return indexPath;
}

이것에 대한 좋은 점은 shouldPerformSegueWithIdentifier:sender:위의 메소드가 nil을 반환하면 호출되지 않는다는 것입니다. 단지 완전성을 위해 위의 테스트를 반복합니다.



0

Bryan의 답변에 동의합니다

만약 내가한다면

cell.isUserInteractionEnabled = false 

셀 내의 하위 뷰는 사용자와 상호 작용하지 않습니다.

다른 사이트에서 설정

cell.selectionStyle = .none

선택 색상을 업데이트하지 않아도 didSelect 메서드가 트리거됩니다.

willSelectRowAt를 사용하면 문제를 해결할 수 있습니다. 예:

func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {

    if indexPath.section == 0{

        if indexPath.row == 0{
            return nil
        }

    }
    else if indexPath.section == 1{

        if indexPath.row == 0{
            return nil
        }

    }

    return indexPath

}

0

appart는 tableView.allowsMultipleSelection = true다음을 선택할 때 섹션의 나머지 셀을 선택 해제해야합니다.

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if indexPath.section does not support multiple selection {
        // deselect the rest of cells
        tableView
            .indexPathsForSelectedRows?.compactMap { $0 }
            .filter { $0.section == indexPath.section && $0.row != indexPath.row }
            .forEach { tableView.deselectRow(at: $0, animated: true) }
    }
}

-1

swift 3.0의 경우 아래 코드를 사용하여 UITableView 셀에 대한 사용자 상호 작용을 비활성화 할 수 있습니다

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