开发中记录的点点滴滴
1. iOS 逆向篇
常用命令:
0.ps -e | grep WeChat
1.看是否被砸壳:otool -l Mach-o路径 | grep crypt cryptid 1,这表明这个项目文件还未没砸壳,0则表示已经完成砸壳
2.远程拷贝命令:scp /Applications/Reveal.app/Contents/SharedSupport/iOS-Libraries/RevealServer.framework/libReveal.dylib root@192.168.197.146:/Library/RHRevealLoader/libReveal.dylib
3.导出头文件:class-dump -H Mach-o路径 -o 头文件路径 Example:class-dump -H Tweak -o APPHeaders
4.砸壳:DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/mobile/Containers/Bundle/Application/B00865DD-E8AD-49C1-B92C-C3BA22A17CBA/YouShiXiu.app/YouShiXiu
5.砸壳:Clutch -i 查看是否加壳 com.diary.mood Clutch -d 1 砸壳后文件的路径 /private/var/mobile/Documents/Dumped/com.diary.mood-iOS6.0-(Clutch-2.0.4).ipa
6.deb包的路径:
/Library/MobileSubstrate/DynamicLibraries/ABC.dylib
/Library/MobileSubstrate/DynamicLibraries/ABC.plist
7.查看ASLR地址: image list -o -f | grep WeChat
8.查看Mach-o 中含有的动态库:otool -L aisiweb | grep ".dylib"
9.架构拆分与合并:
lipo wework -thin arm64 -output macho_arm64
lipo wework -thin armv7 -output macho_armv7
lipo -create macho_arm64 macho_armv7 -output wework
10. Attach to Process with Xcode
1.ldid -e ./wework > ./wework.plist get-task-allow:YES
2.ldid -Swework.plist ./wework
3.chmod 755 ./WeChat
4.需要dev证书打包
11.恢复符号表:./restore-symbol ./wework -o ./wework_with_symbol
签名腾讯视频:
oTool -L live4iphone
insert_dylib @executable_path/livetweak.dylib live4iphone --all-yes --weak live4iphone
oTool -L livetweak.dylib
install_name_tool -change /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate @loader_path/CydiaSubstrate livetweak.dylib
codesign -fs 6D1DCFE0B265D7324DBC0824AC337D36103169CB livetweak.dylib
codesign -fs 6D1DCFE0B265D7324DBC0824AC337D36103169CB CydiaSubstrate
签名企业微信:
oTool -L wework
insert_dylib @executable_path/wwtweak.dylib wework --all-yes --weak wework
oTool -L wwtweak.dylib
install_name_tool -change /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate @loader_path/CydiaSubstrate wwtweak.dylib
codesign -fs 6D1DCFE0B265D7324DBC0824AC337D36103169CB wwtweak.dylib
codesign -fs 6D1DCFE0B265D7324DBC0824AC337D36103169CB CydiaSubstrate
签名微信:
oTool -L WeChat
insert_dylib @executable_path/fkwechatzan.dylib WeChat --all-yes --weak WeChat
oTool -L fkwechatzan.dylib
install_name_tool -change /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate @loader_path/CydiaSubstrate fkwechatzan.dylib
codesign -fs 6D1DCFE0B265D7324DBC0824AC337D36103169CB fkwechatzan.dylib
codesign -fs 6D1DCFE0B265D7324DBC0824AC337D36103169CB CydiaSubstrate
oTool -L WeChat
insert_dylib @executable_path/tweak_wechat.dylib WeChat --all-yes --weak WeChat
oTool -L tweak_wechat.dylib
install_name_tool -change /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate @loader_path/CydiaSubstrate tweak_wechat.dylib
codesign -fs 6D1DCFE0B265D7324DBC0824AC337D36103169CB tweak_wechat.dylib
codesign -fs 6D1DCFE0B265D7324DBC0824AC337D36103169CB CydiaSubstrate
oTool -L WeChat
insert_dylib @executable_path/WeChatRedEnvelop.dylib WeChat --all-yes --weak WeChat
oTool -L WeChatRedEnvelop.dylib
install_name_tool -change /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate @loader_path/CydiaSubstrate WeChatRedEnvelop.dylib
codesign -fs 6D1DCFE0B265D7324DBC0824AC337D36103169CB WeChatRedEnvelop.dylib
codesign -fs 6D1DCFE0B265D7324DBC0824AC337D36103169CB CydiaSubstrate
签名钉钉:
oTool -L DingTalk
insert_dylib @executable_path/dingdingtweak.dylib DingTalk --all-yes --weak DingTalk
oTool -L dingdingtweak.dylib
install_name_tool -change /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate @loader_path/CydiaSubstrate dingdingtweak.dylib
codesign -fs 6D1DCFE0B265D7324DBC0824AC337D36103169CB dingdingtweak.dylib
codesign -fs 6D1DCFE0B265D7324DBC0824AC337D36103169CB CydiaSubstrate
删除动态库:
optool uninstall -p "@executable_path/Frameworks/sutuplus.dylib" -t WeChat
查找依赖的动态库:
find /iOS-Router/Payload/WeChat.app/ -iname "*.dylib"
重签名APP:
codesign -fs 6D1DCFE0B265D7324DBC0824AC337D36103169CB --no-strict --entitlements=entitlements.plist WeChat.app
查看APP签名是否被替换:
codesign -d -vv WeChat.app
向可执行文件中注入framework:
insert_dylib @rpath/TLocationPlugin.framework/TLocationPlugin WeChat --all-yes --weak WeChat
重签名framework:
codesign -fs 6D1DCFE0B265D7324DBC0824AC337D36103169CB TLocationPlugin.framework
Mac上看可执行问价是否被加壳:
otool -l WeChat | grep crypt
2.iOS arm64汇编相关知识整理:
1.寄存器: ARM64 有34个寄存器,包括31个通用寄存器、SP、PC、CPSR
2.通用寄存器:x0~x28(64位的) (w0~w28(32位)对应的的x0~x28的低32位) ,x0~x7一般是用来存储函数的参数,更多参数,则用堆栈来传递,x0一般用作函数的返回值
3.PC: 程序计数器,存储着当前执行的指令
4.FP:栈顶指针,指向一个栈帧的顶部,当函数发生跳转时,会记录当时的栈的起始位置。
5.SP:栈指针(也称为栈底指针),指向栈当前的位置
6.CPSR:状态寄存器
NZCV是状态寄存器的条件标志位,分别代表运算过程中产生的状态,其中:
N, negative condition flag,一般代表运算结果是负数
Z, zero condition flag, 指令结果为0时Z=1,否则Z=0;
C, carry condition flag, 无符号运算有溢出时,C=1。
V, oVerflow condition flag 有符号运算有溢出时,V=1。
7.LR:通常称X30为程序链接寄存器,保存子程序结束后需要执行的下一条指令
8.wzr:32位零寄存器
9.xzr:64位零寄存器
mov X1,X0 将寄存器X0的值传送到寄存器X1
add X0,X1,X2 寄存器X1和X2的值相加后传送到X0
sub X0,X1,X2 寄存器X1和X2的值相减后传送到X0
and X0,X0,#0xF X0的值与0xF相位与后的值传送到X0
orr X0,X0,#9 X0的值与9相位或后的值传送到X0
eor X0,X0,#0xF X0的值与0xF相异或后的值传送到X0
ldr X5,[X6,#0x08] ld:load X6寄存器加0x08的和的地址值内的数据传送到X5
ldp x29, x30, [sp, #0x10] ldp :load pair 一对寄存器, 从内存读取数据到寄存器
str X0, [sp, #0x8] st:store, str:往内存中写数据(偏移值为正); X0寄存器的数据传送到SP+0x8地址值指向的存储空间
stur w0, [x29, #-0x8] 往内存中写数据(偏移值为负)
stp x29, x30, [sp, #0x10] store pair,存放一对数据, 入栈指令
cmp 比较指令,影响程序状态寄存器CPSR
b 跳转指令,可带条件跳转与cmp配合使用
bl 带返回的跳转指令, 返回地址保存到LR(X30)
ret:函数返回,相当于return
叶子函数:
void test(){
int a = 2;
int b = 3;
}
sub sp, sp, #16 ; =16,sp栈顶指针上移16个字节
.cfi_def_cfa_offset 16
mov w8, #2 ;将2存入w8寄存器
str w8, [sp, #12] ;将w8寄存器的数据存入到sp下移12个字节的所在位置下面的4字节
mov w8, #3 ;将3存入w8寄存器
str w8, [sp, #8] ;将w8寄存器的数据存入到sp下移8个字节的所在位置下面的4字节
add sp, sp, #16 ; =16,sp栈顶指针下移16个字节,恢复到初始位置
ret
非叶子函数,除了叶子函数,其他函数叫非叶子函数:
void excute(){
int a = 4;
int b = 5;
test();
}
void test(){
int a = 2;
int b = 3;
}
3. iOS 组件化
//安装知指定版本的cocoapods:
sudo gem install -n /usr/local/bin cocoapods --version 1.7.4
1.创建远程索引库:
CHSSpec 专门用来存放索引文件 Public Initialize this repository with a README objc
2.创建本地索引库:
1.查看一下当前有哪些本地索引库: pod repo
2.pod repo add <本地索引库的名字> <远程索引库的地址> (pod repo add CHSSpec https://iOS-Git-Path/CHSSpec)
3.通过下面的方式可以查看本地索引库的物理地址: /Users/test/.cocoapods/repos/CHSSpec
3.创建远程代码库(代码实际存放的远程仓库):
CHS-HealthModule-iOS 代码文件 Public
4.创建本地代码库(注意代码与主工程是平级关系)
1.pod lib create <组件名> pod lib create CHS-HealthModule-iOS
2.stoneUoU@163.com iOS Objc Yes None No CHS
3.将要组件化的文件夹拖入到组件CHS-HealthModule-iOS的classes路径下
4.cd到Example下进行pod install(把刚才拖入到classes里的文件夹pod进来)
5.编译并运行,根据需要修改podspecs索引文件
6.编译运行通过后,提交组件到远程代码库并打tag
git init
git add README.md
git commit -m "first commit"
git remote add origin https://iOS-Git-Path/CHS-HealthModule-iOS.git
git push -u origin master
git tag 版本号 (注:这里的版本号必须和podspec里写的版本号一致)
git push --tags
7.pod spec lint --verbose --allow-warnings --use-libraries
pod repo push CHSSpec CHS-HealthModule-iOS.podspec --verbose --allow-warnings --use-libraries //在这一步知道往哪个spces里面提交
8.进入 /Users/test/.cocoapods/repos/CHSSpec 查看 CHS-HealthModule-iOS/0.1.0/CHS-HealthModule-iOS.podspec
9.修改主工程的podfile文件,把CHS-HealthModule-iOS组件pod进来
source 'https://github.com/CocoaPods/Specs.git'
source "https://iOS-Git-Path/CHSSpec.git"
use_frameworks!
platform :ios, '8.0'
target ‘CHSProject’ do
pod 'CHS-HealthModule-iOS', '2.0.0'
pod 'CHS-HealthModule-iOS', :path=>'../CHS-HealthModule-iOS'
pod 'CHS-HealthModule-iOS', :git => 'https://iOS-Git-Path/CHS-HealthModule-iOS.git', :branch =>'feature/2.0.0'
end
10.pod update CHS-HealthModule-iOS --verbose --no-repo-update || pod install --no-repo-update
一:配置工程的打包环境:
1.将Mach-O Type设为Static Library, framework可以是动态库也可以是静态库,对于系统的framework是动态库,而用户制作的framework只能是静态库。
2.Build Active Architecture Only修改为NO,否则生成的静态库就只支持当前选择设备的架构
3.iOS Deployment Target ,静态库需要支持的最低版本号,要小于等于主项目的版本号;
Valid Architecture 支持的iOS的CPU框架
二:将你要公开的头文件拖至Public下,要隐藏的放在Private或者Project下,当然,隐藏的头文件就无法再被引用。
三:把允许别人引用的头文件引入第一步创建项目时自动生成的CHSFramework.h中,CHSFramework.h 文件的作用是整个包对外提供的入口头文件。
四、合并打包:
分别在模拟器和真机设备下编译,生成两个CHSFramework.framework文件,然后把两个CHSFramework.framework文件中的CHSFramework用命令合成一个,和.a的文件合成命令一样(lipo -create +上面两个文件的路径 + -output + 合成后文件的输出路径 )
example: lipo -create ./Release-iphonesimulator/CHSFramework.framework/CHSFramework ./Release-iphoneos/CHSFramework.framework/CHSFramework -output ./CHSFramework
然后在将生成的CHSFramework替换掉/Release-iphoneos/CHSFramework.framework/CHSFramework,最终得到CHSFramework.framework
5. iOS 配置QQ && 微信分享
微信分享:Identifier weixin URL Schemes WXAPPID
iOS平台
iPhone
应用下载地址:未填写
Bundle ID:cn.CHS.App
测试版本Bundle ID:cn.CHS.App
Universal Links:https://CHS-PATH/apple-app-site-association/
qq分享:Identifier qq URL Schemes QQ十六进制(QQAPPID)
Bundle ID:cn.CHS.App
URL Schema:QQ十六进制(QQAPPID)
Universal Link:https://CHS-PATH/qq_conn/QQAPPID
apple-app-site-association.json 格式:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "AppleTeamId.cn.CHS.App", //公司开发者账号的小组ID.包名id
"paths": [ "*", "/qq_con/QQAPPID/*" ]
}
]
}
注意:
1.错误:#warning:尚未配置[QQ]URL Scheme:QQXXX, 无法进行分享
解决方案:在URL Types中添加QQ的AppID,其格式为:”QQ” + AppId的16进制(如果appId转换的16进制数不够8位则在前面补0,如转换的是:5FB8B52,则最终填入为:QQ05FB8B52 注意:转换后的字母要大写)
6. iOS各手机的设计尺寸大小:
iPhoneSE 的分辨率:1136 * 640 || pt: 568 * 320 @2x
iPhone8 的分辨率:1334 * 750 || pt: 667 * 375 @2x
iPhone8 Plus 的分辨率: 2208 * 1242 || pt: 736 * 414 @3x
iPhoneX 的分辨率:2436 * 1125 || pt: 812 * 375 @3x
iPhoneXr 的分辨率:1792 * 828 || pt: 896 * 414 @2x
iPhoneXs 的分辨率:2436 * 1125 || pt: 812 * 375 @3x
iPhoneXs Max 的分辨率:2688 * 1242 || pt: 896 * 414 @3x
iPhone 11 的分辨率:828*1792px || 414*896pt @2x
iPhone 11 Pro 的分辨率:1125*2436px || 375*812pt @3x
iPhone 11 Pro Max 的分辨率:1242*2688px || 414*896pt @3x
iPhone 12 mini 的分辨率:1080*2340px || 360*780pt @3x
iPhone 12 的分辨率:1170*2532px || 390*844pt @3x
iPhone 12 Pro 的分辨率:1170*2532px || 390*844pt @3x
iPhone 12 Pro Max 的分辨率:1284*2778px || 428*926pt @3x
iPhone 13 mini 的分辨率:1125*2436px || 375*812pt @3x
iPhone 13 的分辨率:1170*2532px || 390*844pt @3x
iPhone 13 Pro 的分辨率:1170*2532px || 390*844pt @3x
iPhone 13 Pro Max 的分辨率:1284*2778px || 428*926pt @3x
7. iOS 开发之 ReactiveCocoa,函数响应式编程,信号(代理,通知,hook事件函数)
1.Map:其实是用来转化传递的信号的值的
RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(idsubscriber) {
[subscriber sendNext:@"石"];
return nil;
}] map:^id(NSString* value) {
if ([value isEqualToString:@"石"]) {
return @"金";
}
return value;
}];
[signal subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
2.flattenMap:它把之前监听的信号转换成另外一个信号,并对新的信号进行监听和处理
@property (nonatomic, strong) RACSignal *switchSignal;
@property (nonatomic, strong) CHSModel *model;
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id < RACSubscriber > subscriber) {
_model = [[CHSModel alloc] init];
[subscriber sendNext:_model];
[subscriber sendCompleted];
return nil;
}];
@weakify(self);
self.switchSignal = [signal flattenMap:^__kindof RACSignal * _Nullable(id _Nullable value) {
CHSModel *model = (CHSModel *)value;
@strongify(self); //
return RACObserve(model, name);
}];
[self.switchSignal subscribeNext:^(id x) {
if (![[NSString stringWithFormat:@"%@",x] isEqualToString:@"(null)"]) {
NSLog(@"subscribeNext - %@", x);
}
}];
_model.name = @"我是林磊";
_model.name = @"我是iOS开发工程师";
3.rac_signalForSelector 代理:
方式一:
@protocol ReactiveObjCViewDelegate <NSObject>
- (void)toExcute:(NSDictionary *)dict withView:(id)view;
@end
@property (nonatomic, weak) id<ReactiveObjCViewDelegate> delegate
- (void)toDo {
if (self.delegate && [self.delegate respondsToSelector:@selector(toExcute: withView:)])
{
[self.delegate toExcute:@{@"name":@"Stone",@"age":@(12)} withView:self];
}
}
_reactiveObjCView.delegate = self;
[[[self rac_signalForSelector:@selector(toExcute: withView:) fromProtocol:@protocol(ReactiveObjCViewDelegate)] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(id dict) {
ReactiveObjCView *view = (ReactiveObjCView *)dict[1];
view.nameLabel.text = @"我是iOS工程师-林磊";
}];
方式二:
@property (nonatomic, strong) RACSubject *delegateSignal;
[[[_submitButton rac_signalForControlEvents:UIControlEventTouchUpInside] doNext:^(__kindof UIControl * _Nullable x) {
NSLog(@"oooooooooooooooo");
}] subscribeNext:^(__kindof UIControl * _Nullable x) {
NSLog(@"被点击了");
// 判断代理信号是否有值
if (self.delegateSignal) {
// 有值,才需要通知
[self.delegateSignal sendNext:@{@"name":@"Stone",@"age":@"16"}];
}
}];
// 设置代理信号
_reactiveObjCView.delegateSignal = [RACSubject subject];
// 订阅代理信号
[_reactiveObjCView.delegateSignal subscribeNext:^(id x) {
NSLog(@"貌似可以替代代理丫丫丫丫--------%@",x);
}];
4.rac_addObserverForName : 通知
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:@"postData" object:nil] subscribeNext:^(NSNotification *notification) {
NSLog(@"%@", notification.name);
NSLog(@"%@", notification.object);
}];
NSMutableArray *dataArray = [[NSMutableArray alloc] initWithObjects:@"1", @"2", @"3", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:@"postData" object:dataArray];
5.RACObserve: kvo属性监听
self.nameLabel = [[UILabel alloc] init];
self.nameLabel.textColor = [UIColor blueColor];
[self addSubview:self.nameLabel];
[self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self);
make.width.equalTo(@240);
make.height.equalTo(@40);
}];
[RACObserve(_nameLabel, text) subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
self.nameLabel.text = @"我是iOS工程师-林磊";
6.rac_signalForControlEvents:按钮点击事件监听
[[[self.submitButton rac_signalForControlEvents:UIControlEventTouchUpInside] doNext:^(__kindof UIControl * _Nullable x) {
NSLog(@"oooooooooooooooo");
}] subscribeNext:^(__kindof UIControl * _Nullable x) {
NSLog(@"被点击了");
}];
7.merge: 信号合并 concat:信号连接
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(idsubscriber) {
[subscriber sendNext:@"纸厂污水"];
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(idsubscriber) {
[subscriber sendNext:@"电镀厂污水"];
return nil;
}];
[[RACSignal merge:@[signalA, signalB]] subscribeNext:^(id x) {
NSLog(@"处理%@",x);
}];
[[signalA concat:signalB] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
8.combineLatest: reduce: 归约
RACSignal *sugarSignal = [RACSignal createSignal:^RACDisposable *(idsubscriber) {
[subscriber sendNext:@"糖"];
return nil;
}];
RACSignal *waterSignal = [RACSignal createSignal:^RACDisposable *(idsubscriber) {
[subscriber sendNext:@"水"];
return nil;
}];
[[RACSignal combineLatest:@[sugarSignal, waterSignal] reduce:^id (NSString* sugar, NSString*water){
return [sugar stringByAppendingString:water];
}] subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
9.filter: 过滤
[[[RACSignal createSignal:^RACDisposable *(idsubscriber) {
[subscriber sendNext:@(15)];
[subscriber sendNext:@(17)];
[subscriber sendNext:@(21)];
[subscriber sendNext:@(14)];
[subscriber sendNext:@(30)];
return nil;
}] filter:^BOOL(NSNumber* value) {
return value.integerValue >= 18;
}] subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
10.then:秩序
[[[[RACSignal createSignal:^RACDisposable *(idsubscriber) {
NSLog(@"打开冰箱门");
[subscriber sendCompleted];
return nil;
}] then:^RACSignal *{
return [RACSignal createSignal:^RACDisposable *(idsubscriber) {
NSLog(@"把大象塞进冰箱");
[subscriber sendCompleted];
return nil;
}];
}] then:^RACSignal *{
return [RACSignal createSignal:^RACDisposable *(idsubscriber) {
NSLog(@"关上冰箱门");
[subscriber sendCompleted];
return nil;
}];
}] subscribeCompleted:^{
NSLog(@"把大象塞进冰箱了");
}];
11.onScheduler: 定时
[[RACSignal interval:60*60*8 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(id x) {
NSLog(@"吃药");
}];
12.delay: 延时
[[[RACSignal createSignal:^RACDisposable *(idsubscriber) {
NSLog(@"等等我,我还有10秒钟就到了");
[subscriber sendNext:nil];
[subscriber sendCompleted];
return nil;
}] delay:10] subscribeNext:^(id x) {
NSLog(@"我到了");
}];
13.retry: 重试
_block int failedCount = 0;
[[[RACSignal createSignal:^RACDisposable *(idsubscriber) {
if (failedCount < 100) {
failedCount++;
NSLog(@"我失败了");
[subscriber sendError:nil];
}else{
NSLog(@"经历了数百次失败后");
[subscriber sendNext:nil];
}
return nil;
}] retry] subscribeNext:^(id x) {
NSLog(@"终于成功了");
}];
14.UITextFeild使用RAC
[self.phoneText.rac_textSignal subscribeNext:^(id x) {
NSString *phoneString = [self phoneFormatter:x];
if (phoneLogin.length >=14) {
self.phoneText.text = [phoneLogin substringToIndex:13];
} else {
self.phoneText.text = phoneLogin;
}
}];
8.swift便利构造函数
1.指定构造方法,不允许出现构造代理器,self.init(...)
init(a:Int,b:Int) {
self.a = a
self.b = b
}
2.便利构造方法 -- 一定是通过调用其他的构造方法来实现初始化,self.init(...)
convenience init(a:Int) {
self.init(a:a,b:0)
}
3.便利构造方法也可以通过调用其他的便利构造方法实现初始化
convenience init() {
self.init(a:0)
}
4.当有派生类时:
4.1 构造方法默认是不会被继承,基类的存储属性只能通过基类的构造方法来初始化
4.2 派生类引入的存储属性要先被初始化,然后再调用父类的构造方法对父类的属性进行初始
4.3 只能通过调用父类的指定构造方法来对父类的属性进行初始化,不能通过便利构造方法
init(c:Int,d:Int) {
self.c = c
self.d = d
super.init(a: 0, b: 0)
}
5.便利构造器,只能通过调用本类中的构造器完成初始化,不允许出现super.init()
convenience init(a:Int,b:Int,c:Int,d:Int) {
self.init(c:c,d:d)
}
9. RxSwift的使用
1.监听系统通知:
var disposeBag = DisposeBag()
//监听系统通知:
NotificationCenter.default.rx.notification(UIApplication.willEnterForegroundNotification).takeUntil(self.rx.deallocated).subscribe(onNext: { (value) in
print(value)
}).disposed(by: self.disposeBag)
2.监听自定义通知:
NotificationCenter.default.rx.notification(Notification.Name(rawValue: "personSingal")).takeUntil(self.rx.deallocated).subscribe(onNext: { notification in
//获取通知数据
let userInfo = notification.userInfo as! [String: AnyObject]
let value1 = userInfo["name"] as! String
let value2 = userInfo["age"] as! Int
print("获取到通知,用户数据是[\(value1),\(value2)]")
}).disposed(by: self.disposeBag)
NotificationCenter.default.post(name: Notification.Name(rawValue: "personSingal"), object: self,userInfo: ["name":"Stone", "age" : 24])
3.获取事件:
var disposeBag = DisposeBag()
doBtn.rx.tap
.subscribe(onNext: {
print("按钮已被点击")
})
.disposed(by: self.disposeBag)
doBtn.rx.tap.asObservable().subscribe(onNext: { (result) in
print("按钮已被点击")
}, onError: nil, onCompleted: nil, onDisposed: nil).disposed(by: self.disposeBag)
4.kvo
var disposeBag = DisposeBag()
@objc dynamic var kvoValue:String = String()
self.rx.observe(String.self, "kvoValue")
.subscribe(onNext: { newValue in
print("\(String(describing: newValue))")
})
.disposed(by: disposeBag)
self.perform(#selector(toSetInterval(param:)), with:"I am Stone", afterDelay: 3.0)
@objc func toSetInterval(param:String) {
self.kvoValue = param
}
网友评论