5 Matching Annotations
  1. Mar 2019
    1. If one or more modules/extensions of your app fail to satify these conditions, you can avoid obfuscating them with the -ignore-modules argument.

      如果又[一个/多个] [模块/扩展] 不满足下面这些条件, 可以使用这个参数来忽略混淆

    1. Although Swift doesn’t use the Objective-C runtime by default and the compiler strips the symbols and applies the optimizations that are making it harder for the attacker to read decompiled app, the obfuscation might come in handy. Every time we derive from the NSObject or use the @objc attribute, we voluntarily participate in the Objective-C runtime and we must obey its rules. Therefore, the symbols are not striped.

      虽然 Swift 在做编译的时候会将代码 strip 并利用优化来使得反编译 app 得出来的代码没那么易于理解了, 但是当我们的类是继承自 NSObject, 或者使用@objec 的时候, 我们就会自动去遵守 runtime 的规则. 这些关键字就不会去应用到优化混淆部分

    2. The reason is that all the symbols must be stored in the binary and visible to the runtime so that they can be referenced by strings.

      that's also a important function for runtime for more about tools

    1. 交付什么样的数据给业务层? 我见过非常多的App的网络层在拿到JSON数据之后,会将数据转变成对应的对象原型。注意,我这里指的不是NSDictionary,而是类似Item这样的对象。这种做法是能够提高后续操作代码的可读性的。在比较直觉的思路里面,是需要这部分转化过程的,但这部分转化过程的成本是很大的,主要成本在于: 数组内容的转化成本较高:数组里面每项都要转化成Item对象,如果Item对象中还有类似数组,就很头疼。 转化之后的数据在大部分情况是不能直接被展示的,为了能够被展示,还需要第二次转化。 只有在API返回的数据高度标准化时,这些对象原型(Item)的可复用程度才高,否则容易出现类型爆炸,提高维护成本。 调试时通过对象原型查看数据内容不如直接通过NSDictionary/NSArray直观。 同一API的数据被不同View展示时,难以控制数据转化的代码,它们有可能会散落在任何需要的地方。 其实我们的理想情况是希望API的数据下发之后就能够直接被View所展示。首先要说的是,这种情况非常少。另外,这种做法使得View和API联系紧密,也是我们不希望发生的。 在设计安居客的网络层数据交付这部分时,我添加了reformer(名字而已,叫什么都好)这个对象用于封装数据转化的逻辑,这个对象是一个独立对象,事实上,它是作为Adaptor模式存在的。我们可以这么理解:想象一下我们洗澡时候使用的莲蓬头,水管里出来的水是API下发的原始数据。reformer就是莲蓬头上的不同水流挡板,需要什么模式,就拨到什么模式。 在实际使用时,代码观感是这样的: 先定义一个protocol: @protocol ReformerProtocol <NSObject> - (NSDictionary)reformDataWithManager:(APIManager *)manager; @end 在Controller里是这样: @property (nonatomic, strong) id<ReformerProtocol> XXXReformer; @property (nonatomic, strong) id<ReformerProtocol> YYYReformer; #pragma mark - APIManagerDelegate - (void)apiManagerDidSuccess:(APIManager *)manager { NSDictionary *reformedXXXData = [manager fetchDataWithReformer:self.XXXReformer]; [self.XXXView configWithData:reformedXXXData]; NSDictionary *reformedYYYData = [manager fetchDataWithReformer:self.YYYReformer]; [self.YYYView configWithData:reformedYYYData]; } 在APIManager里面,fetchDataWithReformer是这样: - (NSDictionary)fetchDataWithReformer:(id<ReformerProtocol>)reformer { if (reformer == nil) { return self.rawData; } else { return [reformer reformDataWithManager:self]; } } 要点1:reformer是一个符合ReformerProtocol的对象,它提供了通用的方法供Manager使用。 要点2:API的原始数据(JSON对象)由Manager实例保管,reformer方法里面取Manager的原始数据(manager.rawData)做转换,然后交付出去。莲蓬头的水管部分是Manager,负责提供原始水流(数据流),reformer就是不同的模式,换什么reformer就能出来什么水流。 要点3:例子中举的场景是一个API数据被多个View使用的情况,体现了reformer的一个特点:可以根据需要改变同一数据来源的展示方式。比如API数据展示的是“附近的小区”,那么这个数据可以被列表(XXXView)和地图(YYYView)共用,不同的view使用的数据的转化方式不一样,这就通过不同的reformer解决了。 要点4:在一个view用来同一展示不同API数据的情况,reformer是绝佳利器。比如安居客的列表view的数据来源可能有三个:二手房列表API,租房列表API,新房列表API。这些API返回来的数据的value可能一致,但是key都是不一致的。这时候就可以通过同一个reformer来做数据的标准化输出,这样就使得view代码复用成为可能。这体现了reformer另外一个特点:同一个reformer出来的数据是高度标准化的。形象点说就是:只要莲蓬头不换,哪怕水管的水变成海水或者污水了,也依旧能够输出符合洗澡要求的淡水水流。举个例子: - (void)apiManagerDidSuccess:(APIManager *)manager { // 这个回调方法有可能是来自二手房列表APIManager的回调,也有可能是租房,也有可能是新房。但是在Controller层面我们不需要对它做额外区分,只要是同一个reformer出来的数据,我们就能保证是一定能被self.XXXView使用的。这样的保证由reformer的实现者来提供。 NSDictionary *reformedXXXData = [manager fetchDataWithReformer:self.XXXReformer]; [self.XXXView configWithData:reformedXXXData]; } 要点5:有没有发现,使用reformer之后,Controller的代码简洁了很多?而且,数据原型在这种情况下就没有必要存在了,随之而来的成本也就被我们绕过了。

      感觉么...其实就把model操作放在显示之前, 确实是不错的, 但是也不需要reformer, 感觉就是一个model, 直接使用还是model比较方便啊