您不应该仅仅为了通过应用传递数据而使用数据持久性。既不是用户默认值,也不是核心数据。
同样使用单例也不是好的选择。一切都会打乱你的记忆。
改为使用回调——作为委托或块。
或者使用 unwind segues。
我在这里解释代表和解开问题:Passing row selection between view controllers
这个例子传递了索引路径,因为它在那种情况下是合适的,但是传递的对象可能是任何类型或大小的,因为只有指针是传递的。
如果你在另一边使用 NSUserDefaults,数据被复制并写入磁盘——在那里数据被复制并缓慢处理——没有任何用处。
我创建了一个示例应用程序,如何将数据从一个视图控制器传递到另一个标签栏分支中的另一个视图控制器。
点击放大
TabBarController
我们需要拦截视图控制器的部分来设置一些回调机制。在这种情况下,我使用的是块,但委托也可以工作。
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
我将初始标签栏控制器设置为这个子类
Role、RoleDatasource 和 RoleViewController
RoleViewController 显示一个角色列表,但它的表视图的数据源和委托是一个单独的类,我添加到情节提要中的角色视图控制器场景中,我也在其中。
角色
@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
角色数据源
#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
角色视图控制器
#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
PlayViewController
一旦在角色视图控制器上选择了一个角色,我们想要告诉我们的标签栏控制器切换到游戏视图控制器并在那里显示所选角色,请参阅标签栏控制器的代码。
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 上找到一个示例。