2014-01-24 1 views
3

"그림자"효과를 얻기 위해 UITableViewCell의 아래쪽 부분에 CALayer를 추가하려고합니다. 문제는 테이블을 화면 위로 스크롤하여 화면에서 떼어 내면 레이어가 제거되므로 다시 스크롤하면 다시 볼 수 없습니다. 화면에서 셀을 아래로 스크롤 한 다음 백업하면 정상적으로 나타납니다. UITableViewCell에 CALayer를 추가 한 후 스크롤을 제거했습니다.

I have a gif here showing what's happening.

내가 그 일을하고있어 어떻게 : 나는 또한 그들이 다시 따라서되지 않을 것이라고 희망에 각 셀에 대한 고유 cellIdentifier를 사용하려고했습니다

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


    static NSString *cellIdentifier = @"CellIdentifier"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; 

    if (!cell) { 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; 
    } 

    cell.textLabel.text = [NSString stringWithFormat:@"Row %d", (int)indexPath.row]; 

    CALayer *bottomBorder = [CALayer layer]; 
    bottomBorder.frame = CGRectMake(0.0f, cell.frame.size.height, cell.frame.size.width, 1.0f); 
    bottomBorder.backgroundColor = [UIColor colorWithWhite:0.9f alpha:1.0f].CGColor; 
    [cell.layer addSublayer:bottomBorder]; 

    cell.clipsToBounds = NO; 

    cell.selectionStyle = UITableViewCellSelectionStyleNone; 

    return cell; 
} 

레이어는 절대로 다음과 같이 제거 :

//Same code as before just this changed 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[NSString stringWithFormat:@"%ld_%ld", (long)indexPath.row, (long)indexPath.section]]; 

    if (!cell) { 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[NSString stringWithFormat:@"%ld_%ld", (long)indexPath.row, (long)indexPath.section]]; 
    } 

    //Same code continued... 

내 문제는 셀을 다시 사용할 때 추가 된 CALayer가 제거된다는 것입니다. 셀을 화면에서 스크롤하여 다시 켰을 때 해당 레이어를 유지하려면 무엇을해야합니까?

편집 :

나는이 시도했습니다 중 하나가 작동하지 않습니다

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


    static NSString *cellIdentifier = @"CellIdentifier"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; 

    if (!cell) { 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; 

     CALayer *bottomBorder = [CALayer layer]; 
     bottomBorder.frame = CGRectMake(0.0f, cell.frame.size.height, cell.frame.size.width, 1.0f); 
     bottomBorder.backgroundColor = [UIColor colorWithWhite:0.9f alpha:1.0f].CGColor; 
     [cell.layer addSublayer:bottomBorder]; 

     cell.clipsToBounds = NO; 
     cell.selectionStyle = UITableViewCellSelectionStyleNone; 
    } 

    cell.textLabel.text = [NSString stringWithFormat:@"Row %d", (int)indexPath.row]; 

    return cell; 
} 

답변

3

제거 이유는 UITableViewCellcontentView 대신에 CALayer이 셀에 추가 되었기 때문입니다. 적절한 구현은 다음과 같습니다.

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


    static NSString *cellIdentifier = @"CellIdentifier"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; 

    if (!cell) { 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; 

     CALayer *bottomBorder = [CALayer layer]; 
     bottomBorder.frame = CGRectMake(0.0f, 
              (CGRectGetHeight(cell.contentView.bounds) - 1), 
              CGRectGetWidth(cell.contentView.bounds), 
              1.0f); 

     bottomBorder.backgroundColor = [UIColor colorWithWhite:0.9f alpha:1.0f].CGColor; 
     [cell.contentView.layer addSublayer:bottomBorder]; 
    } 

    cell.textLabel.text = [NSString stringWithFormat:@"Row %d", (int)indexPath.row]; 

    return cell; 
} 
4

GACK! NOT은 모든 셀에 대해 다른 셀 식별자를 사용합니다. 이는 셀 재사용 메커니즘을 완전히 무효화하고 항상 증가하는 메모리 사용량을 제공하며 모든 인덱스에 대해 항상 새로운 셀을 생성하도록합니다. 이는 최악의 결과 일 수 있습니다.

셀이 화면 밖으로 스크롤 될 때마다 재사용 대기열로 이동합니다. 그런 다음 새 색인 경로가 화면으로 스크롤되면 시스템은 이전에 사용한 셀을 휴지통에서 꺼내서 가져옵니다. 구조가 완전히 형성되었다고 가정해야합니다 (사용자가 추가 한 사용자 정의 필드가있을 것입니다). 그러나 내용은 모두 잘못되었으므로 완전히 설정해야합니다. 따라서 레이블이 3 개인 셀이 있고 모델의 일부 개체에 텍스트를 1 개의 레이블로 채우고, 일부를 2로, 일부를 3 개의 레이블로 채우는 경우 비어있는 경우에도 3 개의 레이블 모두에 값을 항상 설정해야합니다 끈. 이렇게하면 셀을 마지막으로 사용했을 때 남은 값이 달라 붙지 않습니다.

의사의 진료실처럼 환자 진료 양식을 작성하는 것이 좋습니다. 귀하는 양식을 작성하여 사무원에게 주십시오. 점원은 정보를 컴퓨터에 입력 한 다음 양식을 양식의 빈 더미 위에 놓습니다. 다음 환자는 자녀, 배우자, 가지고 있지 않은 선재 조건 등이없는 경우 자녀 이름을 포함하여 양식에서 모든 것을 지워야합니다. 그렇지 않으면 마지막 사람의 정보가 양식은 여전히 ​​귀하의 양식에 있습니다.

그림자 레이어의 경우 dequeueReusableCellWithIdentifier를 사용하여 셀을 가져올 때 새 셀을 만들어야 할 경우에만 레이어를 추가해야합니다. 재사용 된 셀을 다시 가져온 경우 해당 레이어는 이미있을 것입니다. 셀에서 셀로 변경되면 내용을 설정해야 할 수도 있습니다.

+0

시간을내어 답변 해 주셔서 감사합니다. UITableView가 어떻게 셀을 재사용하는지 완전히 이해합니다. 내가 한 것은 잘못된 상태로 작동 상태로 전환하는 경우에도 문제를 일부 모양으로 수정하려는 시도였습니다. 나는 내가 묻는 것에 대한 명확한 정의로 나의 질문을 업데이트했다. – random

+0

게시 한 코드가 틀린 것을 제외하고. 셀에 레이어를 추가하는 코드는 "if (! 셀)"조건부에 속합니다. 대신, 셀을 다시 사용할 때마다 새로운 레이어를 추가하는 것이 좋지 않습니다. 그것은 당신이 생각하는 것뿐만 아니라 세포 재사용을 이해하지 못한다는 것을 말해줍니다. –

+0

제가 시도한 모든 코드를 게시 했어야합니다. 'if (! 셀)'에 넣어도 문제가 해결되지 않습니다. – random