美文网首页
开发中记录的点点滴滴

开发中记录的点点滴滴

作者: 许久__ | 来源:发表于2021-09-07 11:33 被阅读0次

开发中记录的点点滴滴

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

4. iOS 打包成framework

一:配置工程的打包环境:
    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
}

相关文章

网友评论

      本文标题:开发中记录的点点滴滴

      本文链接:https://www.haomeiwen.com/subject/okguwltx.html