답변:
이 솔루션을 찾고 있습니다.
StaticDataTableViewController 2.0
https://github.com/xelvenone/StaticDataTableViewController
애니메이션 유무에 관계없이 정적 셀을 표시하거나 숨기거나 다시로드 할 수 있습니다!
[self cell:self.outletToMyStaticCell1 setHidden:hide];
[self cell:self.outletToMyStaticCell2 setHidden:hide];
[self reloadDataAnimated:YES];
항상 (reloadDataAnimated : YES / NO) 만 사용하십시오 ([self.tableView reloadData]를 직접 호출하지 마십시오)
높이를 0으로 설정 한 해키 솔루션을 사용하지 않으며 변경 사항에 애니메이션을 적용하고 전체 섹션을 숨길 수 있습니다.
IBOutletCollection
것이지만 어떻게 그것이 차이를 만들지 알지 못합니다. 어제 코드를 다운로드 했으므로 이전 버전은 생각하지 않습니다.
UITable에서 정적 셀을 숨기려면
UITableView 컨트롤러 위임 클래스에서 :
목표 -C :
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
if(cell == self.cellYouWantToHide)
return 0; //set the hidden cell's height to 0
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
빠른:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
var cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)
if cell == self.cellYouWantToHide {
return 0
}
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
이 메소드는 UITable의 각 셀에 대해 호출됩니다. 숨기려는 셀을 호출하면 높이를 0으로 설정합니다. 콘센트를 만들어 대상 셀을 식별합니다.
ClipToBounds
문제 를 피하기 위해 셀을 숨김으로 설정할 수도 있습니다. 이것은 나에게 더 깨끗해 보일 것입니다. ;-)
가장 좋은 방법은 다음 블로그 http://ali-reynolds.com/2013/06/29/hide-cells-in-static-table-view/에 설명 된대로입니다.
인터페이스 빌더에서 정적 테이블 뷰를 정상적으로 설계하십시오. 잠재적으로 숨겨진 셀이 모두 있습니다. 그러나 숨길 수있는 모든 잠재적 인 셀에 대해 수행해야 할 한 가지가 있습니다. 셀의 "클립 하위 뷰"속성을 확인하십시오. 그렇지 않으면 셀을 숨기려고 할 때 셀의 내용이 사라지지 않습니다 (높이를 줄임으로써) - 더 늦게).
SO – 셀에 스위치가 있고 스위치는 일부 정적 셀을 숨기고 표시해야합니다. IBAction에 연결하고 다음을 수행하십시오.
[self.tableView beginUpdates]; [self.tableView endUpdates];
그것은 세포가 나타나고 사라지는 멋진 애니메이션을 제공합니다. 이제 다음 테이블 뷰 델리게이트 메소드를 구현하십시오.
- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == 1 && indexPath.row == 1) { // This is the cell to hide - change as you need // Show or hide cell if (self.mySwitch.on) { return 44; // Show the cell - adjust the height as you need } else { return 0; // Hide the cell } } return 44; }
그리고 그게 다야. 스위치를 뒤집 으면 멋지고 부드러운 애니메이션으로 셀이 숨겨지고 다시 나타납니다.
내 솔루션은 Gareth와 비슷한 방향으로 진행되지만 몇 가지 작업은 다르게 수행합니다.
간다 :
1. 세포를 숨기십시오
셀을 직접 숨길 수는 없습니다. UITableViewController
는 정적 셀을 제공하는 데이터 소스이며 현재 "셀 x 제공하지 않음"을 알 수있는 방법이 없습니다. 따라서 우리는 우리 자신의 데이터 소스를 제공해야합니다.UITableViewController
정적 셀을 얻으려면에 .
가장 쉬운 방법은 하위 클래스 UITableViewController
를 만들고 셀을 숨길 때 다르게 동작해야하는 모든 메서드를 재정의 하는 것입니다. 입니다.
가장 간단한 경우 (단일 섹션 테이블, 모든 셀의 높이가 동일), 다음과 같습니다.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [super tableView:tableView numberOfRowsInSection:section] - numberOfCellsHidden;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Recalculate indexPath based on hidden cells
indexPath = [self offsetIndexPath:indexPath];
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
- (NSIndexPath*)offsetIndexPath:(NSIndexPath*)indexPath
{
int offsetSection = indexPath.section; // Also offset section if you intend to hide whole sections
int numberOfCellsHiddenAbove = ... // Calculate how many cells are hidden above the given indexPath.row
int offsetRow = indexPath.row + numberOfCellsHiddenAbove;
return [NSIndexPath indexPathForRow:offsetRow inSection:offsetSection];
}
테이블에 여러 섹션이 있거나 셀의 높이가 다른 경우 더 많은 메서드를 재정의해야합니다. 동일한 원칙이 여기에 적용됩니다. super에 위임하기 전에 indexPath, section 및 row를 오프셋해야합니다.
또한 다음과 같은 메소드의 indexPath 매개 변수는 didSelectRowAtIndexPath:
같은 셀에 대해 같은 상태 (즉, 숨겨진 셀 수)에 따라 다를 수 있습니다. 따라서 항상 indexPath 매개 변수를 오프셋하고이 값으로 작업하는 것이 좋습니다.
2. 변화를 애니메이션
Gareth가 이미 언급했듯이 reloadSections:withRowAnimation:
방법을 사용하여 변경 사항을 애니메이션하면 주요 결함이 발생합니다 .
reloadData:
나중에 즉시 전화 하면 애니메이션이 훨씬 향상됩니다 (사소한 결함 만 남음). 애니메이션 후 테이블이 올바르게 표시됩니다.
그래서 내가하고있는 일은 :
- (void)changeState
{
// Change state so cells are hidden/unhidden
...
// Reload all sections
NSIndexSet* reloadSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [self numberOfSectionsInTableView:tableView])];
[tableView reloadSections:reloadSet withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView reloadData];
}
numberOfRowsInSection:
하면 테이블이 처음로드 될 때만 호출 된다는 것입니다 . [self.tableView reloadData]를 호출하면 numberOfRowsInSection:
다시 호출되지 않습니다. 만 cellForRowAtIndexPath:
이라고합니다. 내가 무엇을 놓치고 있습니까?
cellOneOutlet.hidden = true
이제 아래 방법을 재정의하고 어떤 셀 상태가 숨겨져 있는지 확인하고 해당 셀의 높이 0을 반환하십시오. 이것은 정적 tableView의 모든 셀을 신속하게 숨길 수있는 많은 방법 중 하나입니다.
override func tableView(tableView: UITableView, heightForRowAtIndexPathindexPath: NSIndexPath) -> CGFloat
{
let tableViewCell = super.tableView(tableView,cellForRowAtIndexPath: indexPath)
if tableViewCell.hidden == true
{
return 0
}
else{
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
}
let tableViewCell = super.tableView(tableView,cellForRowAtIndexPath: indexPath)
. 나는로 대체되었다고 가정합니다 let tableViewCell = tableView.cellForRow(at: indexPath as IndexPath)
.
UITableViewController
가 없습니다 UITableView
. 호출 heightForRow
하려면 다른 방법이 필요합니까?
실제로 섹션을 숨기고 삭제하지 않는 대안을 생각해 냈습니다. @ henning77의 접근 방식을 시도했지만 정적 UITableView의 섹션 수를 변경하면 계속 문제가 발생합니다. 이 방법은 실제로 잘 작동했지만 주로 행 대신 섹션을 숨기려고합니다. 나는 즉시 행을 성공적으로 제거하고 있지만 훨씬 더 지저분하므로 표시하거나 숨길 필요가있는 섹션으로 항목을 그룹화하려고했습니다. 섹션을 숨기는 방법의 예는 다음과 같습니다.
먼저 NSMutableArray 속성을 선언합니다
@property (nonatomic, strong) NSMutableArray *hiddenSections;
viewDidLoad에서 (또는 데이터를 쿼리 한 후) 숨기려는 섹션을 배열에 추가 할 수 있습니다.
- (void)viewDidLoad
{
hiddenSections = [NSMutableArray new];
if(some piece of data is empty){
// Add index of section that should be hidden
[self.hiddenSections addObject:[NSNumber numberWithInt:1]];
}
... add as many sections to the array as needed
[self.tableView reloadData];
}
그런 다음 TableView 델리게이트 메소드를 다음과 같이 구현하십시오.
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
return nil;
}
return [super tableView:tableView titleForHeaderInSection:section];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:indexPath.section]]){
return 0;
}
return [super tableView:tableView heightForRowAtIndexPath:[self offsetIndexPath:indexPath]];
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:indexPath.section]]){
[cell setHidden:YES];
}
}
그런 다음 높이를 0으로 설정할 수 없기 때문에 숨겨진 섹션에 대해 머리글과 바닥 글 높이를 1로 설정하십시오. 이렇게하면 추가 2 픽셀 공간이 생길 수 있지만 다음에 보이는 머리글의 높이를 조정하여 보충 할 수 있습니다.
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
CGFloat height = [super tableView:tableView heightForHeaderInSection:section];
if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
height = 1; // Can't be zero
}
else if([self tableView:tableView titleForHeaderInSection:section] == nil){ // Only adjust if title is nil
// Adjust height for previous hidden sections
CGFloat adjust = 0;
for(int i = (section - 1); i >= 0; i--){
if([self.hiddenSections containsObject:[NSNumber numberWithInt:i]]){
adjust = adjust + 2;
}
else {
break;
}
}
if(adjust > 0)
{
if(height == -1){
height = self.tableView.sectionHeaderHeight;
}
height = height - adjust;
if(height < 1){
height = 1;
}
}
}
return height;
}
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
return 1;
}
return [super tableView:tableView heightForFooterInSection:section];
}
그런 다음 숨길 특정 행이있는 경우 numberOfRowsInSection 및 cellForRowAtIndexPath에 리턴되는 행을 조정할 수 있습니다. 이 예에는 3 개의 행이 있으며 3 개가 비어 있고 제거 해야하는 섹션이 있습니다.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger rows = [super tableView:tableView numberOfRowsInSection:section];
if(self.organization != nil){
if(section == 5){ // Contact
if([self.organization objectForKey:@"Phone"] == [NSNull null]){
rows--;
}
if([self.organization objectForKey:@"Email"] == [NSNull null]){
rows--;
}
if([self.organization objectForKey:@"City"] == [NSNull null]){
rows--;
}
}
}
return rows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [super tableView:tableView cellForRowAtIndexPath:[self offsetIndexPath:indexPath]];
}
조건부로 행을 제거하는 행에 대한 indexPath를 계산하려면이 offsetIndexPath를 사용하십시오. 섹션 만 숨기는 경우 필요하지 않습니다
- (NSIndexPath *)offsetIndexPath:(NSIndexPath*)indexPath
{
int row = indexPath.row;
if(self.organization != nil){
if(indexPath.section == 5){
// Adjust row to return based on which rows before are hidden
if(indexPath.row == 0 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Email"] != [NSNull null]){
row++;
}
else if(indexPath.row == 0 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Address"] != [NSNull null]){
row = row + 2;
}
else if(indexPath.row == 1 && [self.organization objectForKey:@"Phone"] != [NSNull null] && [self.organization objectForKey:@"Email"] == [NSNull null]){
row++;
}
else if(indexPath.row == 1 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Email"] != [NSNull null]){
row++;
}
}
}
NSIndexPath *offsetPath = [NSIndexPath indexPathForRow:row inSection:indexPath.section];
return offsetPath;
}
재정의 할 방법이 많이 있지만이 방법에 대해 내가 좋아하는 것은 재사용 할 수 있다는 것입니다. hiddenSections 배열을 설정하고 추가하면 올바른 섹션이 숨겨집니다. 행을 숨기는 것은 조금 까다 롭지 만 가능합니다. 테두리가 올바르게 그려지지 않기 때문에 그룹화 된 UITableView를 사용하는 경우 숨기려는 행의 높이를 0으로 설정할 수 없습니다.
NSMutableSet
위해 hiddenSections
대신. 회원 자격을 테스트 할 때 속도가 훨씬 빠릅니다.
NSMutableSet
for 사용 에 대해 좋은 지적을 hiddenSections
하지만, 대답의 요점은 사용해야하는 데이터 구조 유형에 대해 nit-picky보다 개념적이라는 것을 이해합니다.
정적 UITableView에서 애니메이션을 사용하여 셀을 숨기거나 표시 할 수 있습니다. 그리고 그렇게 어렵지 않습니다.
요점:
Use tableView:heightForRowAtIndexPath:
일부 상태를 기반으로 셀 높이를 동적으로 지정합니다.tableView.beginUpdates();tableView.endUpdates()
tableView.cellForRowAtIndexPath:
안으로 전화하지 마십시오 tableView:heightForRowAtIndexPath:
. 캐시 된 indexPath를 사용하여 셀을 구별하십시오.예, 현재 동일한 문제로 어려움을 겪고 있지만 확실히 가능합니다. 셀을 숨길 수 있었고 모든 것이 제대로 작동하지만 현재는 깔끔하게 애니메이션을 만들 수 없습니다. 내가 찾은 것은 다음과 같습니다.
첫 번째 섹션의 첫 번째 행에서 ON / OFF 스위치의 상태에 따라 행을 숨기고 있습니다. 스위치가 ON이면 같은 섹션에 그 아래에 1 개의 행이 있고, 그렇지 않으면 2 개의 다른 행이 있습니다.
스위치가 토글 될 때 호출되는 선택기가 있고 현재 상태를 나타내는 변수를 설정했습니다. 그런 다음 다음을 호출합니다.
[[self tableView] reloadData];
tableView : willDisplayCell : forRowAtIndexPath를 재정의합니다 . 함수를 셀을 과 같이하십시오.
[cell setHidden:YES];
셀과 내용을 숨기지 만 차지하는 공간을 제거하지는 않습니다.
공백을 제거하려면 tableView : heightForRowAtIndexPath를 . 함수를 숨겨져 야하는 행에 대해 0을 리턴하십시오.
또한 tableView : numberOfRowsInSection 을 대체해야합니다 . 하고 해당 섹션의 행 수를 리턴해야합니다. 테이블이 그룹화 된 스타일 인 경우 둥근 모서리가 올바른 셀에 나타나도록 이상한 것을 수행해야합니다. 정적 테이블에는 섹션에 대한 전체 셀 세트가 있으므로 옵션을 포함하는 첫 번째 셀이 있고 ON 상태 옵션에 대해 1 셀이 있고 OFF 상태 옵션에 대해 2 개 이상의 셀이 있습니다 (총 4 셀). 옵션이 ON이면 4를 반환해야합니다. 숨겨진 옵션이 포함되어 있으므로 표시된 마지막 옵션에 둥근 상자가 있습니다. 옵션이 꺼져 있으면 마지막 두 옵션이 표시되지 않으므로 2를 반환합니다. 이것이 명확하지 않으면 죄송하지만 설명하기가 어렵습니다. 설정을 설명하기 위해 IB의 테이블 섹션 구성입니다.
따라서 옵션이 ON이면 테이블은 다음 두 행을보고합니다.
옵션이 OFF이면 테이블은 다음과 같은 네 개의 행을보고합니다.
이 접근 방식은 여러 가지 이유로 정확하지 않습니다. 지금까지 실험을해온 한, 더 나은 방법을 찾으면 알려주십시오. 지금까지 내가 관찰 한 문제는 다음과 같습니다.
테이블에 행 수가 기본 데이터에 포함 된 것과 다른 수를 알려주는 것은 잘못된 생각입니다.
변경 사항을 애니메이션으로 표시 할 수 없습니다. 내가 사용하려고했습니다 reloadSections : withRowAnimation :있는 tableView를 reloadData하고 결과를 이해하지 않는 것 대신에, 나는 여전히이 작업을 얻기 위해 노력하고있어. 현재 일어날 것으로 보이는 것은 tableView가 올바른 행을 업데이트하지 않으므로 표시되어야하는 행이 숨겨져 있고 첫 번째 행 아래에 공백이 남아 있다는 것입니다. 나는 이것이 기본 데이터에 대한 첫 번째 지점과 관련이 있다고 생각합니다.
누군가가 다른 방법이나 애니메이션으로 확장하는 방법을 제안 할 수 있기를 희망하지만 이것이 시작될 수 있습니다. 함수에 대한 하이퍼 링크가 부족하다는 점에 사과를 드려 죄송하지만 새로운 사용자이므로 스팸 필터에 의해 거부되었습니다.
[[self tableView] reloadData];
세포를 숨기고 나서 한 번 더 전화해야한다고 확신합니다
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
에 UITableViewController
정적 세포를 생성하기위한 서브 클래스입니다. 인덱스 경로는 정적 인덱스입니다 (동적 아님).
Justas의 답변에 따르면 Swift 4의 경우 :
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let cell = super.tableView(tableView, cellForRowAt: indexPath)
if cell == self.cellYouWantToHide {
return 0
}
return super.tableView(tableView, heightForRowAt: indexPath)
}
tableView.reloadRows(at:, with:)
행이 이미 표시된 상태에서 높이를 변경하면 셀을 업데이트 해야 할 수도 있습니다.
좋아, 약간의 시도 후에, 나는 일반적인 대답이 아닙니다. 이 셀을 숨겨야하는지 확인하기 위해 "isHidden"또는 "hidden"변수를 사용하고 있습니다.
뷰 컨트롤러에 IBOutlet을 작성하십시오.
@IBOutlet weak var myCell: UITableViewCell!
myCell
사용자 정의 함수를 업데이트하십시오 ( 예 : viewDidLoad에 추가 할 수 있음).
override func viewDidLoad() {
super.viewDidLoad()
self.myCell.isHidden = true
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let cell = super.tableView(tableView, cellForRowAt: indexPath)
guard !cell.isHidden else {
return 0
}
return super.tableView(tableView, heightForRowAt: indexPath)
}
이렇게하면 대리자 메서드의 논리가 줄어들고 비즈니스 요구 사항에만 집중하면됩니다.
자동 레이아웃 문제로 인해 셀 숨기기 / 표시, rowHeight 변경 또는 자동 레이아웃 제약 조건으로 인한 위의 답변이 작동하지 않았습니다. 코드는 참을 수 없게되었습니다.
간단한 정적 테이블의 경우 가장 효과적인 것은 다음과 같습니다.
다음은 테이블 뷰 컨트롤러의 예입니다.
@IBOutlet weak var titleCell: UITableViewCell!
@IBOutlet weak var nagCell: UITableViewCell!
@IBOutlet weak var categoryCell: UITableViewCell!
var cellsToShow: [UITableViewCell] = []
override func viewDidLoad() {
super.viewDidLoad()
determinCellsToShow()
}
func determinCellsToShow() {
if detail!.duration.type != nil {
cellsToShow = [titleCell, nagCell, categoryCell]
}
else {
cellsToShow = [titleCell, categoryCell]
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return cellsToShow[indexPath.row]
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellsToShow.count
}
iOS 11의 경우 수정 된 버전의 Mohamed Saleh의 답변이 Apple의 문서를 기반으로 한 개선 사항과 함께 가장 잘 작동 한다는 것을 알았습니다 . 멋지게 애니메이션을 만들고 추악한 해킹이나 하드 코딩 된 값을 피하고 Interface Builder에 이미 설정된 행 높이를 사용합니다. .
기본 개념은 숨겨진 행에 대해 행 높이를 0으로 설정하는 것입니다. 그런 다음 tableView.performBatchUpdates
일관되게 작동하는 애니메이션을 트리거하는 데 사용하십시오 .
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath == indexPathOfHiddenCell {
if cellIsHidden {
return 0
}
}
// Calling super will use the height set in your storyboard, avoiding hardcoded values
return super.tableView(tableView, heightForRowAt: indexPath)
}
확인 cellIsHidden
하고 indexPathOfHiddenCell
사용 사례에 맞게 설정해야합니다. 내 코드의 경우 테이블 뷰 컨트롤러의 속성입니다.
가시성 (예 : 버튼 동작 또는 didSelectRow
)을 제어하는 모든 방법 에서 performBatchUpdates
블록 내에서 cellIsHidden 상태를 전환하십시오 .
tableView.performBatchUpdates({
// Use self to capture for block
self.cellIsHidden = !self.cellIsHidden
}, completion: nil)
정적 테이블에서 셀 숨기기 애니메이션에 대한 솔루션을 찾았습니다.
// Class for wrapping Objective-C block
typedef BOOL (^HidableCellVisibilityFunctor)();
@interface BlockExecutor : NSObject
@property (strong,nonatomic) HidableCellVisibilityFunctor block;
+ (BlockExecutor*)executorWithBlock:(HidableCellVisibilityFunctor)block;
@end
@implementation BlockExecutor
@synthesize block = _block;
+ (BlockExecutor*)executorWithBlock:(HidableCellVisibilityFunctor)block
{
BlockExecutor * executor = [[BlockExecutor alloc] init];
executor.block = block;
return executor;
}
@end
하나의 추가 사전 만 필요했습니다.
@interface MyTableViewController ()
@property (nonatomic) NSMutableDictionary * hidableCellsDict;
@property (weak, nonatomic) IBOutlet UISwitch * birthdaySwitch;
@end
MyTableViewController의 구현을 살펴보십시오. 보이는 인덱스와 보이지 않는 인덱스 사이에서 indexPath를 변환하는 두 가지 방법이 필요합니다.
- (NSIndexPath*)recoverIndexPath:(NSIndexPath *)indexPath
{
int rowDelta = 0;
for (NSIndexPath * ip in [[self.hidableCellsDict allKeys] sortedArrayUsingSelector:@selector(compare:)])
{
BlockExecutor * executor = [self.hidableCellsDict objectForKey:ip];
if (ip.section == indexPath.section
&& ip.row <= indexPath.row + rowDelta
&& !executor.block())
{
rowDelta++;
}
}
return [NSIndexPath indexPathForRow:indexPath.row+rowDelta inSection:indexPath.section];
}
- (NSIndexPath*)mapToNewIndexPath:(NSIndexPath *)indexPath
{
int rowDelta = 0;
for (NSIndexPath * ip in [[self.hidableCellsDict allKeys] sortedArrayUsingSelector:@selector(compare:)])
{
BlockExecutor * executor = [self.hidableCellsDict objectForKey:ip];
if (ip.section == indexPath.section
&& ip.row < indexPath.row - rowDelta
&& !executor.block())
{
rowDelta++;
}
}
return [NSIndexPath indexPathForRow:indexPath.row-rowDelta inSection:indexPath.section];
}
UISwitch 값 변경에 대한 하나의 IBAction :
- (IBAction)birthdaySwitchChanged:(id)sender
{
NSIndexPath * indexPath = [self mapToNewIndexPath:[NSIndexPath indexPathForRow:1 inSection:1]];
if (self.birthdaySwitch.on)
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
else
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
일부 UITableViewDataSource 및 UITableViewDelegate 메소드 :
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int numberOfRows = [super tableView:tableView numberOfRowsInSection:section];
for (NSIndexPath * indexPath in [self.hidableCellsDict allKeys])
if (indexPath.section == section)
{
BlockExecutor * executor = [self.hidableCellsDict objectForKey:indexPath];
numberOfRows -= (executor.block()?0:1);
}
return numberOfRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
indexPath = [self recoverIndexPath:indexPath];
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
indexPath = [self recoverIndexPath:indexPath];
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// initializing dictionary
self.hidableCellsDict = [NSMutableDictionary dictionary];
[self.hidableCellsDict setObject:[BlockExecutor executorWithBlock:^(){return self.birthdaySwitch.on;}] forKey:[NSIndexPath indexPathForRow:1 inSection:1]];
}
- (void)viewDidUnload
{
[self setBirthdaySwitch:nil];
[super viewDidUnload];
}
@end
신속한 답변 :
TableViewController에 다음 메소드를 추가하십시오.
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return indexPathOfCellYouWantToHide == indexPath ? 0 : super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
tableView가 숨기려는 셀을 그리려고하면 위의 방법으로 높이가 0pt로 설정되어 다른 모든 것이 변경되지 않으므로 표시되지 않습니다.
그주의 사항 indexPathOfCellYouWantToHide
언제든지 변경 될 수 있습니다 :)
> Swift 2.2에서는 몇 가지 답변을 결합했습니다.
스토리 보드에서 콘센트를 만들어 staticCell에 연결하십시오.
@IBOutlet weak var updateStaticCell: UITableViewCell!
override func viewDidLoad() {
...
updateStaticCell.hidden = true
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row == 0 {
return 0
} else {
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
}
첫 번째 셀을 숨기고 위에서 설명한대로 높이를 0으로 설정하고 싶습니다.
테이블 뷰의 맨 아래에서 셀을 숨기는 가장 쉬운 시나리오의 경우 셀을 숨긴 후 tableView의 contentInset을 조정할 수 있습니다.
- (void)adjustBottomInsetForHiddenSections:(NSInteger)numberOfHiddenSections
{
CGFloat bottomInset = numberOfHiddenSections * 44.0; // or any other 'magic number
self.tableView.contentInset = UIEdgeInsetsMake(self.tableView.contentInset.top, self.tableView.contentInset.left, -bottomInset, self.tableView.contentInset.right);
}
이것은 https://github.com/k06a/ABStaticTableViewController를 사용 하여이 작업을 수행하는 새로운 방법입니다
NSIndexPath *ip = [NSIndexPath indexPathForRow:1 section:1];
[self deleteRowsAtIndexPaths:@[ip] withRowAnimation:UITableViewRowAnimationFade]
k06a ( https://github.com/k06a/ABStaticTableViewController )의 솔루션은 셀 헤더 및 바닥 글을 포함한 전체 섹션을 숨기므로 더 좋습니다.이 솔루션 ( https://github.com/peterpaulis/StaticDataTableViewController )은 바닥 글을 제외한 모든 항목을 숨 깁니다.
편집하다
바닥 글을에 숨기려면 해결책을 찾았습니다 StaticDataTableViewController
. 이것은 StaticTableViewController.m 파일에 복사해야하는 것입니다.
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
return nil;
} else {
return [super tableView:tableView titleForFooterInSection:section];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
CGFloat height = [super tableView:tableView heightForFooterInSection:section];
if (self.originalTable == nil) {
return height;
}
if (!self.hideSectionsWithHiddenRows) {
return height;
}
OriginalSection * os = self.originalTable.sections[section];
if ([os numberOfVissibleRows] == 0) {
//return 0;
return CGFLOAT_MIN;
} else {
return height;
}
//return 0;
return CGFLOAT_MIN;
}
물론 가능합니다. 먼저 tableView로 돌아가서 표시하려는 셀 수를 지정한 다음 super
스토리 보드에서 특정 셀을 달성하기 위해 호출 하여 tableView에 반환하십시오.
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.mode.numberOfCells()
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = super.tableView(tableView, cellForRowAtIndexPath: self.mode.indexPathForIndexPath(indexPath))
return cell
}
세포가 다른 hieght를 가지고 있다면 그것을 반환하십시오 :
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return super.tableView(tableView, heightForRowAtIndexPath: self.mode.indexPathForIndexPath(indexPath))
}
@Saleh Masum 솔루션 외에도 :
자동 레이아웃 오류가 발생하는 경우 자동 레이아웃 오류가 발생 하면tableViewCell.contentView
스위프트 3 :
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let tableViewCell = super.tableView(tableView, cellForRowAt: indexPath)
if tableViewCell.isHidden == true
{
tableViewCell.contentView.removeConstraints(tableViewCell.contentView.constraints)
return 0
}
else{
return super.tableView(tableView, heightForRowAt: indexPath)
}
}
이 솔루션은 앱의 흐름에 따라 다릅니다 . 동일한 뷰 컨트롤러 인스턴스에서 셀을 표시하거나 숨기려면 제약 조건 이 제거 되므로 최선의 선택이 아닐 수 있습니다 .
해킹없이 정적 셀과 섹션을 동적으로 숨기는 더 좋은 방법을 얻었습니다.
행 높이를 0으로 설정하면 행을 숨길 수 있지만 전체 행을 숨기고 일부 행을 숨기더라도 행을 숨기더라도 작동하지 않습니다.
내 접근법은 정적 셀의 섹션 배열을 만드는 것입니다. 그러면 테이블 뷰 내용이 섹션 배열에 의해 구동됩니다.
샘플 코드는 다음과 같습니다.
var tableSections = [[UITableViewCell]]()
private func configTableSections() {
// seciton A
tableSections.append([self.cell1InSectionA, self.cell2InSectionA])
// section B
if shouldShowSectionB {
tableSections.append([self.cell1InSectionB, self.cell2InSectionB])
}
// section C
if shouldShowCell1InSectionC {
tableSections.append([self.cell1InSectionC, self.cell2InSectionC, self.cell3InSectionC])
} else {
tableSections.append([self.cell2InSectionC, self.cell3InSectionC])
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return tableSections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableSections[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return tableSections[indexPath.section][indexPath.row]
}
이런 식으로 행과 섹션 수를 계산하기 위해 불쾌한 코드를 작성하지 않고도 모든 구성 코드를 하나로 묶을 수 있습니다. 그리고 물론0
더 이상 높이가 없습니다.
이 코드는 유지 관리가 매우 쉽습니다. 예를 들어, 더 많은 셀 또는 섹션을 추가 / 제거하려는 경우.
마찬가지로 섹션 제목 제목 배열과 섹션 바닥 글 제목 배열을 만들어 섹션 제목을 동적으로 구성 할 수 있습니다.