Обновить выбор из второго UITableView в исходном UITableView - PullRequest
0 голосов
/ 04 апреля 2011

Я не могу обновить свой первый UITableView с настройкой, заданной во втором UITableView.

Пользователь щелкает строку в firstTableView, вызывая отображение secondTableView. Когда пользователь выбирает строку, secondTableView исчезает, а firstTableView появляется снова. Однако данные не обновляются.

Я попытался использовать следующее в firstTableView:

- (void) viewWillAppear:(BOOL)animated {

    // (verified it's defenitely section 2, row 0 by logging it before and after...)
    // (also verified that the source data has been updated before viewWillAppear is called...)

    NSIndexPath *durPath = [NSIndexPath indexPathForRow:0 inSection:2];
    NSArray *paths = [NSArray arrayWithObject:durPath];

   [self.firstTableView reloadRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationNone];

    // If I use some row animation, I can clearly see that the correct row is being animated, it's just not being updated.

}

Но ярлык не обновляется. Очевидно, я что-то упустил. Оба представления являются модальными контроллерами представления.

Вот моя конструкция клетки:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [firstTableView dequeueReusableCellWithIdentifier:CellIdentifier];

    UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(150.0, 15.0, 120.0, 17.0)];
    myLabel.backgroundColor = [UIColor clearColor];
    myLabel.font = [UIFont systemFontOfSize:14];
    myLabel.textAlignment = UITextAlignmentLeft;

    static NSString* kConstants[] = {kOption0,kOption1,kOption2,kOption3,kOption4,kOption5,kOption6,kOption7,kOption8,kOption9,kOption10,nil};

    if (cell == nil) {

        cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

        if (indexPath.section == 2) {
            [cell addSubview:myLabel];
        }   
    }

    switch (indexPath.section) {        
        case 0: 
            // … deal with a bunch of UISwitches        
            break;  
        case 1:
            // … deal with section 1 stuff
            break;
        case 2: 
        {
            NSLog(@"Verify that intType has in fact been changed here: %i, %@",intType, kConstants[intType]);

            // Even though intType and the constant string reflects the correct (updated) values when returning from secondTableView, myLabel.text does not change, ie: it's correct one line above, but not correct one line below. The myLabel.text is just not updating to the new value.

            myLabel.text = kConstants[intType];

            cell.textLabel.text = @"Choose Some Value:";
            cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
        }
            break;
        case 3:     
            // … deal with section 3 stuff
            break;
    }
    [myLabel release];
    return cell;
}

Ответы [ 3 ]

1 голос
/ 05 апреля 2011

Я наконец-то обнаружил проблему: при перезагрузке ячейки значение (cell == nil) будет ложным, поскольку ячейка уже присутствует.

Кроме того, даже если значение (cell == nil) равно true, вы добавляетеновое подпредставление, не изменяя существующее - это не только проблема управления памятью, но и делает текст нечитаемым, размещая метки друг над другом.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    static NSString* kConstants[] = {kOption0,kOption1,kOption2,kOption3,kOption4,kOption5,kOption6,kOption7,kOption8,kOption9,kOption10,nil};

    if (cell == nil) {

        cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

        UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(150.0, 15.0, 120.0, 17.0)];
        myLabel.backgroundColor = [UIColor clearColor];
        myLabel.font = [UIFont systemFontOfSize:14];
        myLabel.textAlignment = UITextAlignmentLeft;
        myLabel.tag = 1;
        myLabel.text = kConstants[intType];

        [cell addSubview:myLabel];
        [myLabel release];

        cell.textLabel.text = @"Label";
        cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
    } else {
        UILabel *myLabel = (UILabel *)[cell viewWithTag:1];
        myLabel.text = kConstants[intType];
    }
    return cell;
}
1 голос
/ 05 апреля 2011

