每个分段表行的附件视图中的 UISwitch
Posted
技术标签:
【中文标题】每个分段表行的附件视图中的 UISwitch【英文标题】:UISwitch in each sectioned table row's accessoryView 【发布时间】:2013-07-19 14:04:48 【问题描述】:我是 ios 编码的新手,我在 SO 中环顾四周并尝试了几种方法来解决这个问题,但似乎没有任何效果。我确信这是因为我的一些愚蠢的错误:-)
我有一个分区表,总共大约 25 行,分为 2 个部分。
每个cell.accessoryView
都有一个开关,我尝试在开关状态更改时将其存储在NSArray
中,但是在该索引处记录数组内容在任何情况下都会奇怪地返回0
。
(数组被实例化为TableViewController
的属性(nonatomic, readwrite)
,并合成)
显然,当我上下滚动表格时,所有开关都返回默认的OFF
状态。
感谢您的帮助!
- (void)viewDidLoad
[super viewDidLoad];
//countries dict and switch state array init..
self.countries = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"countries" ofType:@"plist"]];
NSNumber *b = [NSNumber numberWithBool:NO];
for (int i=0; i<210; i++)
[statiSwitch addObject:b];
NSLog(@"%d", [[statiSwitch objectAtIndex:i] integerValue]);
//tableview drawing..
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"CellWithSwitch";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
NSString *continent = [self tableView:tableView titleForHeaderInSection:indexPath.section];
NSString *country = [[self.countries valueForKey:continent] objectAtIndex:indexPath.row];
//Simple tag calculation...
NSInteger tagOb = indexPath.section * 100 + indexPath.row;
UISwitch *mySwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
[mySwitch addTarget:self action:@selector(switchChange:) forControlEvents:UIControlEventValueChanged];
mySwitch.tag = tagOb;
if ([statiSwitch count] > tagOb)
[mySwitch setOn:[[statiSwitch objectAtIndex:tagOb] boolValue] animated:NO];
cell.textLabel.text = country;
cell.accessoryView = mySwitch;
return cell;
然后是切换状态变化时调用的方法:
- (void) switchChange:(UISwitch *)sender
NSNumber *c = [NSNumber numberWithBool:sender.on];
[statiSwitch replaceObjectAtIndex:sender.tag withObject:c];
NSLog(@"switch tag is: %i and state is: %d", sender.tag, sender.on);
NSLog(@"switch states array value: %d", [[statiSwitch objectAtIndex:sender.tag] integerValue]);
【问题讨论】:
尝试子类化 UITableViewCell,并将整个单元格存储在一个数组中,而不仅仅是开关值。然后,随着 tableView 滚动,将单元格拉出数组而不是出队。 那么,我应该设置一个包含所有(比方说)20 个单元对象的数组,包括附件开关,然后让- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
方法从该数组中取出单元?跨度>
你应该继承 UITableViewCell,并在该类中处理切换操作。这就像使用对象类来存储数据一样。
好的,我试试看!谢谢! (如果您建议我为处理开关操作的子类提供一些示例代码.. 那会很棒:-)
您是在做故事板,还是全部用代码完成?使用故事板,这是一个非常简单的过程。
【参考方案1】:
我认为您在向其添加对象之前忽略了初始化 statiSwitch。
在for循环前的viewDidLoad中,添加这一行
statiSwitch = [NSMutableArray array];
【讨论】:
我将继续使用 int 数组。但你是对的@Rick,我忘了在上面的代码中初始化数组:statiSwitch
被声明为 @987654323 的属性@,合成等等,这就是为什么我认为没有必要再次分配和初始化它。
别担心,记住这一点。在很多情况下你仍然需要使用 NSMutableArrays。如果你想学习 iOS 编程,你不能总是坚持使用 C。干杯。【参考方案2】:
-
设置自定义单元类。
在情节提要中创建一个原型单元,并在其中放置一个开关。
将原型单元设置为您的自定义类,并设置重用标识符。
将开关连接到自定义单元类中的 IBOutlet。
(如果您希望您的单元能够通信,还可以设置 @protocol 和委托)
现在是棘手/骇人听闻的部分:
在 -viewDidLoad 中:
for (int i = 0; i < [self.cellDataArray count]; ++i)
CustomCell *cell;
cell = [self.tableView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:nil];
cell.delegate = self;
[self.cellsArray addObject:cell];
在您的 cellForRowAtIndexPath 中,执行以下操作:
cell = self.cellsArray[indexPath.row]; // 如果使用 collectionView,则为 .item
由于开关连接到每个单元,因此您需要在 CustomCell 类中提供一个方法,该方法将基于开关执行某些操作,并且可能会向委托类发送调用。
【讨论】:
非常感谢!我会尽力让你知道。 我尝试过这种方式,单元格数组和其他部分都很好,但是我在cell = [self.tableView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:nil];
行中收到了编译器警告,将其放在 -viewDidLoad:
方法中。它告诉我tableView
没有dequeueReusableCellWithReuseIdentifier:
的任何标识符。我用一个解决方法解决了这个问题,使用一个简单的 int 数组来存储开关值。不知道它不能在 NSObjects 的 NSMutableArray 中存储值。有关详细信息,请参阅我的答案。
如果您将@"Cell" 更改为@"CellWithSwitch",您就不会遇到这个问题。
在我的回答中我写了“@Cella”而不是“@CellWithSwitch”,因为那是我在情节提要和编辑的“表格视图控制器”.m 文件中使用的新标识符【参考方案3】:
我使用了一个简单的int array
来存储开关值,它似乎比由具有switchTag 和switchState 属性的对象组成的NSMutableArray
工作得更好,这是我以前做的。
代码如下:
- (void)viewDidLoad
//[here goes the code to retrieve my table data from a dictionary, getting sections and rows]
//int array iniazialization, with zeros to have switches set at OFF at beginning
for (int i = 0; i < 300; i++)
switchStates[i] = 0;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"Cella";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
//Cell drawing..
NSString *continent = [self tableView:tableView titleForHeaderInSection:indexPath.section];
NSString *country = [[self.countries valueForKey:continent] objectAtIndex:indexPath.row];
cell.textLabel.text = country;
//Calculate the tag to be assigned to the switches..
switchTag = indexPath.section * 100 + indexPath.row
UISwitch *mySwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
[mySwitch addTarget:self action:@selector(switchChange:) forControlEvents:UIControlEventValueChanged];
mySwitch.tag = switchTag;
mySwitch.on = switchStates[switchTag];
cell.accessoryView = mySwitch;
return cell;
//switch change action..
- (void) switchChange:(UISwitch *)sender
switchStates[sender.tag] = sender.on;
现在我“只是”将这些开关值存储在核心数据中。在我即将提出的问题中见 :-)
【讨论】:
以上是关于每个分段表行的附件视图中的 UISwitch的主要内容,如果未能解决你的问题,请参考以下文章