0. 我前面所说的意思并不是DataCenter交由APIManager管辖。而是有一个业务Manager,这个业务Manager管辖APIManager和DataCenter。
1. 这里应该没Table什么事儿。
你通过reformer取出来的recordArray里面的所有record,都必须要符合CTPersistanceRecordProtocol。然后你会有一个DataCenter提供一个例如saveWithRecordList的方法,在这个方法里面,DataCenter操作CTPersistanceTable去存数据。由于recordArray中的每一个record都符合CTPersistanceRecordProtocol,因此每个record都可以直接参与Table的操作。
2. 整个需求中你有三个角色:BusinessManager,APIManager,DataCenter。
BusinessManager下辖APIManager,DataCenterManager。
BusinessManager响应Controller的需求去调用APIManager,然后reformer是在BusinessManager里的。在API回调方法中拿着reformer去获得record,在获得record之后,一方面把recordArray交给DataCenter去存储,另一方面将这个recordArray交给Controlle去展示。
你的WorkCirclePublicRecord没必要去继承CTPersistanceRecord,你的WorkCirclePublicRecord可以就是一个View,然后实现CTPersistanceRecordProtocol中的方法,就可以了。
dictionaryRepresentationWithTable:方法是让你返回这个数据在数据库中的记录的dictionary的表达。传进来的table就是告诉你CTPersistance希望你返回的是这个表相关的dictionary记录,因为record有可能merge了多个表。你挑出你这个对象中跟数据库有关的几个property,然后把它组成字典return出来就好了。
objectRepresentationWithDictionary:方法就是在CTPersistance拿到了dictionary表达的数据后,交给record让record去根据这个数据组装自己的方法。你也可以从中挑出你要的数据,赋值给自己的对象。比如挑出textContent赋值给自己的某个label。
setPersistanceValue:forKey:就是CTPersistance有时候会单独取出记录中的某一个Key来赋值,你在这个方法中拿到key之后判断一下,然后给相应的对象赋值即可。如果key是title,那么你就找到你的titleLable,把titleLabel.text赋值为提供给你的value。
mergeRecord:shouldOverride:的意思就是会给你一个record,然后希望你把这个record的值对应赋值给自己,你根据shouldOverride来决定当自己和record的同一个property都不为nil的时候,采用哪一个。
optional中的availableKeyList:方法是当merge两个record的时候,你有可能不希望所有的key都参与merge,那么这个方法就提供你需要参与merge的key的列表。
3. 其实你样例中的这部分代码是多余的。
当APIManager拿到了dictionary的数据之后,直接丢给record的objectRepresentationWithDictionary:方法就可以了,这样record就会根据dictionary的内容组装好自己了。
4. 同上
5. 在2的回答中我已经告诉你协议里的方法都应该如何实现了。
看完文章觉得懂了,其实只是你看懂我写的字了,看懂我说的逻辑了。但没有想明白背后的思想来源,没有想明白为什么是这个逻辑,所以不知道如何下手。要理解背后的思想,只有有足够的经验才能明白,这个没有捷径的。
一个完整的API对应一个Manager,一组API对应一个Service。http://google/login和http://google/logout分别对应两个APIMananger,但是只有一个Service。
1. APIManager只做网络相关的操作,不负责处理业务。reformer只负责做数据转化,也不算很涉及业务,主要是要跟view的需求做匹配。
如果涉及storage,那这些是交给Controller去调度的。举个例子,API回来的数据要存本地。那么这个场景在我的设计下应该是这样一个过程:
a. controller命令APIManager获取API数据,回调方法在controller内
b. API调用成功,此时走到Controller内部的回调方法,这时候Controller拿着reformer去问APIManager要数据。
c. 数据经过reformer的清洗:格式修改、空数据筛除、脏数据筛除等,得到一个可以直接用于本地化存储的对象。
d. controller拿着APIManager使用reformer吐出之后的对象,交给StorageMananger,完成本地持久化。
2. reformer其实是跟具体哪个view是不相关的。经过reformer得到的数据不光可以被一种View渲染,也可以被其他View渲染。Controller在其中的角色就是,controller知道自己管辖的那个View能够使用哪种类型的数据,然后controller再根据这个去选择合适的reformer(如果没有找到合适的reformer,那就自己写一个咯),把可以直接被那个view使用的数据交给view。
所以,reformer吐出来的数据的key,是要跟着reformer走的,不适合放到ViewController里面去,因为reformer决定了数据输出是什么样的,controller根据数据输出的样子去选择reformer。
3. 转变成model之后的数据,有的时候能保证直接被view使用,有的时候不能保证直接被view使用,比如附近房源列表API返回来的数据如果要在MKMapView上展示,就只能使用MKAnnotation,model是不能直接使用的。这是其一。
API返回的数据不一定都是标准的,但会有不同来源的数据需要同一个view来渲染的情况,如果采用model,就会导致代码混乱。举个例子:租房列表API、新房列表API、二手房列表API,他们返回的数据格式是很有可能不一样的,因为在服务端他们就不处在同一个表,比如房子的名字一个叫name,一个叫houseName,一个叫propertyName。然而在iOS客户端,展现他们的UI却是相同的,只需要一个UITableView。如果用这些库转变成model,做这样的需求就很蛋疼。这是其二
当你做迁移的时候,如果是model代码实体,你不能保证其他人在创建这个model的时候,以及后面维护这个model的时候不去包含其他的代码。一旦有这种情况,迁移起来就很蛋疼。用reformer就消除了model这一层,而reformer是属于非常独立的对象,迁移的时候非常方便。这是其三。
4. 其实还是集约型还是离散型的问题。
我这边是希望一个APIMananger对应单独的一个API。如果App需要的API数量非常多,APIMananger的数量也会多,这是合理的。比如你接下来要开发pad版app,pad版不需要phone那么多API,你只要挑几个APIMananger扔过去就可以了,维护起来还是很方便的。
另外,如果你要针对单独的某个API做拦截器的操作,集约型的就很难做了。数量不怕多,整齐就可以了。离散型API的调用方式虽然也有缺点,但是相对而言,还是较集约型API调用方式为优。
5. 哈哈,我要睡午觉了,回头晚点我再帮你看看~