Для тех, кто сталкивается с этим в будущем, я публикую здесь полное решение моего вопроса, особенно спасибо Antal за то, что он показал мне основную ошибку в построении моей таблицы.В общем, таблица - плохая идея, потому что она заставляет таблицу или ее части загружаться дважды.Правильный способ сделать это - использовать метод Delegate второго контроллера представления, который я сделал здесь.

Я публикую соответствующие части двух контроллеров представления.Оба настроены как UViewControllers, а не как UITableViewControllers.Оба являются модальными представлениями.

Я надеюсь, что кто-то найдет это полезным.

//    
//  FirstViewController.h
//

#import <UIKit/UIKit.h>
#import "SecondViewController.h"

@interface FirstViewController : UIViewController 
<SecondViewControllerDelegate, UITableViewDataSource, UITableViewDelegate>
{
    UITableView  *firstTableView;
    NSArray      *myArray;
}

@property (nonatomic, retain) IBOutlet UITableView *firstTableView;
@property (nonatomic, assign) NSArray *myArray;

- (void) didSelectOptions:(NSInteger *)intOptionType;
- (void) didCancelOptions;

@end


//
//  FirstViewController.m
//

#import "FirstViewController.h"
#import "Constants.h"

@implementation FirstViewController

@synthesize firstTableView;
@synthesize myArray;

- (void) viewDidLoad {

    // Load the array that contains the option names, in this case, constants stored in Constants.h

    myArray = [[NSArray alloc] initWithObjects:kStoredRowName0, kStoredRowName1, kStoredRowName2, nil];

}

// do everything else to deal with the first view . . .

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    // Use the indexPath.section as the identifier since objects in each section share unique construction, ie: switches, etc.

    NSString *identifier = [NSString stringWithFormat: @"%d", [indexPath indexAtPosition: 0]];

    // In this example I'm storing the important integer value in NSUserDefaults as kStoredConstant

    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

    UITableViewCell *cell = [firstTableView dequeueReusableCellWithIdentifier:identifier];

    if (cell == nil) {

        cell = [[[UITableViewCell alloc]
                initWithStyle: UITableViewCellStyleDefault
                reuseIdentifier:identifier]
                autorelease];

        switch (indexPath.section) {
        case 0:                     // OnOff Controls using UISwitch
            NSLog(@"Section 0");
            // set up switches …
            break;
        case 1:                     // Segmented Controls using UISegmentedControl
            NSLog(@"Section 1");
            // set up segmented controls …
            break;
        case 2:                     // Label that will be selected from SecondViewContoller
            NSLog(@"Section 2");
            // set up label
            UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(150.0, 15.0, 120.0, 17.0)];
                myLabel.backgroundColor = [UIColor clearColor];
                myLabel.font = [UIFont systemFontOfSize:14];
                myLabel.textColor = [UIColor colorWithRed:0.25 green:0.0 blue:0.0 alpha:1.0];
                myLabel.textAlignment = UITextAlignmentLeft;
                myLabel.tag = indexPath.section;
                myLabel.text = [myArray objectAtIndex:[userDefaults integerForKey:kStoredConstant]];

                [cell addSubview:myLabel];
                [myLabel release];

            cell.textLabel.text = @"Choose A Value:";
            cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
            break;
        }

    } else {

        switch (indexPath.section) {
        case 0:                     // OnOff Controls using UISwitch
            NSLog(@"Section 0");
            break;
        case 1:                     // Segmented Controls using UISegmentedControl
            NSLog(@"Section 1");
            break;
        case 2:                     // Label that will be selected from SecondViewContoller
            {
            NSLog(@"Section 2");
            UILabel *myLabel = (UILabel *)[cell viewWithTag:indexPath.section];
            myLabel.text = [myArray objectAtIndex:[userDefaults integerForKey:kStoredConstant]];
            }
            break;
        }

    }

    // Format the cell label properties for all cells

    cell.textLabel.backgroundColor = [UIColor clearColor];
    cell.textLabel.font = [UIFont systemFontOfSize:14];
    cell.textLabel.textColor = [UIColor colorWithRed:0.25 green:0.0 blue:0.0 alpha:1.0];
    cell.textLabel.highlightedTextColor = [UIColor colorWithRed:1.0 green:1.0 blue:0.9 alpha:1.0];

    return cell;

}

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

    // Un-highlight the selected cell

    [firstTableView deselectRowAtIndexPath:indexPath animated:YES];

    switch (indexPath.section) {
    case 0:                     // Deal with changes in UISwitch Controls
        NSLog(@"Section 0");
        break;
    case 1:                     // Deal with changes in Segmented Controls
        NSLog(@"Section 1");
        break;
    case 2:                     // Launch the SecondViewContoller to select a value
        {
        SecondViewController *secondViewController = [[SecondViewController alloc] init];
        secondViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
        secondViewController.secondViewControllerDelegate = self;
        [self presentModalViewController:secondViewController animated:YES];
        [secondViewController release];
        }
        break;
    }

}

