引言

  1. get 和post 布尔值参数处理( 使用NSNumber 传BOOL值)
  2. 全局的const常量代替宏常量,节省内存空间。
  3. 敏感逻辑的保护: 把函数名隐藏在结构体里,以函数指针成员的形式存储。


编译后,只留了下地址,去掉了名字和参数表,提高了逆向成本和攻击门槛


I 装箱和拆箱

1.1 Java包装类

  • Java包装类(装箱和拆箱)


全部被final修饰,顺便提一下,java.lang.Math,System,String也被final修饰


包装类是使用面向对象的思想把简单的数据类型封装成类

  1. 特点

包装类把简单的数据类型包装成类。 注:简单数据类型不是类,使用简单数据类型主要为了提高代码的运行效率 2. ​​装箱和拆箱​​​ ​​​把简单数据类型包装成对应的包装类称为boxing​​(示例:Integer i=1;将1包装成Integer再使用Object引用Integer对象)

​把包装类型转换成简单数据类型称为unboxing​​(示例:Integer i=1,int p=i;//将包装类Integer转化成简单数据类型int)

注:Integer的拆箱方法为 int intValue(),其他的包装类以此类推。

1)包装类都重写了toString方法,equals方法,hashCode方法 2)Integer的API: ​​String toBinaryString(int i); ​​​将int类型的数据以二进制字符串形式返回 ​​​int parseInt(String)​​​ 将字符串转化成int类型 ​​​int parseInt(Stringstr,int i ) ​​​将字符串转化成对应的进制 类型,str为被转换的字符串,i为进制类型(10,8,16) ​​​Integer valueof(String str)​​ 将字符串转换成Integer类型。

1.2 iOS ​​装箱​​:快速构造数字对象

Objective-C's boxing capability: The printf function ​​NSLog​​ offers a number of substitution tokens for printing numbers (%d, %ld, %f, %d, for example). As a convenience, you can use Objective-C's boxing capability to save time and avoid compiler warnings.

  • For example

iOS小技能:装箱和拆箱(boxing、unboxing)_ios

平常也可以使用​​@​​ 来快速包装数字类型以对象的形式进行存储和传参

iOS小技能:装箱和拆箱(boxing、unboxing)_iOS_02

[discountArray addObject:[[ self class] mj_objectWithKeyValues:@{@"placeholder":QCTLocal(@"please_input_card_num"),@"btnContent":QCTLocal(@"member_see"),@"EnterModelType":@2,@"isEnabled":@1,@"isLast":@1,@"block":block}]];

II The Truth About NSNumber and BOOL

Name

Typedef

Header

True Value

False Value

BOOL

signed char

objc.h

YES

NO

bool

_Bool (int)

stdbool.h

true

false

Boolean

unsigned char

MacTypes.h

TRUE

FALSE

NSNumber

__NSCFBoolean

Foundation.h

@(YES)

@(NO)

CFBooleanRef

struct

CoreFoundation.h

kCFBooleanTrue

kCFBooleanFalse

BOOL不如bool好用


BOOL表示 1是YES , 所以非1是NO. 而bool表示0是false,所以非0是true;


2.1 NSCFBoolean

NSCFBoolean是NSNumber类簇中的一个私有的类,它是通往CFBooleanRef类型的桥梁。NSCFBoolean被用来给Core Foundation的属性列表和集合封装布尔数值。


CFBoolean定义了常量kCFBooleanTrue和kCFBooleanFalse。


​NSLog(@"%@", [@(YES) class]);​

__NSCFBoolean

2.1 get 和post 布尔值参数处理( 使用NSNumber 传BOOL值)

使用NSNumber 传BOOL值的时候,get 和post对应的参数不一致。get请求对应的0和1,post对应true/false。

​ [params setValue:[NSNumber numberWithBool:self.viewModel.multipleSwitchCellTableViewCellModel.IsSon] forKey:@"IsSon"];​


