Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/108.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios UISwitch和viewWithTag在numberOfRowsInSection中为零_Ios_Null - Fatal编程技术网

Ios UISwitch和viewWithTag在numberOfRowsInSection中为零

Ios UISwitch和viewWithTag在numberOfRowsInSection中为零,ios,null,Ios,Null,我正在试图找出向UITableView的标题中添加和管理UISwitch的最佳方法,到目前为止,我已经阅读了几个关于如何最好地在表中使用UISwitch的链接:,和。这些链接演示了在单元格中使用UISwitch,而我在标题的自定义UIView中使用它们。也就是说,我更喜欢使用标记来管理这些对象,但我不明白为什么viewWithTag方法不起作用 旁注:我能够在运行时将UISwitches放入NSMutableArray,并以这种方式管理它们,但我不希望如此冗长,管理数组上的边界冲突/索引或检查n

我正在试图找出向UITableView的标题中添加和管理UISwitch的最佳方法,到目前为止,我已经阅读了几个关于如何最好地在表中使用UISwitch的链接:,和。这些链接演示了在单元格中使用UISwitch,而我在标题的自定义UIView中使用它们。也就是说,我更喜欢使用标记来管理这些对象,但我不明白为什么viewWithTag方法不起作用

旁注:我能够在运行时将UISwitches放入NSMutableArray,并以这种方式管理它们,但我不希望如此冗长,管理数组上的边界冲突/索引或检查nil列表,等等。。。我也不清楚如何使用IBOutlets实现这一点。这就是为什么我要尝试标记方法

我的目标是使用开关折叠/展开每个部分中的行,这就是为什么我想标记UI开关并将其作为子视图添加到我在viewForHeaderInSection中返回的UIView中。然后,当我需要执行一些逻辑来折叠单元格时,重新引用它们。此外,在运行时,我可以有一个或多个部分,因此硬编码标签号是不切实际的。下面是该方法的代码:

假设:

#define kSwitchTagRange 2000
在switchChanged中:我只是重新加载表的数据:

- (void)switchChanged:(id)sender {

     [self.tableView reloadData];
}
最后,在重新创建表的数据时,我尝试检索UISwitch并确定它的打开/关闭状态,然后如果关闭,则返回0表示部分中的行数,如果打开,则返回一些其他数字:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    NSInteger rowCount = 0;

    UISwitch *switchView = (UISwitch*)[self.view viewWithTag:(kSwitchTagRange + section)];

    if (switchView != nil && switchView.isOn == NO)
    {
        rowCount = 0;

    }
    else
    {
        // Row count is something other than 0
        rowCount = 3;
    }

    return rowCount;
}
不幸的是,此switchView始终为零

我有一些猜测,但无法确定为什么会发生这种情况

  • 猜测1:当表的数据被重新加载时,添加了我想要的开关的UIView被解除分配。它不存在于内存中,因此无法通过标记进行搜索
  • 猜测2:我错误地将UISwitch添加到视图对象中(在许多示例中,我看到对象添加到UITableViewCell的contentView,但是由于我在ViewForHeaderSection:方法中发回UIView,我不确定这些示例是否适用于此处。addSubview应将任何对象添加到树中
有人能告诉我为什么上面的viewWithTag方法会返回nil吗?我倾向于猜测#1,但没有找到任何文档告诉我自定义标题UIView会在任何时候解除分配。单元格会被重复使用,但是节标题呢

最后,我已经读过了,虽然关于标签使用的建议是有道理的,但它似乎根本不喜欢标签方法。如果你不觉得使用标签很混乱,而且使用起来很智能,为什么不使用标签呢?为什么标签功能甚至可用

实际上,我只是想知道为什么viewWithTag方法在我的例子中返回nil


干杯!

我不确定为什么您的viewWithTag总是返回零,我确实认为这可能与视图在某个时候被释放的事实有关

但是,标记仍然可以执行您想要的操作,但是您需要在模型对象中有一个属性或键来跟踪开关的值。您可以使用标记来告诉开关在其操作方法中处于哪个部分,并适当地更新模型。下面是我所做的。我的模型是一个字典数组,其中值键“rowData”的e是一个数组,其中包含该部分的所有数据,键“switchValue”的值是一个NSNumber,0或1,表示交换机的状态。因此,我的数据如下所示:

2012-11-28 22:50:03.104 TableWithSwitchesInHeaderView[3592:c07] (
        {
        rowData =         (
            One,
            Two,
            Three,
            Four
        );
        switchValue = 1;
    },
        {
        rowData =         (
            Red,
            Orange,
            Yellow,
            Green,
            Blue,
            Violet
        );
        switchValue = 1;
    },
)
这是我在相关的表视图委托和数据源方法中看到的:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return self.theData.count;
}

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.bounds.size.width, 44)];
    UISwitch *switchView = [[UISwitch alloc] init];
    double xOffset = self.tableView.bounds.size.width - switchView.frame.size.width;
    switchView.frame = CGRectMake(xOffset,7,switchView.frame.size.width,switchView.frame.size.height);
    [switchView addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
    switchView.tag = kSwitchTagRange + section;
    switchView.on = [[[self.theData objectAtIndex:switchView.tag - 101] valueForKey:@"switchValue"] boolValue];
    [view addSubview:switchView];
    return view;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 50;
}

