【问题标题】:TableView in iOS Settings BundleiOS 设置包中的 TableView
【发布时间】:2014-09-12 05:36:41
【问题描述】:

我是 iOS 开发的新手,我正在整理如何在设置包上创建一个带有复选标记的表格视图,如下所示:

有什么办法吗?还是仅适用于特定的 iOS 批准应用?

期待答案。谢谢。

【问题讨论】:

  • 查看设置包的“多值”选项。

标签: ios settings


【解决方案1】:

您可以通过多值元素来实现这一点。当用户点击包含多值元素的首选项时,设置应用程序会显示一个新页面,其中包含可供选择的可能值。如果需要,请在 Google 上搜索教程(设置包的多值选项)。

详情如下:PSMultiValueSpecifier

【讨论】:

    【解决方案2】:

    如果我猜对了,并且您想知道如何在应用程序外部和 iOS 设置中显示设置,请查看this tutorial。它应该可以帮助您入门。

    摘自以下链接:

    我一直在四处寻找,但找不到样板解决方案,因此为此创建了自己的代码。支持Title、Group、Text Field、Multi Value、Toggle Switch等设置类型。

    它不支持滑块。

    此解决方案确实支持纵向和横向模式,还可以处理设备方向的更改。

    首先,我假设您使用以下代码从 Settings.bundle 中读取默认值。

    - (void) registerDefaultsFromSettingsBundle
    {
        NSLog(@"Registering default values from Settings.bundle");
        NSUserDefaults * defs = [NSUserDefaults standardUserDefaults];
        [defs synchronize];
    
        NSString *settingsBundle = [[NSBundle mainBundle] pathForResource: @"Settings" ofType: @"bundle"];
    
        if(!settingsBundle)
        {
            NSLog(@"Could not find Settings.bundle");
            return;
        }
    
        NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[settingsBundle stringByAppendingPathComponent: @"Root.plist"]];
        NSArray *preferences = [settings objectForKey: @"PreferenceSpecifiers"];
        NSMutableDictionary *defaultsToRegister = [[NSMutableDictionary alloc] initWithCapacity:[preferences count]];
    
        for (NSDictionary *prefSpecification in preferences)
        {
            NSString *key = [prefSpecification objectForKey:@"Key"];
            if (key)
            {
                // check if value readable in userDefaults
                id currentObject = [defs objectForKey: key];
                if (currentObject == nil)
                {
                    // not readable: set value from Settings.bundle
                    id objectToSet = [prefSpecification objectForKey: @"DefaultValue"];
                    [defaultsToRegister setObject: objectToSet forKey: key];
                    NSLog(@"Setting object %@ for key %@", objectToSet, key);
                }
                else
                {
                    // already readable: don't touch
                    NSLog(@"Key %@ is readable (value: %@), nothing written to defaults.", key, currentObject);
                }
            }
        }
    
        [defs registerDefaults: defaultsToRegister];
        [defs synchronize];
    }
    

    好的,现在您需要 2 节课。 SettingsTableViewController 和 MultiValueTableViewController。

    SettingsTableViewController.h

        //
    //  SettingsTableViewController.h
    //  Cochlear App
    //
    //  Created by Gilles Lesire on 16/07/14.
    //  Free to use
    //
    
    #import <UIKit/UIKit.h>
    #import "MultiValueTableViewController.h"
    
    @interface SettingsTableViewController : UITableViewController <MultiValueDelegate> {
        NSMutableArray *labelViews;
        NSMutableArray *textViews;
        NSMutableArray *settingsKeys;
        NSMutableArray *settingsTableSections;
        NSMutableArray *settingsTableData;
    }
    
    @end
    

    SettingsTableViewController.m

    //
    //  SettingsTableViewController.m
    //  Cochlear App
    //
    //  Created by Gilles Lesire on 16/07/14.
    //  Free to use
    ////
    
    #import "SettingsTableViewController.h"
    
    #define labelCGRectX 25
    #define labelCGRectY 25
    #define labelCGRectWidth 140
    #define labelCGRectHeight 21
    
    #define typeGroup @"PSGroupSpecifier"
    #define typeTitle @"PSTitleValueSpecifier"
    #define typeToggleSwitch @"PSToggleSwitchSpecifier"
    #define typeMultiValue @"PSMultiValueSpecifier"
    #define typeTextField @"PSTextFieldSpecifier"
    
    @interface SettingsTableViewController ()
    
    @end
    
    @implementation SettingsTableViewController
    
    - (id)initWithStyle: (UITableViewStyle)style
    {
        self = [super initWithStyle: style];
    
        if (self) {
        }
    
        return self;
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        // Track rotation changes
        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(deviceOrientationDidChange) name: UIDeviceOrientationDidChangeNotification object: nil];
    
        // Avoid tab bar to overlap tableview
        self.edgesForExtendedLayout = UIRectEdgeAll;
        self.tableView.contentInset = UIEdgeInsetsMake(0.0f, 0.0f, CGRectGetHeight(self.tabBarController.tabBar.frame), 0.0f);
    
        // Custom initialization
        labelViews = [NSMutableArray arrayWithObjects: nil];
        textViews = [NSMutableArray arrayWithObjects: nil];
        settingsTableSections = [NSMutableArray arrayWithObjects: nil];
        settingsTableData = [NSMutableArray arrayWithObjects: nil];
        settingsKeys = [NSMutableArray arrayWithObjects: nil];
    
        NSLog(@"Created arrays");
    
    
        NSString *settingsBundle = [[NSBundle mainBundle] pathForResource: @"Settings" ofType: @"bundle"];
    
        if(!settingsBundle) {
    
            NSLog(@"Could not find Settings.bundle");
    
        } else {
    
            NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[settingsBundle stringByAppendingPathComponent: @"Root.plist"]];
            NSArray *preferences = [settings objectForKey: @"PreferenceSpecifiers"];
            NSMutableDictionary *defaultsToRegister = [[NSMutableDictionary alloc] initWithCapacity: [preferences count]];
    
            for (NSDictionary *prefSpecification in preferences) {
    
                NSLog(@"%@", prefSpecification);
    
                NSString *title = [prefSpecification objectForKey: @"Title"];
                NSString *type = [prefSpecification objectForKey: @"Type"];
    
                if([type isEqualToString: typeGroup]) {
    
                    // Create new section
                    [settingsTableSections addObject: title];
                    NSMutableArray *newSection = [NSMutableArray arrayWithObjects: nil];
                    [settingsTableData addObject: newSection];
    
                } else {
    
                    // Add specification to last section
                    [[settingsTableData objectAtIndex: ([settingsTableData count] - 1)] addObject:prefSpecification];
    
                }
            }
        }
    }
    
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    #pragma mark - Table view data source
    
    - (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView
    {
        // Return the number of sections.
        return [settingsTableSections count];
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        // Return the number of rows in the section.
        return [[settingsTableData objectAtIndex: section] count];
    }
    
    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
    {
        return [settingsTableSections objectAtIndex: section];
    }
    
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
        // Get the dictionary item
        NSDictionary *prefSpecification = [[settingsTableData objectAtIndex: indexPath.section] objectAtIndex: indexPath.row];
    
        NSString *title = [prefSpecification objectForKey: @"Title"];
        NSString *key = [prefSpecification objectForKey: @"Key"];
        NSString *type = [prefSpecification objectForKey: @"Type"];
    
        // Define cell
        UITableViewCell *cell;
    
        // Keep tag of keys
        [settingsKeys addObject: key];
        int tag = [settingsKeys count] - 1;
    
        if([type isEqualToString: typeTitle]) {
    
            // Create cell
            cell = [tableView dequeueReusableCellWithIdentifier: @"Cell" forIndexPath:indexPath];
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
    
            // Set title
            cell.textLabel.text = title;
    
            // Add label
            UILabel *labelView = [[UILabel alloc] initWithFrame: CGRectMake(labelCGRectX, labelCGRectY, labelCGRectWidth, labelCGRectHeight)];
            labelView.text = [[NSUserDefaults standardUserDefaults] objectForKey: key];
            labelView.textAlignment = NSTextAlignmentRight;
            labelView.textColor = [UIColor grayColor];
            cell.accessoryView = labelView;
    
        }
        if([type isEqualToString: typeToggleSwitch]) {
    
            // Create cell
            cell = [tableView dequeueReusableCellWithIdentifier: @"Cell" forIndexPath:indexPath];
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
    
            // Set title
            cell.textLabel.text = title;
    
            // Add switch
            UISwitch *switchView = [[UISwitch alloc] initWithFrame: CGRectZero];
            cell.accessoryView = switchView;
            switchView.tag = tag;
            [switchView setOn: [[[NSUserDefaults standardUserDefaults] objectForKey: key] boolValue] animated: NO];
    
            // Connect action to switch
            [switchView addTarget: self action: @selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
    
        }
        if([type isEqualToString: typeTextField]) {
    
            // Create cell
            cell = [tableView dequeueReusableCellWithIdentifier: @"Cell" forIndexPath:indexPath];
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
    
            int frameSize = self.view.frame.size.width;
    
            UITextField *textField = [[UITextField alloc] initWithFrame: CGRectMake(15, 10, frameSize,labelCGRectHeight)];
            textField.tag = tag;
            textField.text = [[NSUserDefaults standardUserDefaults] objectForKey: key];
    
            [textField addTarget: self
                          action: @selector(textFieldChanged:)
                forControlEvents: UIControlEventEditingChanged];
    
            [cell.contentView addSubview: textField];
    
            // Tract text field
            [textViews addObject: textField];
        }
        if([type isEqualToString: typeMultiValue]) {
    
            // Create cell
            cell = [tableView dequeueReusableCellWithIdentifier: @"MultiValueCell" forIndexPath:indexPath];
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
    
            // Get value
            int value = [[[NSUserDefaults standardUserDefaults] objectForKey: key] intValue];
            NSArray *values = [prefSpecification objectForKey: @"Values"];
            NSArray *titles = [prefSpecification objectForKey: @"Titles"];
            NSString *multiValue = @"Unknown";
            int index = [values indexOfObject: [NSString stringWithFormat: @"%d", value]];
    
            if(index >= 0 && index < [values count]) {
                multiValue = [titles objectAtIndex: index];
            }
    
            // Set title
            cell.textLabel.text = title;
    
            int frameSize = self.view.frame.size.width;
    
            // Add label
            UILabel *labelView = [[UILabel alloc] initWithFrame: CGRectMake((frameSize - labelCGRectWidth - 30), 12, labelCGRectWidth, labelCGRectHeight)];
            labelView.textAlignment = NSTextAlignmentRight;
            labelView.text = multiValue;
            labelView.textColor = [UIColor grayColor];
    
            [cell addSubview: labelView];
            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    
            // Track label
            [labelViews addObject: labelView];
        }
    
        return cell;
    }
    
    - (void) switchChanged: (id) sender {
        UISwitch* switchControl = sender;
    
        NSString *key = [settingsKeys objectAtIndex: switchControl.tag];
        NSNumber *numberValue = [NSNumber numberWithBool: switchControl.on];
    
        [[NSUserDefaults standardUserDefaults] setObject: numberValue forKey: key];
    }
    - (void) textFieldChanged: (id) sender {
        UITextField* textControl = sender;
    
        NSString *key = [settingsKeys objectAtIndex: textControl.tag];
        NSString *stringValue = textControl.text;
    
        [[NSUserDefaults standardUserDefaults] setObject: stringValue forKey: key];
    }
    
    - (void) selectedMultiValue {
        [self reloadTable];
    }
    
    - (void) deviceOrientationDidChange {
        [self reloadTable];
    }
    
    - (void)prepareForSegue: (UIStoryboardSegue *) segue sender: (id) sender
    {
        if ([[segue identifier] isEqualToString: @"changeMultiValue"])
        {
            MultiValueTableViewController *multiValueViewController =
            [segue destinationViewController];
    
            NSIndexPath *indexPath = [self.tableView
                                      indexPathForSelectedRow];
    
            // Get the dictionary item
            NSDictionary *prefSpecification = [[settingsTableData objectAtIndex: indexPath.section] objectAtIndex: indexPath.row];
    
            multiValueViewController.prefSpecification = prefSpecification;
            multiValueViewController.delegate = self;
        }
    }
    
    - (void) reloadTable {
        for (UILabel *labelView in labelViews) {
            [labelView removeFromSuperview];
        }
        for (UITextField *textView in textViews) {
            [textView removeFromSuperview];
        }
    
        // Remove references to objects for garbage collection
        labelViews = [NSMutableArray arrayWithObjects: nil];
        textViews = [NSMutableArray arrayWithObjects: nil];
    
        [self.tableView reloadData];
    }
    
    - (void) dealloc {
        // Remove observers
        [[NSNotificationCenter defaultCenter] removeObserver: self];
    }
    @end
    

    MultiValueTableViewController.h

    //
    //  MultiValueTableViewController.h
    //  Cochlear App
    //
    //  Created by Gilles Lesire on 16/07/14.
    //  Free to use
    //
    
    #import <UIKit/UIKit.h>
    #import "SettingsController.h"
    
    @protocol MultiValueDelegate
    
    - (void) selectedMultiValue;
    
    @end
    
    @interface MultiValueTableViewController : UITableViewController {
        NSDictionary *prefSpecification;
    }
    
    @property (nonatomic) id<MultiValueDelegate> delegate;
    @property (strong, nonatomic) NSDictionary *prefSpecification;
    
    @end
    

    MultiValueTableViewController.m

    //
    //  MultiValueTableViewController.m
    //  Cochlear App
    //
    //  Created by Gilles Lesire on 16/07/14.
    //  Free to use
    //
    
    #import "MultiValueTableViewController.h"
    
    @interface MultiValueTableViewController ()
    
    @end
    
    @implementation MultiValueTableViewController
    
    @synthesize prefSpecification;
    
    - (id)initWithStyle:(UITableViewStyle)style
    {
        self = [super initWithStyle:style];
        if (self) {
            // Custom initialization
        }
        return self;
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        NSString *title = [prefSpecification objectForKey: @"Title"];
        self.navigationItem.title = title;
    
    // Avoid tab bar to overlap tableview
    self.edgesForExtendedLayout = UIRectEdgeAll;
    self.tableView.contentInset = UIEdgeInsetsMake(0.0f, 0.0f, CGRectGetHeight(self.tabBarController.tabBar.frame), 0.0f);
    }
    
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    #pragma mark - Table view data source
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        // Return the number of sections.
        return 1;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        NSArray *values = [prefSpecification objectForKey: @"Values"];
    
        // Return the number of rows in the section.
        return [values count];
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: @"Cell" forIndexPath:indexPath];
    
        NSString *key = [prefSpecification objectForKey: @"Key"];
        NSArray *titles = [prefSpecification objectForKey: @"Titles"];
        NSArray *values = [prefSpecification objectForKey: @"Values"];
        NSString *title = [titles objectAtIndex: indexPath.row];
    
        // Create cell
        cell.selectionStyle = UITableViewCellSelectionStyleGray;
    
        // Set title
        cell.textLabel.text = title;
    
        // If this is the selected value
        if([[values objectAtIndex: indexPath.row] intValue] == [[[NSUserDefaults standardUserDefaults] objectForKey: key] intValue]) {
            cell.accessoryType = UITableViewCellAccessoryCheckmark;
        } else {
            cell.accessoryType = UITableViewCellAccessoryNone;
        }
    
        return cell;
    }
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        NSString *key = [prefSpecification objectForKey: @"Key"];
        NSArray *values = [prefSpecification objectForKey: @"Values"];
    
        NSNumber *value = [values objectAtIndex: indexPath.row];
    
        [[NSUserDefaults standardUserDefaults] setObject: value forKey: key];
    
        [self.delegate selectedMultiValue];
        [self.tableView reloadData];
    }
    
    @end
    

    故事板 现在进入故事板并创建一个 TableViewController。选择 TableViewController 并选择“编辑器”->“嵌入”->“导航控制器”。

    将 TableViewController 的类设置为 SettingsTableViewController。将单元格的标识符设置为“Cell”,将第二个 TableViewCell 添加到 TableView 并将其标识符设置为“MultiValueCell”。添加第二个 TableViewController,然后 CTRL+CLICK 并从 MultiValueCell 拖动到第二个 TableViewController。将第二个 TableViewController 的类设置为 MultiValueTableViewController。将第二个 TableViewController 中单元格的标识符也设置为“Cell”。就是这样!

    【讨论】:

    • 感谢您的快速回复。我已经知道如何在应用程序之外进行设置。但我问是否可以在您的 iOS App Settings Bundle 中有一个表格视图。如果可以,我该怎么做?
    • 为什么所有这些代码? OP 要求将选择表设置为外部设置包的一部分。无需代码。
    【解决方案3】:
    #import "SettingViewController.h"
    NSInteger selectedIndex;
    //Use this, it works for me 
    
    - (void)viewDidLoad
    {
    selectedIndex = 0;
        [super viewDidLoad];
    }
    -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        return 1;
    }
    
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        return 50.0f;
    }
    
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return [_arrayForSaveSetting count];
    }
    
    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *CellIdentifier = @"Cell";
    
        UITableViewCell *cell = nil;
    
        if (cell == nil)
        {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
        }
        if (indexPath.row==selectedIndex) {
            cell.accessoryType =UITableViewCellAccessoryCheckmark;
        }
    
        return cell;
    }
    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        [tableView deselectRowAtIndexPath:indexPath animated:YES];
        selectedIndex=indexPath.row;   
        [_tblSaveSetting reloadData];
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-19
      • 2017-08-16
      • 1970-01-01
      • 1970-01-01
      • 2014-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多