Programming

iOS7에서 UITableViewCell 구분 기호가 사라짐

procodes 2020. 7. 2. 08:13
반응형

iOS7에서 UITableViewCell 구분 기호가 사라짐


UITableViewiOS 7에서만 이상한 문제가 있습니다.

UITableViewCellSeparator첫 번째 행 위와 마지막 행 아래에서 사라집니다. 때때로 행이나 일부 스크롤 동작을 선택한 후 나타납니다.

내 경우 tableView에는 Storyboardwith UITableViewStylePlain스타일 에서로드됩니다 . 문제는 확실하지 않으며 UITableViewCellSeparatorStyle기본값에서 변경되지 않습니다 UITableViewCellSeparatorStyleSingleLine.

Apple Dev Forums ( herehere ) 에서 읽을 때 다른 사람들에게 그러한 문제가 있으며 몇 가지 해결 방법이 있습니다.

Workaround: disable the default selection and recreate the behaviour in a method
trigged by a tapGestureRecognizer.

그러나 나는 여전히 그런 분리기의 이상한 행동의 이유를 찾고 있습니다.

어떤 아이디어?

업데이트 : XCode 5.1 DP 및 iOS 7.1 베타에서 보았 듯이 Apple 은이 문제를 해결하려고했습니다. 이제 구분 기호는 때때로 새로 고친 후 마지막 행 아래에 필요에 따라 표시되지만 테이블 뷰 생성 후에는 표시되지 않습니다.


영향을받는 셀의 하위 뷰 계층 구조를 덤프하고 _UITableViewCellSeparatorView가 숨김으로 설정되어 있음을 발견했습니다 . 그것이 보이지 않는 것은 당연합니다!

나는 오버라이드 layoutSubviews내에서 UITableViewCell서브 지금은 분리가 확실하게 표시됩니다

목표 -C :

- (void)layoutSubviews {
    [super layoutSubviews];

    for (UIView *subview in self.contentView.superview.subviews) {
        if ([NSStringFromClass(subview.class) hasSuffix:@"SeparatorView"]) {
            subview.hidden = NO;
        }
    }
}

스위프트 :

override func layoutSubviews() {
    super.layoutSubviews()

    guard let superview = contentView.superview else {
        return
    }
    for subview in superview.subviews {
        if String(subview.dynamicType).hasSuffix("SeparatorView") {
            subview.hidden = false
        }
    }
}

여기에 제안 된 다른 솔루션은 나에게 일관되게 작동하지 않거나 어리석은 것처럼 보입니다 (사용자 정의 1px 바닥 글보기 추가).


이것은 나를 위해 일했다 :

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

    // fix for separators bug in iOS 7
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;

또한 분리 누락 된 문제를했고 나는 때만 문제가 발생한 것을 발견 heightForRowAtIndexPath소수의 개수를 돌려줍니다 . 해결책:

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return ceil(yourHeight) // Ceiling this value fixes disappearing separators
}

밝은 회색 배경색으로 테이블의 머리글과 바닥 글에 높이 1의 UIView를 추가하려고 했습니까? 기본적으로 첫 번째와 마지막 구분 기호를 조롱합니다.


sam

이 대리자 메서드를 사용하여 문제를 해결했습니다. 이제 깜박 거리지 않습니다.

