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

开发中记录的点点滴滴

作者: 许久__ | 来源:发表于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