【问题标题】:multiple checkmarks from多个复选标记来自
【发布时间】:2012-12-02 21:24:50
【问题描述】:

我正在关注的教程:http://www.appcoda.com/ios-programming-tutorial-create-a-simple-table-view-app/

我创建了一个包含 16 个单元格的表格视图。当我选择一行时,它会在上面显示复选标记。

但是当我滚动表格视图时,列表下方的另一个单元格上还会显示一个复选标记。这对选定的任何单元格重复。

    #import "FlightChecklistViewController.h"

    @interface FlightChecklistViewController ()

    @end

    @implementation FlightChecklistViewController

{
    NSArray *tableData;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    // Initialize table data
    tableData = [NSArray arrayWithObjects:@"Egg Benedict", @"Mushroom Risotto", @"Full Breakfast", @"Hamburger", @"Ham and Egg Sandwich", @"Creme Brelee", @"White Chocolate Donut", @"Starbucks Coffee", @"Vegetable Curry", @"Instant Noodle with Egg", @"Noodle with BBQ Pork", @"Japanese Noodle with Pork", @"Green Tea", @"Thai Shrimp Cake", @"Angry Birds Cake", @"Ham and Cheese Panini", nil];

}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [tableData count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *simpleTableIdentifier = @"SimpleTableItem";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];

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

    cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
    return cell;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UIAlertView *messageAlert = [[UIAlertView alloc]
                                    initWithTitle:@"Row Selected" message:@"You've selected a row" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];

    // Display Alert Message
    [messageAlert show];

    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    cell.accessoryType = UITableViewCellAccessoryCheckmark;

    [tableView deselectRowAtIndexPath:indexPath animated:YES];

}

@end

有什么建议吗?

【问题讨论】:

    标签: objective-c ios cocoa-touch uitableview


    【解决方案1】:

    您需要以某种方式存储有关所选行索引路径的信息。 并根据它填充您的单元格。

    #import "ViewController.h"
    
    @interface ViewController ()
    @property (nonatomic, strong) NSMutableArray *selectedCells;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        self.selectedCells = [NSMutableArray array];
    }
    
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return 100;
    }
    
    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *unifiedID = @"aCellID";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:unifiedID];
        if (!cell) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:unifiedID];
        }
    
        cell.textLabel.text = [NSString stringWithFormat:@"%u", indexPath.row];
    
        //if the indexPath was found among the selected ones, set the checkmark on the cell
        cell.accessoryType = ([self isRowSelectedOnTableView:tableView atIndexPath:indexPath]) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
        return cell;
    
    }
    
    //if a row gets selected, toggle checkmark    
    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
        if([self isRowSelectedOnTableView:tableView atIndexPath:indexPath]){
            [self.selectedCells removeObject:indexPath];
            cell.accessoryType = UITableViewCellAccessoryNone;
        } else {
            [self.selectedCells addObject:indexPath];
            cell.accessoryType = UITableViewCellAccessoryCheckmark;
        }
    }
    
    -(BOOL)isRowSelectedOnTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath
    {
        return ([self.selectedCells containsObject:indexPath]) ? YES : NO;
    }
    
    @end
    

    你可以在github找到完整的示例代码

    【讨论】:

      【解决方案2】:

      问题是细胞被重复使用。因此,如果您将复选标记附件视图添加到更上方的单元格,它将在该单元格被更下方重复使用时再次出现。添加/删除复选标记时,您应该将哪些已复选标记保存在与表格行相关的某个位置的数组中。然后,当您给表格视图一个新单元格时,您可以确定它是否需要复选标记并进行设置。

      【讨论】:

        【解决方案3】:

        我最近在使用我的一个应用时遇到了同样的问题,我通过这样做解决了这个问题:

        @property (nonatomic, strong) NSArray *list;
        
        - (void)viewDidLoad
        {
            [super viewDidLoad];
        
            self.list = [[NSArray alloc] initWithObjects:@"foo", @"bar", nil];
        }
        
        - (NSString *)SettingsPlist
        {
            NSString *paths = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
            NSString *PlistPath = [paths stringByAppendingPathComponent:@"Settings.plist"];
            return PlistPath;
        }
        
        - (NSInteger)tableView:(UITableView *)tableView
         numberOfRowsInSection:(NSInteger)section
        {
            return [[self list] count];
        }
        
        - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
        {
            NSString *contentForThisRow = [[self list] objectAtIndex:[indexPath row]];
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
        
            if(cell == nil)
            {
                cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
            }
        
            NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:[self SettingsPlist]];
        
            NSString *row = [NSString stringWithFormat:@"%d",indexPath.row];
        
            if([[dict objectForKey:row]isEqualToString:@"0"])
            {
                cell.accessoryType = UITableViewCellAccessoryNone;
            }
            else
            {
                cell.accessoryType = UITableViewCellAccessoryCheckmark;
            }
        
            [[cell textLabel] setText:contentForThisRow];
        
            return cell;
        }
        
        - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
        {
            NSMutableDictionary *plist = [NSMutableDictionary dictionaryWithContentsOfFile:[self SettingsPlist]];
        
            UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
        
            NSString *row = [NSString stringWithFormat:@"%d",indexPath.row];
        
            if(cell.accessoryType == UITableViewCellAccessoryNone)
            {
                cell.accessoryType = UITableViewCellAccessoryCheckmark;
                NSString *on = @"1";
                [plist setObject:on forKey:row];
                [plist writeToFile:[self SettingsPlist] atomically:YES];
            }
            else if(cell.accessoryType == UITableViewCellAccessoryCheckmark)
            {
                cell.accessoryType = UITableViewCellAccessoryNone;
                NSString *off = @"0";
                [plist setObject:off forKey:row];
                [plist writeToFile:[self SettingsPlist] atomically:YES];
            }
            [tableView deselectRowAtIndexPath:indexPath animated:YES];
        }
        

        【讨论】:

        • 这是一个非常糟糕的解决方案,因为您无法重复使用单元格。
        • @troop231 这是不正确的。您应该只为每种类型的单元格设置一个标识符。这完全阻止了单元重用,并显示了对机制的完全误解。以这种方式禁用单元重用可以消除问题,但完全违背了将标识符分配给单元的目的。
        • 又错了。如果正确完成,if 将完美运行。你似乎还没有完全理解细胞的重用。
        • 现在您的答案根本没有回答问题。复选标记在哪里?为什么这有助于解决问题?
        • 单元重用仍然存在问题:当您检查单元的附件类型而不是 indexPath 时,您仍然会遇到问题,该 cel 将被重新用于不同的索引路径。因此,之前未点击的行将切换其复选标记外观。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-08-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-30
        • 2023-04-04
        • 1970-01-01
        相关资源
        最近更新 更多