所以我有2个不同的表视图使用相同的数组(该数组最初是在Role表视图中创建的,下面是一个)。我如何连接这两个? (通常我使用prepareForSegue来传递数据,但由于没有segue,我不知道我该怎么办呢)
编辑1:添加阵列的位置。
答案 0 :(得分:1)
在大多数情况下,如果您没有数据模型,传递数据是没用的。您可以使用名为Data Persistence的技术存储数据。
您可以使用的模式示例是MVC。 MVC或model-view controlelr是一种在制作iOS应用时广泛使用的软件模式。在这种架构模式中,您的控制器是View和模型之间的桥梁。
在此特定情况下,UITableViewController
两个{s}将使用相同的模型,但它们会以不同方式显示此数据。
有几种方法可以做到这一点,我最喜欢的方式是一个名为CoreData的小框架,您可以看到this问题以获得一些参考。
您还可以参考this问题查看单身人士的使用情况。但请记住,单身不坚持数据。如果您希望在应用会话之间保留数据,则必须添加某种机制。
存储小块数据的最简单方法是使用NSUserDefaults
(但仅用于存储默认值):
假设你有一个数组
NSArray* testArray = @[@"first", @"second", @"third"];
您可以使用
将其设置为键[[NSUserDefaults standardUserDefaults] setObject:testArray forKey:@“myArray”];
您可以使用
同步NSUserDefaults
[[NSUserDefaults standardUserDefaults] synchronize];
然后,您可以在应用中的任何位置阅读
[[NSUserDefaults standardUserDefaults] objectForKey:@"myArray"]
另一方面,你必须以某种方式传递你的数据。为此,您可以使用正式协议,特别是委托。 根据{{3}}:
在基于委托的模型中,视图控制器为其定义协议 其代表实施。该协议定义了方法 由视图控制器调用以响应特定操作,例如 点击完成按钮。然后代表负责 实施这些方法。例如,当呈现视图时 控制器完成其任务,它向呈现发送消息 视图控制器和控制器解除它。
使用委托来管理与其他应用程序对象的交互是关键 优于其他技术的优势:
委托对象有机会验证或合并 来自视图控制器的更改。
代表的使用促进 更好的封装,因为视图控制器不必知道 关于代表类的任何事情。这使您可以重用 在应用程序的其他部分查看控制器。
有关通过视图控制器传递数据的更多信息(这个问题的要点),请查看Apple documentation SO答案。
答案 1 :(得分:1)
您永远不应该仅使用数据持久性来通过应用程序传递数据。既不是用户默认也不是核心数据 使用单身人士也不是一个好选择。一切都会弄乱你的记忆。
而是使用回调 - 作为代理或阻止。
或使用展开segues。
我在这里解释代表并解开segues:Passing row selection between view controllers
此示例传递索引路径,因为在这种情况下它是合适的,但传递的对象可能是任何类型或大小,因为只有指针通过。
如果你在另一边使用NSUserDefaults,数据被复制并写入磁盘 - 数据被复制并缓慢处理 - 没有任何用处。
我创建了一个示例应用程序,如何将数据从一个视图控制器传递到另一个标签栏分支中的另一个视图控制器。
我们需要截取视图控制器的部分来设置一些回调机制。在这种情况下,我使用块,但委托也可以正常工作。
UITabController有一个纯粹的可选委托。我创建一个UITabBarController的子类来作为它自己的委托,但实际上一个单独的委托应该以相同的方式工作。
#import "GameTabBarController.h"
#import "RoleViewController.h"
@interface GameTabBarController () <UITabBarControllerDelegate>
@end
@implementation GameTabBarController
-(void)viewDidLoad
{
[super viewDidLoad];
self.delegate = self;
}
-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
if ([viewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *navController = (UINavigationController *)viewController;
if ([navController.topViewController isKindOfClass:[RoleViewController class]]) {
RoleViewController *rvc = (RoleViewController *)[navController topViewController];
[rvc setSelectedRole:^(Role *role) {
UIViewController *viewController = self.viewControllers[0];
[viewController setValue:role forKey:@"role"];
[self setSelectedIndex:0];
}];
}
}
return YES;
}
@end
我将初始标签栏控制器设置为此子类
RoleViewController显示一个Roles列表,但是它的表视图的数据源和委托是一个单独的类,我添加到故事板中的角色视图控制器场景,我也在其中。
角色@interface Role : NSObject
@property (nonatomic,copy, readonly) NSString *name;
-(instancetype)initWithName:(NSString *)name;
@end
#import "Role.h"
@interface Role ()
@property (nonatomic,copy) NSString *name;
@end
@implementation Role
- (instancetype)initWithName:(NSString *)name
{
self = [super init];
if (self) {
_name = name;
}
return self;
}
@end
RoleDatasource
#import <UIKit/UIKit.h>
@class Role;
@interface RoleDatasource : NSObject <UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, copy) void(^roleSelector)(Role *role);
@end
#import "RoleDatasource.h"
#import "Role.h"
@interface RoleDatasource ()
@property (nonatomic,strong) NSArray *roles;
@end
@implementation RoleDatasource
- (instancetype)init
{
self = [super init];
if (self) {
_roles = @[[[Role alloc] initWithName:@"Magician"], [[Role alloc] initWithName:@"Soldier"], [[Role alloc] initWithName:@"Maid"]];
}
return self;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.roles.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = @"RoleCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
cell.textLabel.text = [self.roles[indexPath.row] name];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.roleSelector(self.roles[indexPath.row]);
}
@end
RoleViewController
#import <UIKit/UIKit.h>
@class Role;
@interface RoleViewController : UIViewController
@property (nonatomic, copy) void(^selectedRole)(Role *role);
@end
#import "RoleViewController.h"
#import "RoleDatasource.h"
@interface RoleViewController ()
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@end
@implementation RoleViewController
- (void)viewDidLoad {
[super viewDidLoad];
RoleDatasource *roleDataSource = (RoleDatasource *)[self.tableView dataSource];
[roleDataSource setRoleSelector:^(Role *role) {
self.selectedRole(role);
}];
}
@end
一旦在角色视图控制器上选择了角色,我们就要告诉我们的标签栏控制器切换到游戏视图控制器并在那里显示所选角色,请参阅标签栏控制器的代码。
GameViewController只是一个简单的视图控制器子类,它具有保存角色的属性,如果设置了角色,它将显示它的名称。
#import <UIKit/UIKit.h>
@class Role;
@interface PlayViewController : UIViewController
@property (nonatomic, strong) Role *role;
@end
#import "PlayViewController.h"
#import "Role.h"
@interface PlayViewController ()
@property (weak, nonatomic) IBOutlet UILabel *roleNameLabel;
@end
@implementation PlayViewController
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.roleNameLabel.text = (self.role) ? self.role.name : self.roleNameLabel.text;
}
@end
你会在github上找到一个例子。
答案 2 :(得分:-1)
我认为我应该将数组放在Tab栏控制器中并将其连接到Role Table视图(为了保持之前的行为)并将其连接到我的新Table视图以执行我想要的操作做。
我能想到的唯一问题是,由于我的程序很小,添加它不会是一个大问题。但如果我有更多的vc,那将会非常痛苦。