-(void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath {
    // fix for separators bug in iOS 7
    tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
}


-(void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath {
    // fix for separators bug in iOS 7
    tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
}

앱에서이 문제가 발생했습니다. 사용자가 셀을 선택하면 새 테이블보기가 탐색 컨트롤러 스택으로 푸시 된 다음 사용자가이를 제거 할 때 구분 기호가 누락되었습니다. 테이블 뷰 대리자 메소드 [self.tableView deselectRowAtIndexPath:indexPath animated:NO];를 사용하여 해결했습니다 didSelectRowAtIndexPath.


필요한 경우 더 쉬운 해결 방법이 있습니다 (데이터가 다시로드되고 기본 애니메이션이 완료된 후 셀을 선택하고 선택 취소하십시오).

그냥 추가하십시오 :

[self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
[self.tableView deselectRowAtIndexPath:indexPath animated:NO];

가장 쉬운 해결책은 셀을 다시로드 한 후 위의 셀을 다시로드하는 것입니다.

if (indexPath.row > 0) {
    NSIndexPath *path = [NSIndexPath indexPathForRow:indexPath.row - 1 inSection:indexPath.section];
    [self.tableView reloadRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationNone];
}

iOS 8과 iOS 9 (베타 1) 모두에서 작동하는 간단하고 깨끗한 솔루션

다음은 간단하고 깨끗 하며 방해가되지 않는 해결 방법입니다. 구분 기호를 수정하는 범주 메서드를 호출해야합니다.

셀의 계층 구조를 따라 가고 구분 기호를 숨기기 해제하기 만하면됩니다. 이처럼 :

for (UIView *subview in cell.contentView.superview.subviews) {
    if ([NSStringFromClass(subview.class) hasSuffix:@"SeparatorView"]) {
        subview.hidden = NO;
    }
}

내가 권장하는 것은 이것을 다음과 같이 UITableViewCell의 카테고리에 추가하는 것입니다.

@interface UITableViewCell (fixSeparator)
- (void)fixSeparator;
@end

@implementation UITableViewCell (fixSeparator)

- (void)fixSeparator {
    for (UIView *subview in self.contentView.superview.subviews) {
        if ([NSStringFromClass(subview.class) hasSuffix:@"SeparatorView"]) {
            subview.hidden = NO;
        }
    }
}

@end

현재 선택된 셀과 다른 셀에서 구분 기호가 사라질 수 있으므로 테이블 뷰의 모든에서이 수정 프로그램을 호출하는 것이 좋습니다 . 이를 위해 UITableView에 다음과 같은 범주를 추가 할 수 있습니다.

@implementation UITableView (fixSeparators)

- (void)fixSeparators {
    for (UITableViewCell *cell in self.visibleCells) {
        [cell fixSeparator];
    }
}

@end

이를 사용하면 -fixSeparatostableView가 사라지는 작업 직후에 tableView를 호출 할 수 있습니다 . 내 경우, 호출 한 후였다 [tableView beginUpdates][tableView endUpdates].

처음에 언급했듯이 iOS 8과 iOS 9에서 모두 테스트했습니다 .iOS 7에서도 작동한다고 가정하지만 거기서 시도 할 방법이 없습니다. 아시다시피, 이것은 셀의 내부를 피들 링하여 향후 릴리스에서 작동을 멈출 수 있습니다. 그리고 애플은 이론적으로 (0.001 % 확률) 앱으로 인해 앱을 거부 할 수는 있지만, 당신이하고있는 일을 어떻게 알 수 있는지 알 수 없습니다 (정적 분석기는 무언가로 클래스의 접미사를 확인할 수 없습니다) 나쁘다, IMO).


@ ortwin-gentz의 의견에 따라이 솔루션은 iOS 9에서 작동합니다.

func fixCellsSeparator() {

    // Loop through every cell in the tableview
    for cell: UITableViewCell in self.tableView.visibleCells {

        // Loop through every subview in the cell which its class is kind of SeparatorView
        for subview: UIView in (cell.contentView.superview?.subviews)!
            where NSStringFromClass(subview.classForCoder).hasSuffix("SeparatorView") {
                subview.hidden = false
        }
    }

}

(스위프트 코드)

내 tableView의 일부 메소드에서 endUpdates ()호출 한 후 fixCellsSeparator () 함수를 사용합니다 .

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    //  Perform some stuff
    //  ...

    self.tableView.endUpdates()
    self.fixCellsSeparator()

}

이 솔루션이 누군가에게 도움이되기를 바랍니다.


에어 포그의 답을 보완하십시오.

따라서 기본적으로 두 개의 UITableDelegate 메소드를 구현해야합니다. 여기 iOS7과 iOS6에서 모두 작동하는 솔루션이 있습니다.

#define IS_OS_VERSION_7 (NSFoundationVersionNumber_iOS_6_1 < floor(NSFoundationVersionNumber))

#define UIColorFromRGB(hexRGBValue) [UIColor colorWithRed:((float)((hexRGBValue & 0xFF0000) >> 16))/255.0 green:((float)((hexRGBValue & 0xFF00) >> 8))/255.0 blue:((float)(hexRGBValue & 0xFF))/255.0 alpha:1.0]

// 전체 화면을 덮지 않으면 셀 아래에 빈 표 격자가 숨겨집니다.

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
    UIView *view = nil;

    if (IS_OS_VERSION_7 /* && <is this the last section of the data source> */)
    {
        CGFloat height = 1 / [UIScreen mainScreen].scale;
        view = [[UIView alloc] initWithFrame:CGRectMake(0., 0., 320., height)];
        view.backgroundColor = UIColorFromRGB(0xC8C7CC);
        view.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    }
    else
    {
        view = [UIView new];
    }
    return view;
}


- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
    if (IS_OS_VERSION_7 /* && <is this the last section of the data source> */)
    {
        return 1 / [UIScreen mainScreen].scale;
    }
    else
    {
        // This will hide the empty table grid below the cells if they do not cover the entire screen
        return 0.01f;
    }
}

이것은 나를 위해 문제를 해결했습니다.

확인 clipsToBounds셀에 YES로 설정되어 있지만, NO 셀의 대한 contentView. 또한 설정cell.contentView.backgroundColor = [UIColor clearColor];


이 문제는 많은 상황에서 나타납니다.