- (void)switchChanged:(UISwitch *)sender {
    NSMutableDictionary *dict = [self.theData objectAtIndex:sender.tag - 101];
    [dict setValue:[NSNumber numberWithBool:sender.isOn] forKey:@"switchValue"];
    [self.tableView reloadData];
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    BOOL switchValue = [[self.theData[section] valueForKey:@"switchValue"] boolValue];
    if (switchValue) {
        return [[self.theData[section] valueForKey:@"rowData"] count];
    }else{
        return 0;
    }

}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    cell.textLabel.text = [[self.theData[indexPath.section]valueForKey:@"rowData"]objectAtIndex:indexPath.row] ;
    return cell;
}

我的kSwitchTagRange被定义为101。这段代码用于在关闭开关的任何部分中折叠行(实际上去除了所有行)。

我不确定为什么viewWithTag总是返回零,我确实认为这可能与视图在某个点上被释放有关

但是,标记仍然可以执行您想要的操作,但是您需要在模型对象中有一个属性或键来跟踪开关的值。您可以使用标记来告诉开关在其操作方法中处于哪个部分,并适当地更新模型。下面是我所做的。我的模型是一个字典数组,其中值键“rowData”的e是一个数组,其中包含该部分的所有数据,键“switchValue”的值是一个NSNumber,0或1,表示交换机的状态。因此,我的数据如下所示:

2012-11-28 22:50:03.104 TableWithSwitchesInHeaderView[3592:c07] (
        {
        rowData =         (
            One,
            Two,
            Three,
            Four
        );
        switchValue = 1;
    },
        {
        rowData =         (
            Red,
            Orange,
            Yellow,
            Green,
            Blue,
            Violet
        );
        switchValue = 1;
    },
)
这是我在相关的表视图委托和数据源方法中看到的:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return self.theData.count;
}

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.bounds.size.width, 44)];
    UISwitch *switchView = [[UISwitch alloc] init];
    double xOffset = self.tableView.bounds.size.width - switchView.frame.size.width;
    switchView.frame = CGRectMake(xOffset,7,switchView.frame.size.width,switchView.frame.size.height);
    [switchView addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
    switchView.tag = kSwitchTagRange + section;
    switchView.on = [[[self.theData objectAtIndex:switchView.tag - 101] valueForKey:@"switchValue"] boolValue];
    [view addSubview:switchView];
    return view;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 50;
}

- (void)switchChanged:(UISwitch *)sender {
    NSMutableDictionary *dict = [self.theData objectAtIndex:sender.tag - 101];
    [dict setValue:[NSNumber numberWithBool:sender.isOn] forKey:@"switchValue"];
    [self.tableView reloadData];
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    BOOL switchValue = [[self.theData[section] valueForKey:@"switchValue"] boolValue];
    if (switchValue) {
        return [[self.theData[section] valueForKey:@"rowData"] count];
    }else{
        return 0;
    }

}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    cell.textLabel.text = [[self.theData[indexPath.section]valueForKey:@"rowData"]objectAtIndex:indexPath.row] ;
    return cell;
}

我的kSwitchTagRange被定义为101。这段代码用于在关闭开关的任何节中折叠行(实际上是除去所有行)。

从文章中可以看出,ViewForHeaderSection返回的UIView已解除分配,必须重新创建(以及它的所有子视图,包括我的UISwitch),而不是重复使用。我相信苹果公司认为你的节头比单元格要少得多,因此没有提供检索节头的可重用机制。@rdelmar提出的数据绑定方法似乎适用于这种情况。

从帖子中可以看出,viewForHea返回的UIViewderInSection已解除分配,必须重新创建(以及它的所有子视图,包括my UISwitch),而不是重复使用。我相信苹果公司假定您的节头比单元格少得多,因此没有提供检索节头的可重用机制。@rdelmar提出的数据绑定方法似乎适用于这种情况。

感谢您的回复。这实际上是我推荐的一种方法er来自Microsoft堆栈(“将UI控件的属性绑定到相应的数据模型对象的值”)。鉴于UISwitch可能不再可供参考,我可能会采用这种方法,但在此之前,我有一个哲学上的编程问题要问你