#pragma mark -
#pragma mark SecondViewControllerDelegate

- (void) didSelectOptions:(NSInteger *)intOptionType {

    // User selected a row in secondTableView on SecondViewController, store it in NSUserDefaults

    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    [userDefaults setInteger:(int)intOptionType forKey:kStoredConstant];
    [userDefaults synchronize];

    // Reload only the row in firstTableView that has been changed, in this case, row 0 in section 2
    [self.firstTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:2]]withRowAnimation:UITableViewRowAnimationNone];

    [self dismissModalViewControllerAnimated:YES];

}

- (void) didCancelOptions {

    // User didn't select a row, instead clicked a done or cancel button on SecondViewController

    [self dismissModalViewControllerAnimated:YES];

}

// Make sure and release Array and Table


//
//  SecondViewController.h
//

#import <UIKit/UIKit.h>

@protocol SecondViewControllerDelegate <NSObject>
    - (void) didCancelOptions;
    - (void) didSelectOptions:(NSInteger *)optionType;
@end

@interface SecondViewController : UIViewController
    <UITableViewDataSource, UITableViewDelegate>
{
    NSArray             *myArray;
    UITableView         *secondTableView;

    id secondViewControllerDelegate;
}

@property (nonatomic, retain) NSArray *myArray;
@property (nonatomic, retain) IBOutlet UITableView *secondTableView;
@property (nonatomic, assign) id<SecondViewControllerDelegate> secondViewControllerDelegate;

- (IBAction) doneViewingOptions:(id)sender;    // This is wired to a Cancel or a Done Button

@end


//
//  SecondViewController.m
//

#import "SecondViewController.h"
#import "Constants.h"

@implementation SecondViewController

@synthesize secondViewControllerDelegate;
@synthesize myArray;
@synthesize secondTableView;

- (void) viewDidLoad {

    // Load the array that contains the option names, in this case, constants stored in Constants.h

    myArray = [[NSArray alloc] initWithObjects:kStoredRowName0, kStoredRowName1, kStoredRowName2, nil];

}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    // Build a default table. This one is simple so the following is the only important part:

    cell.textLabel.text = [myArray objectAtIndex:indexPath.row];

}

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

    // Return the changed row value to the FirstViewController using secondViewControllerDelegate

    [self.secondViewControllerDelegate didSelectOptions:(NSInteger *)indexPath.row];

}

- (IBAction) doneViewingOptions:(id)sender {

    // User didn't select a row, just clicked Done or Cancel button

    [self.secondViewControllerDelegate didCancelOptions];

}

// Make sure and release Array and Table
0 голосов
/ 05 апреля 2011

Вы можете использовать reloadRowsAtIndexPaths, чтобы перезагрузить определенную строку (или строки) и избежать перезагрузки всей таблицы.

Что касается метки, которая отображает строковое значение, не могли бы вы опубликовать код, чтобы мы могли видеть?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...