这个代码使用Post 会将请求参数IsSon 自动转为true/false


若服务端Bool 参数没有支持0和1格式,只支持true false的时候,就需要特殊处理。

//get  需要自己处理
if(self.viewModel.multipleSwitchCellTableViewCellModel.IsSon){
[params setValue:@"true" forKey:@"IsSon"];//


}else{

[params setValue:@"false" forKey:@"IsSon"];//

}


iOS小技能:装箱和拆箱(boxing、unboxing)_包装类_03

————————————————




II 常量

2.1 对象常量

随着Apple 的 LLVM 4.0 编译器的发布,让我们欣喜的是NSNumber,NSArray和NSDictionary常量被添加了。

  • ​@""​​:返回一个由引号内 Unicode 内容初始化的 NSString 对象。
  • ​@42,@3.14,@YES,@'Z'​​:返回一个由相关类构造初始化的 NSNumber 对象


比如 @42 → [NSNumber numberWithInteger:42],或者 @YES → [NSNumber numberWithBool:YES]。支持使用后缀进一步指定类型,如 @42U → [NSNumber numberWithUnsignedInt:42U]。


  • ​@[]​​:返回一个由冒号分隔的对象列表作为内容的 NSArray 对象。


比如,@[@"A", @NO, @2.718] → [NSArray arrayWithObjects:@"A", @NO, @2.718, nil] (注意在数组常量中结束标记nil是不需要的)。


  • ​@{}​​​:返回一个由特定键-值对初始化作为内容的NSDictionary对象,格式:​​ @{@"someKey" : @"theValue"}​​。
  • @():动态评估封装的表达,并返回基于其值的合适的对象常量,这也是使用数字常量和枚举值的指定方式。


(比如,const char*返回NSString,int返回NSNumber。)


2.2 Objective-C 常量

选择器和协议可以作为方法参数。​​@selector()​​​和​​@protocol()​​作为伪常量指令返回一个指向特定选择器(SEL)或协议(Protocol *)的指针。

  • ​@selector()​​:返回一个指向有特定名称的选择器的 SEL 指针。


​-performSelector:withObject:​


  • ​@protocol()​​:返回一个指向有特定名称的协议的 Protocol * 指针。


​-conformsToProtocol:​


2.3 全局的const常量代替宏常量,节省内存空间。

使用字符串常量来代替宏的使用

  1. 定义const 全局常量 ,保证只在一处定义,多处进行引用。
  2. 全局的const常量代替宏常量,节省内存空间(内存只有一份)。

#define KNClientId @""//宏会在编译时,将所有引用宏变量的地方,进行值的替换,造成很多相同的临时字面量,浪费内存
NSString * const KNClientId = @"";// 全局的const常量代替宏常量,节省内存空间。内存只有一份

III 扩展:敏感逻辑的保护

3.1 把函数名隐藏在结构体里,以函数指针成员的形式存储

把函数名隐藏在结构体里,以函数指针成员的形式存储。


编译后,只留了下地址,去掉了名字和参数表,提高了逆向成本和攻击门槛


#import <Foundation/Foundation.h>

@interface KNUtil : NSObject



/**
把函数名隐藏在结构体里,以函数指针成员的形式存储。

编译后,只留了下地址,去掉了名字和参数表,提高了逆向成本和攻击门槛
*/
typedef struct _util {
void (*checkKNSign)(char *keys[], unsigned char *output);
}CheckKNSignUtil_t ;


#define ShareKNUtil ([KNUtil sharedUtil])

+ (CheckKNSignUtil_t *)sharedUtil;

  • 调用方法

ShareKNUtil->checkKNSign(key, output);

3.2 使用宏进行替换字符串

  • 根据前缀搜索出需要混淆的类名、方法名, 生成对应的宏文件

#define run OmWJoTZfCqoPshvr
#define iosre egnjoOFDrFiQVRgr


静态分析时hopper等反汇编工具无法根据string搜索到关键字符