저에게는 셀 선택과 관련이 있습니다. 나는 왜 그것을 알지 못하고 너무 깊게 파고들 시간이 없었지만 셀 selectionStyle을 none으로 설정했을 때 발생하기 시작했다고 말할 수 있습니다 . 즉 :

//This line brought up the issue for me
cell.selectionStyle = UITableViewCellSelectionStyleNone;

위의 위임 방법 중 일부를 사용하여 separatorStyle속성을 켜고 끄려고 시도했지만 tableView문제를 해결하기 위해 아무것도하지 않는 것 같습니다.

내가 필요한 이유는 셀 선택이 필요하지 않았기 때문입니다.

그래서 나에게 도움이되는 것을 찾았습니다. 방금 선택을 비활성화했습니다 UITableView.

tableView.allowsSelection = NO;

셀 선택이 필요하지 않은 경우 누군가에게 도움이되기를 바랍니다.


나는 너무 많은 제안을 시도했지만 그것을 고칠 수는 없다. 마침내 나는 다음과 같이 사용자 정의 구분선을 결정했다.

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    var lineView = UIView(frame: CGRectMake(20, cell.contentView.frame.size.height - 1.0, cell.contentView.frame.size.width - 20, 1))

    lineView.backgroundColor = UIColor(red: 170.0/255.0, green: 170.0/255.0, blue: 170.0/255.0, alpha: 1)
    cell.contentView.addSubview(lineView)
}

P / S : willDisplayCell 에서 사용자 정의 하지 않음 cellForRowAtIndexPath


놀랍게도 셀의 separatorInset값을 앞뒤로 변경하는 것이 효과가있는 것 같습니다.

NSIndexPath *selectedPath = [self.controller.tableView indexPathForSelectedRow];
[self.controller.tableView deselectRowAtIndexPath:selectedPath animated:YES];

UITableViewCell *cell = [self.controller.tableView cellForRowAtIndexPath:selectedPath];
UIEdgeInsets insets = cell.separatorInset;
cell.separatorInset = UIEdgeInsetsMake(0.0, insets.left + 1.0, 0.0, 0.0);
cell.separatorInset = insets;

또한 UITableView의 맨 아래 에이 일관되지 않은 구분선 표시 문제가있었습니다. 사용자 정의 바닥 글보기를 사용하여 비슷한 선을 작성하여 잠재적 인 기존 선 (때로는 누락 된) 위에 표시 할 수있었습니다.

이 솔루션의 유일한 문제는 Apple이 언젠가 선 두께를 변경할 수 있다는 것입니다

- (UIView*) tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
    float w = tableView.frame.size.width;

    UIView * footerView =  [[UIView alloc] initWithFrame:CGRectMake(0, 0, w, 1)];
    footerView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    footerView.clipsToBounds=NO;

    UIView* separatoraddon = [[UIView alloc] initWithFrame:CGRectMake(0, -.5, w, .5)];
    separatoraddon.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    separatoraddon.backgroundColor = tableView.separatorColor;
    [footerView addSubview:separatoraddon];

    return footerView;
}
- (CGFloat) tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
    return 1;
}

테이블 뷰 업데이트가 필요한 위치에 다음 코드 줄을 넣는 것을 해결했습니다.

self.tableView.separatorStyle = UITableViewCellSeparatorStyle.None;
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.SingleLine;

예를 들어, 제 경우에는 여기에 넣었습니다.

tableView.beginUpdates()
tableView.insertRowsAtIndexPaths(insertIndexPaths, withRowAnimation: UITableViewRowAnimation.Fade)
tableView.endUpdates()
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.None;
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.SingleLine;

셀 업데이트를 수행하기 전에 셀 선택을 제거해야합니다. 그런 다음 선택을 복원 할 수 있습니다.

NSIndexPath *selectedPath = [self.tableview indexPathForSelectedRow];
    [self.tableview deselectRowAtIndexPath:selectedPath animated:NO];
    [self.tableview reloadRowsAtIndexPaths:@[ path ] withRowAnimation:UITableViewRowAnimationNone];
    [self.tableview selectRowAtIndexPath:selectedPath animated:NO scrollPosition:UITableViewScrollPositionNone];

위의 문제를 해결하려면 viewDidLoad에 빈 바닥 글을 추가하십시오.

UIView *emptyView_ = [[UIView alloc] initWithFrame:CGRectZero];   
emptyView_.backgroundColor = [UIColor clearColor];  
[tableView setTableFooterView:emptyView_];

viewForFooterInSection 델리게이트 메소드에서 위의 라인을 사용하지 마십시오. 의미 viewForFooterInSection 메소드를 구현하지 않습니다.


에어 포그 답변을 확장하는 데 도움이되지 않았습니다.

높이를 얻으려면 heightforfooter 메서드를 구현해야했습니다.

