我一直在重写我的模型层,以便在多个现有应用程序中使用。现有的代码库已经过时了,我想概括一下我的方法,以便将来更容易扩展,并获得最新语言/技术添加的好处(ARC 为其中之一)。
我的目标是一个可移植的、由 SQL 支持的“框架”,由一个简单的数据库层(建立在 FMDatabase 之上)和健壮的模型对象类组成,它们共同封装了大部分复杂性。模型对象是主超类的子类,并遵守合同来实现(和覆盖)方法,这些方法提供必要的属性和模式细节以促进 SQL 操作。
我在 PHP 中使用这种方法取得了很大的成功,但在使用 Objective-C 时遇到了问题。
是的,CoreData 提供了这些东西,但由于多种原因不是一种选择。我还看到了在运行时解决问题的解决方案,但我不确定这是否适用于 ARC,并且更愿意在编译之前生成访问器。
我从为多线程访问维护基于锁的模式与基于 GCD 的方法(这里提出的问题)的辩论开始,并最终得到以下模式:
- (NSDate *)creationDate {
__block NSDate *aDate;
dispatch_sync(accessorQueue, ^{
aDate = creationDate;
});
return aDate;
}
- (void)setCreationDate:(NSDate *)aDate {
if (![aDate isKindOfClass: [NSDate class]]) {
NSLog(@"setCreationDate: called with non-date object);
return;
}
dispatch_barrier_async(accessorQueue, ^{
if ((!creationDate && aDate) || ![aDate isEqualToDate: creationDate]) {
[self willChangeValueForKey: @"creationDate"];
[changes setObject: aDate ? aDate : [NSNull null]
forKey: @"creationDate"];
creationDate = aDate;
[self didChangeValueForKey: @"creationDate"];
}
});
}
我喜欢它,但我希望能够生成属性列表以简化模型对象代码。我的第一步是创建宏扩展来构建访问器/修改器。不过,在这里我已经遇到了不太完美的选择。
1) 迭代宏中的列表是一个丑陋的过程。Boost.preprocessor 可能是一种选择,但考虑到 (2 & 3) 它有点吓到我。
2) 宏需要在所用令牌的所有可能版本中传递(即,我必须传递 creationDate 和 CreationDate 只是为了满足为上面的示例生成 getter 和 setter。)不是一个显示停止器,但不理想任何一个。
3) 对象和原始类型需要不同的宏扩展,这使得遍历属性列表 (1) 更加困难。我可以为列表中的每个属性传入扩展宏,但这个“节省时间”现在看起来完全相反——一长串元组并不比一个单独调用宏的列表更具可读性。
我希望我忽略了一些使这成为可能的东西,或者也许有人已经构建了一个我还没有找到的解决方案。也许是一个预处理脚本来生成包含访问器的类别......?我还没有研究过这个选项,但我可以接受,特别是如果它扩展到其他语言以实现跨平台定位。
建议表示赞赏。