Заполнение UITableView с использованием NSUserdefaults - PullRequest
0 голосов
/ 30 сентября 2018

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

Я искал в GoogleНекоторое время я смотрел на документы Apple, но я все еще не понимаю, как правильно заполнить UITableView.

Первая проблема.Где взять камеру?Мне нужно сделать собственную ячейку для отображения данных.Кажется, что решение заключается в использовании пера, но как я могу загрузить его на другой контроллер представления?

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

Третья проблема.Я хочу иметь разные разделы (каждый раздел имеет свой вид ячейки для отображения), с разными колонтитулами.Как всегда, здесь мне не хватает документации.Как мне этого добиться?

Четвертая и самая важная проблема.У меня нет идеи о том, как загрузить клетки.По-видимому, это делает cellForRowAtIndexPath, но я не уверен, как ему это удается.

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

#import "profileViewController.h"
#import "../Objs/CCProfileObject.h"

@interface profileViewController ()
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (strong, nonatomic) IBOutlet UITableViewCell *proxySampleCell;
@property (strong, nonatomic) IBOutlet UITableViewCell *ccSampleCell;
@end

@implementation profileViewController
@synthesize tableView;

- (void)viewDidLoad{
    // Dark mode, you can skip all of this
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(changeColor:)
                                                 name:@"darkToggle" object:nil];

    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    if([userDefaults boolForKey:@"darkMode"] == YES){
        [self changeColor:nil];
    }

}

- (void)viewDidAppear:(BOOL)animated{

    // Display profiles
    NSData *arrayData = [[NSUserDefaults standardUserDefaults] objectForKey:@"profileArray"];
    NSArray *profiles = [NSKeyedUnarchiver unarchiveObjectWithData:arrayData];

    for(NSObject *profile in profiles){
        if([profile class] == [CCProfileObject class])
        {
            CCProfileObject *ccProfile = (CCProfileObject*) profile;
            printf("%s\n", [ccProfile.getName UTF8String]);
            // Retrieve info from the object
            // Duplicate cell
            // Change appropriate labels
            // Add cell to a specific section
        }
        // Different types of cells will be added later
        // Concept is the same, what changes is the specific section and cell to duplicate

    }
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    if(indexPath.section == 1){
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"reusableShippingCell"];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"reusableShippingCell"];
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
        }

        cell.textLabel.text = @"aldo";

        return cell;
    }



    return nil;
}
// This should be the only part that actually works (I use the same class twice because proxy and shipping are not yet done)
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    // Display profiles
    NSData *arrayData = [[NSUserDefaults standardUserDefaults] objectForKey:@"profileArray"];
    NSArray *profiles = [NSKeyedUnarchiver unarchiveObjectWithData:arrayData];
    NSMutableArray *sectionData = [[NSMutableArray alloc]init];

    for(NSObject *profile in profiles){
        // Credit
        if([profile class] == [CCProfileObject class])
        {
            [sectionData insertObject:@1 atIndex:0];
        }
        // Shipping
        else if([profile class] == [UIImage class])
        {
            [sectionData insertObject:@1 atIndex:1];
        }
        // Proxy
        else if([profile class] == [UIImage class])
        {
            [sectionData insertObject:@1 atIndex:2];
        }
    }

    int toReturn = 0;
    for(int i = 0; i < [sectionData count]; i++){
        toReturn += [[sectionData objectAtIndex:i] integerValue];
    }
    return toReturn;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    // Credit card section
    if(section == 0){
        return 1;
    } else if (section == 1){
        return 2;
    } else {
        return 3;
    }
}

`Assertion failure in -[UITableView _configureCellForDisplay:forIndexPath:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3698.52.10/UITableView.m:9453
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView (<UITableView: 0x16106d000; frame = (0 0; 375 812); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x1d0243bd0>; layer = <CALayer: 0x1d0030f60>; contentOffset: {0, -88}; contentSize: {375, 117}; adjustedContentInset: {88, 0, 83, 0}>) failed to obtain a cell from its dataSource (<profileViewController: 0x15ff14c70>)
First throw call stack:
(0x1837f6d8c 0x1829b05ec 0x1837f6bf8 0x1841e6fa0 0x18d4975b0 0x18d4941e8 0x18d493e00 0x18d492b1c 0x18d48e668 0x18d3cb770 0x18796d25c 0x1879713ec 0x1878ddaa0 0x1879055d0 0x18d7b56b4 0x18379f2bc 0x18379ea7c 0x18379c7b0 0x1836bcda8 0x18569f020 0x18d69d78c 0x1048a4f90 0x18314dfc0)
libc++abi.dylib: terminating with uncaught exception of type NSException

Вы не обязаны решать все мои проблемы одним ответом.Достаточно даже решить проблему / объяснить, что мне нужно сделать, поскольку это позволит мне хотя бы немного продвинуться вперед.

Ответы [ 2 ]

0 голосов
/ 01 октября 2018

Во-первых, вам не нужен пользовательский кончик для UITableViewCell, если у вас нет действительно сложной ячейки.Вместо этого вы можете напрямую создать макет своей ячейки, используя Prototype Cells в UITableView 's Attributes inspector.Просто дайте Prototype Cells число и спроектируйте соответствующий макет ячейки внутри UITableView вида.Не забудьте установить identifier для каждого из них, что поможет вам загрузить правильную разметку в cellForRowAtIndexPath.

Для простой разметки ячейки вы можете указать для каждого из элементов ячейки a tagчисло.Это поможет вам получить к ним доступ всякий раз, когда они вам понадобятся, например:

UILabel *label = [cell viewWithTag:100];

Каждому UITableView требуется DataSource, вы реализуете UITableViewDataSource для предоставления:

  1. Количество разделов для вашей таблицы
  2. Количество элементов для каждого раздела
  3. Содержимое для отдельной ячейки

Вы только что сделали это в предоставленном исходном коде, за исключением одной вещи: cellForRowAtIndexPath требует возврата UITableViewCell, а не nil.Если вы вернете nil, будет сгенерировано исключение.

Итак, рабочий cellForRowAtIndexPath может выглядеть так:

@implementation ViewController {
    NSArray *data;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    // You load your data from NSUserDefault here
    data = [self loadDataFromNSUserDefault];
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *cellIdentifier = @"defaultCell";
    if (indexPath.section == 0) {
        cellIdentifier = @"customCell1";
    } else if (indexPath.section == 1) {
        cellIdentifier = @"customCell2";
    }

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

    // Access your view's children using their `tag`
    UILabel *title = [cell viewWithTag:100];
    UIImageView *icon = [cell viewWithTag:101];

    // Set content
    title.text = [[data objectAtIndex:indexPath.row] objectForKey:@"title"];
    icon.image = [UIImage imageNamed:[[data objectAtIndex:indexPath.row] objectForKey:@"icon"]];

    return cell;
}
0 голосов
/ 01 октября 2018

Ваша основная проблема заключается в этой строке - if (indexPath.section == 1) - нумерация разделов начинается с 0.Таким образом, вы возвращаете nil для ячеек в вашем первом разделе (номер 0) и в любом разделе, выходящем за пределы второго (номер 1), что приводит к сбою.Вы должны никогда вернуть nil из cellForRow.

При этом - я все же рекомендую вам прочитать ссылки, приведенные в комментариях, вы все равно можете узнать что-то ценное и / или интересное.

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