밝은 회색이 너무 어둡다는 것을 알았습니다. 테이블 뷰의 현재 구분 기호 색상을 잡고 다음을 사용 하여이 문제를 해결했습니다.

UIColor *separatorGray = [self.briefcaseTableView separatorColor]; [footerSeparator setBackgroundColor:separatorGray];


I also ran into this problem in our project. My table view had a tableFooterView which could make this happen. I found the separator below the last row would appear if I removed that tableFooterView.


What made the difference for me was reloading the row for which the bottom separator line would not appear:

NSIndexPath *indexPath = 
     [NSIndexPath indexPathForRow:rowIndex inSection:sectionIndex];  
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];

I solve this problem in another way: add a layer that its height is 0.5px and its color is lightgray into tableview.tableFooterView as its sublayer.

the code is just like this:

UIView *tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 70)];
CALayer *topSeperatorLine = [CALayer layer];
topSeperatorLine.borderWidth = 0.5f;
topSeperatorLine.borderColor = [UIColor lightGrayColor].CGColor;
topSeperatorLine.frame = CGRectMake(0, 0, 320, 0.5f);
[tableFooterView.layer addSublayer:topSeperatorLine];
self.tableView.tableFooterView = tableFooterView;

In your UITableViewCell Subclass implement layoutSubviews and add:

- (void)layoutSubviews{
    [super layoutSubviews]
    for (UIView *subview in self.contentView.superview.subviews) {
        if ([NSStringFromClass(subview.class) hasSuffix:@"SeparatorView"]) {
            CGRect separatorFrame = subview.frame;
            separatorFrame.size.width = self.frame.size.width;
            subview.frame = separatorFrame;
        }
    }
}

As someone else mentioned, this problem seems to manifest in a variety of ways. I resolved my issue via the following workaround:

[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
[tableView endUpdates];

Going through the answers and solutions I came up with such observations:

This seems to be problematic in both iOS 7 and 8. I noticed the problem when selecting cell from code in viewDidLoad method so:

1) workaround was doing so in viewDidAppear: if someone doesn't mind the noticeable delay between presenting the view and selecting the cell

2) the second solution worked for me but the code looks a bit fragile as it base on the internal implementation of the UITableViewCell

3) adding own separator seems to be the most flexible and best for now but require more coding :)


Setting the style in viewWillAppear worked for me.


As this is still an issue with IOS 8, I will add my solution in Swift. Set the tableview separator line to none. Then add this code to the cellForRowAtIndexPath delegate method. It will add a nice separator. The if statement allows to decide which cells should have a separator.

    var separator:UIView!
    if let s = cell.viewWithTag(1000)
    {
        separator = s
    }
    else
    {
        separator = UIView()
        separator.tag = 1000
        separator.setTranslatesAutoresizingMaskIntoConstraints(false)
        cell.addSubview(separator)

        // Swiper constraints
        var leadingConstraint = NSLayoutConstraint(item: separator, attribute: .Leading, relatedBy: .Equal, toItem: cell, attribute: .Leading, multiplier: 1, constant: 15)
        var heightConstraint = NSLayoutConstraint(item: separator, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 0.5)
        var bottomConstraint = NSLayoutConstraint(item: cell, attribute: .Bottom, relatedBy: .Equal, toItem: separator, attribute: .Bottom, multiplier: 1, constant:0)
        var trailingConstraint = NSLayoutConstraint(item: cell, attribute: .Trailing, relatedBy: .Equal, toItem: separator, attribute: .Trailing, multiplier: 1, constant: 15)
        cell.addConstraints([bottomConstraint, leadingConstraint, heightConstraint, trailingConstraint])
    }

    if indexPath.row == 3
    {
        separator.backgroundColor = UIColor.clearColor()
    }
    else
    {
        separator.backgroundColor = UIColor.blackColor()
    }

Here's my solution to this problem. After you insert your cell(s), reload the section. If reloading the entire section is too intensive for you, just reload the indexPaths above and below.

[CATransaction begin];
[CATransaction setCompletionBlock:^{
    //  Fix for issue where seperators disappear

    [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];
}];

[self.tableView insertRowsAtIndexPaths:@[ indexPath ] withRowAnimation:UITableViewRowAnimationFade];

[CATransaction commit];

ran into a similar problem, I found that another good solution, especially if your dataSource is not large is reload the tableData when you implement the -(void)scrollViewDidScroll:(UIScrollView *)scrollView method, here's an example:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
      if (scrollView == self.tableView1) {
          [self.tableView1 reloadData];
      }

      else {
          [self.tableView2 reloadData];
      }
}

You can also just reload non-visible data based on the visible dataSource, but that requires some more hacking.

Keep in mind this delegate function falls under the UITableViewDelegate protocol!

Hope it helps!

참고URL : https://stackoverflow.com/questions/18924589/uitableviewcell-separator-disappearing-in-ios7

반응형