如何实现两个Table View间的数据共享与实时同步?
嘿,这个场景我太熟了!要让两个TableView实时同步数据,核心就是让它们共享同一个数据源,同时在数据变化时能及时通知到两个视图。我给你几个实用的方案,按推荐程度排序👇
把共享的可变数组放到一个全局唯一的单例类里,这个类专门负责数据的增删改查,两个TableViewController都从这里获取数据源。这样做的好处是数据逻辑和视图完全分离,所有数据操作都集中管理,不会出现多个地方改数组导致的不一致问题。
步骤1:创建数据管理器类
先建一个DataManager类(.h和.m文件),封装数组和操作方法:
// DataManager.h #import <Foundation/Foundation.h> @class YourCustomObject; // 替换成你的自定义对象类名 @interface DataManager : NSObject // 只读属性,外部只能通过封装的方法修改数组 @property (nonatomic, strong, readonly) NSMutableArray<YourCustomObject *> *objects; // 获取单例实例 + (instancetype)sharedManager; // 封装数据操作方法 - (void)addCustomObject:(YourCustomObject *)object; - (void)removeCustomObject:(YourCustomObject *)object; - (void)moveObjectFromIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex; @end
// DataManager.m #import "DataManager.h" #import "YourCustomObject.h" static DataManager *_sharedInstance = nil; @implementation DataManager + (instancetype)sharedManager { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _sharedInstance = [[self alloc] init]; _sharedInstance.objects = [NSMutableArray array]; }); return _sharedInstance; } - (void)addCustomObject:(YourCustomObject *)object { // 加个同步锁,避免多线程操作数组出问题 @synchronized(self) { [self.objects addObject:object]; } // 发送通知,告诉所有监听的视图数据更新了 [[NSNotificationCenter defaultCenter] postNotificationName:@"CustomObjectsUpdated" object:nil]; } - (void)removeCustomObject:(YourCustomObject *)object { @synchronized(self) { [self.objects removeObject:object]; } [[NSNotificationCenter defaultCenter] postNotificationName:@"CustomObjectsUpdated" object:nil]; } - (void)moveObjectFromIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex { @synchronized(self) { if (fromIndex != toIndex && fromIndex < self.objects.count && toIndex < self.objects.count) { YourCustomObject *targetObj = self.objects[fromIndex]; [self.objects removeObjectAtIndex:fromIndex]; [self.objects insertObject:targetObj atIndex:toIndex]; } } [[NSNotificationCenter defaultCenter] postNotificationName:@"CustomObjectsUpdated" object:nil]; } @end
步骤2:在TableViewController里使用
每个TableViewController都注册通知、获取共享数据源,数据变化时自动刷新:
#import "DataManager.h" @implementation YourTableViewController - (void)viewDidLoad { [super viewDidLoad]; // 注册通知,监听数据更新 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshTableView) name:@"CustomObjectsUpdated" object:nil]; // 绑定共享数据源 self.dataSourceArray = [DataManager sharedManager].objects; } - (void)refreshTableView { // 一定要在主线程刷新UI dispatch_async(dispatch_get_main_queue(), ^{ [self.tableView reloadData]; }); } // 记得在销毁时移除观察者,避免野指针 - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } // 剩下的TableView代理方法就用self.dataSourceArray作为数据源即可 @end
你也可以把可变数组放到AppDelegate的属性里,两个TableViewController通过[[UIApplication sharedApplication] delegate]获取这个数组。但这种方法会让AppDelegate变得臃肿,视图和AppDelegate耦合度太高,后期维护起来很麻烦,只适合极小的Demo项目,不推荐在正式项目里用。
如果不想用通知,可以让TableViewController监听单例里数组的变化。不过要注意:普通的NSMutableArray增删改不会触发KVO,因为KVO监听的是属性的setter方法。所以你需要在DataManager的操作方法里手动触发KVO通知:
// 在DataManager的add方法里修改 - (void)addCustomObject:(YourCustomObject *)object { @synchronized(self) { [self willChangeValueForKey:@"objects"]; [self.objects addObject:object]; [self didChangeValueForKey:@"objects"]; } }
然后在TableViewController里监听:
- (void)viewDidLoad { [super viewDidLoad]; self.dataManager = [DataManager sharedManager]; [self.dataManager addObserver:self forKeyPath:@"objects" options:NSKeyValueObservingOptionNew context:nil]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context { if ([keyPath isEqualToString:@"objects"]) { dispatch_async(dispatch_get_main_queue(), ^{ [self.tableView reloadData]; }); } } - (void)dealloc { [self.dataManager removeObserver:self forKeyPath:@"objects"]; }
这种方法也能实现同步,但通知的写法更直观,KVO需要注意处理上下文和避免内存泄漏,看你个人习惯选择。
内容的提问来源于stack exchange,提问作者John L

