開發(fā)中記錄的點(diǎn)點(diǎn)滴滴

開發(fā)中記錄的點(diǎn)點(diǎn)滴滴

1. iOS 逆向篇

常用命令:

0.ps -e | grep WeChat
1.看是否被砸殼:otool -l Mach-o路徑 | grep crypt   cryptid 1赞哗,這表明這個(gè)項(xiàng)目文件還未沒砸殼,0則表示已經(jīng)完成砸殼
2.遠(yuǎn)程拷貝命令:scp /Applications/Reveal.app/Contents/SharedSupport/iOS-Libraries/RevealServer.framework/libReveal.dylib root@192.168.197.146:/Library/RHRevealLoader/libReveal.dylib
3.導(dǎo)出頭文件: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 中含有的動(dòng)態(tài)庫:otool -L aisiweb | grep ".dylib"
9.架構(gòu)拆分與合并:
    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.恢復(fù)符號(hào)表:./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

簽名企業(yè)微信:
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

刪除動(dòng)態(tài)庫:
optool uninstall -p "@executable_path/Frameworks/sutuplus.dylib" -t WeChat

查找依賴的動(dòng)態(tài)庫:
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

向可執(zhí)行文件中注入framework:
insert_dylib @rpath/TLocationPlugin.framework/TLocationPlugin WeChat --all-yes --weak WeChat

重簽名framework:
codesign -fs 6D1DCFE0B265D7324DBC0824AC337D36103169CB TLocationPlugin.framework

Mac上看可執(zhí)行問價(jià)是否被加殼:
otool -l WeChat | grep crypt

2.iOS arm64匯編相關(guān)知識(shí)整理:

1.寄存器: ARM64 有34個(gè)寄存器交播,包括31個(gè)通用寄存器麸锉、SP、PC展姐、CPSR
2.通用寄存器:x0~x28(64位的) (w0~w28(32位)對(duì)應(yīng)的的x0~x28的低32位) 茄唐,x0~x7一般是用來存儲(chǔ)函數(shù)的參數(shù)孝扛,更多參數(shù),則用堆棧來傳遞乎芳,x0一般用作函數(shù)的返回值
3.PC: 程序計(jì)數(shù)器遵蚜,存儲(chǔ)著當(dāng)前執(zhí)行的指令
4.FP:棧頂指針帖池,指向一個(gè)棧幀的頂部,當(dāng)函數(shù)發(fā)生跳轉(zhuǎn)時(shí)吭净,會(huì)記錄當(dāng)時(shí)的棧的起始位置睡汹。
5.SP:棧指針(也稱為棧底指針),指向棧當(dāng)前的位置
6.CPSR:狀態(tài)寄存器
      NZCV是狀態(tài)寄存器的條件標(biāo)志位攒钳,分別代表運(yùn)算過程中產(chǎn)生的狀態(tài)帮孔,其中:
      N, negative condition flag,一般代表運(yùn)算結(jié)果是負(fù)數(shù)
      Z, zero condition flag, 指令結(jié)果為0時(shí)Z=1不撑,否則Z=0文兢;
      C, carry condition flag, 無符號(hào)運(yùn)算有溢出時(shí),C=1焕檬。
      V, oVerflow condition flag 有符號(hào)運(yùn)算有溢出時(shí)姆坚,V=1。
7.LR:通常稱X30為程序鏈接寄存器实愚,保存子程序結(jié)束后需要執(zhí)行的下一條指令
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的和的地址值內(nèi)的數(shù)據(jù)傳送到X5
ldp    x29, x30, [sp, #0x10]    ldp :load pair 一對(duì)寄存器, 從內(nèi)存讀取數(shù)據(jù)到寄存器
    
str    X0, [sp, #0x8]           st:store, str:往內(nèi)存中寫數(shù)據(jù)(偏移值為正); X0寄存器的數(shù)據(jù)傳送到SP+0x8地址值指向的存儲(chǔ)空間
stur   w0, [x29, #-0x8]         往內(nèi)存中寫數(shù)據(jù)(偏移值為負(fù))
stp    x29, x30, [sp, #0x10]    store pair,存放一對(duì)數(shù)據(jù), 入棧指令
    
cmp   比較指令会钝,影響程序狀態(tài)寄存器CPSR 
b     跳轉(zhuǎn)指令伐蒋,可帶條件跳轉(zhuǎn)與cmp配合使用
bl    帶返回的跳轉(zhuǎn)指令, 返回地址保存到LR(X30)  
    
ret:函數(shù)返回顽素,相當(dāng)于return
    
    
葉子函數(shù):
void test(){
    int a = 2;
    int b = 3;
}
sub sp, sp, #16             ; =16咽弦,sp棧頂指針上移16個(gè)字節(jié)
.cfi_def_cfa_offset 16
mov w8, #2                  ;將2存入w8寄存器
str w8, [sp, #12]           ;將w8寄存器的數(shù)據(jù)存入到sp下移12個(gè)字節(jié)的所在位置下面的4字節(jié)
mov w8, #3                  ;將3存入w8寄存器
str w8, [sp, #8]            ;將w8寄存器的數(shù)據(jù)存入到sp下移8個(gè)字節(jié)的所在位置下面的4字節(jié)
add sp, sp, #16             ; =16,sp棧頂指針下移16個(gè)字節(jié)胁出,恢復(fù)到初始位置
ret
    
非葉子函數(shù),除了葉子函數(shù)段审,其他函數(shù)叫非葉子函數(shù):
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.創(chuàng)建遠(yuǎn)程索引庫:
    CHSSpec   專門用來存放索引文件   Public  Initialize this repository with a README  objc
2.創(chuàng)建本地索引庫:
    1.查看一下當(dāng)前有哪些本地索引庫: pod repo
    2.pod repo add <本地索引庫的名字>  <遠(yuǎn)程索引庫的地址> (pod repo add CHSSpec https://iOS-Git-Path/CHSSpec)
    3.通過下面的方式可以查看本地索引庫的物理地址: /Users/test/.cocoapods/repos/CHSSpec
3.創(chuàng)建遠(yuǎn)程代碼庫(代碼實(shí)際存放的遠(yuǎn)程倉庫):
    CHS-HealthModule-iOS   代碼文件   Public  
4.創(chuàng)建本地代碼庫(注意代碼與主工程是平級(jí)關(guān)系)
    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下進(jìn)行pod install(把剛才拖入到classes里的文件夾pod進(jìn)來)
    5.編譯并運(yùn)行全蝶,根據(jù)需要修改podspecs索引文件
    6.編譯運(yùn)行通過后,提交組件到遠(yuǎn)程代碼庫并打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 版本號(hào) (注:這里的版本號(hào)必須和podspec里寫的版本號(hào)一致)
        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  //在這一步知道往哪個(gè)spces里面提交
    8.進(jìn)入 /Users/test/.cocoapods/repos/CHSSpec 查看 CHS-HealthModule-iOS/0.1.0/CHS-HealthModule-iOS.podspec
    9.修改主工程的podfile文件,把CHS-HealthModule-iOS組件pod進(jìn)來
        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

一:配置工程的打包環(huán)境:
    1.將Mach-O Type設(shè)為Static Library抑淫, framework可以是動(dòng)態(tài)庫也可以是靜態(tài)庫绷落,對(duì)于系統(tǒng)的framework是動(dòng)態(tài)庫,而用戶制作的framework只能是靜態(tài)庫始苇。
    2.Build Active Architecture Only修改為NO砌烁,否則生成的靜態(tài)庫就只支持當(dāng)前選擇設(shè)備的架構(gòu)
    3.iOS Deployment Target ,靜態(tài)庫需要支持的最低版本號(hào)催式,要小于等于主項(xiàng)目的版本號(hào)函喉;
        Valid Architecture 支持的iOS的CPU框架
    
二:將你要公開的頭文件拖至Public下,要隱藏的放在Private或者Project下荣月,當(dāng)然管呵,隱藏的頭文件就無法再被引用。
    
三:把允許別人引用的頭文件引入第一步創(chuàng)建項(xiàng)目時(shí)自動(dòng)生成的CHSFramework.h中哺窄,CHSFramework.h 文件的作用是整個(gè)包對(duì)外提供的入口頭文件捐下。
    
四、合并打包:
    分別在模擬器和真機(jī)設(shè)備下編譯萌业,生成兩個(gè)CHSFramework.framework文件坷襟,然后把兩個(gè)CHSFramework.framework文件中的CHSFramework用命令合成一個(gè),和.a的文件合成命令一樣(lipo -create +上面兩個(gè)文件的路徑 + -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平臺(tái)
    iPhone
    應(yīng)用下載地址:未填寫
    Bundle ID:cn.CHS.App
    測(cè)試版本Bundle ID:cn.CHS.App
    Universal Links:https://CHS-PATH/apple-app-site-association/

qq分享:Identifier qq        URL Schemes QQ十六進(jìn)制(QQAPPID)
    Bundle ID:cn.CHS.App
    URL Schema:QQ十六進(jìn)制(QQAPPID)
    Universal Link:https://CHS-PATH/qq_conn/QQAPPID

 apple-app-site-association.json 格式:
    {
    "applinks": {
        "apps": [],
        "details": [
            {
                "appID": "AppleTeamId.cn.CHS.App",  //公司開發(fā)者賬號(hào)的小組ID.包名id
                "paths": [ "*", "/qq_con/QQAPPID/*" ]
            }
        ]
    } 

注意:
1.錯(cuò)誤:#warning:尚未配置[QQ]URL Scheme:QQXXX, 無法進(jìn)行分享
解決方案:在URL Types中添加QQ的AppID生年,其格式為:”QQ” + AppId的16進(jìn)制(如果appId轉(zhuǎn)換的16進(jìn)制數(shù)不夠8位則在前面補(bǔ)0婴程,如轉(zhuǎn)換的是:5FB8B52,則最終填入為:QQ05FB8B52 注意:轉(zhuǎn)換后的字母要大寫)  

6. iOS各手機(jī)的設(shè)計(jì)尺寸大芯Э颉:

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 開發(fā)之 ReactiveCocoa,函數(shù)響應(yīng)式編程,信號(hào)(代理排抬,通知,hook事件函數(shù))

1.Map:其實(shí)是用來轉(zhuǎn)化傳遞的信號(hào)的值的
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:它把之前監(jiān)聽的信號(hào)轉(zhuǎn)換成另外一個(gè)信號(hào)授段,并對(duì)新的信號(hào)進(jìn)行監(jiān)聽和處理
@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開發(fā)工程師";

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(@"被點(diǎn)擊了");
    // 判斷代理信號(hào)是否有值
    if (self.delegateSignal) {
    // 有值蹲蒲,才需要通知
        [self.delegateSignal sendNext:@{@"name":@"Stone",@"age":@"16"}];
    }
}];
// 設(shè)置代理信號(hào)
_reactiveObjCView.delegateSignal = [RACSubject subject];
// 訂閱代理信號(hào)
[_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屬性監(jiān)聽
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:按鈕點(diǎn)擊事件監(jiān)聽 
[[[self.submitButton rac_signalForControlEvents:UIControlEventTouchUpInside] doNext:^(__kindof UIControl * _Nullable x) {
    NSLog(@"oooooooooooooooo");
}] subscribeNext:^(__kindof UIControl * _Nullable x) {
    NSLog(@"被點(diǎn)擊了");
}];

7.merge: 信號(hào)合并   concat:信號(hào)連接
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(@"把大象塞進(jìn)冰箱");
        [subscriber sendCompleted];
        return nil;
    }];
}] then:^RACSignal *{
    return [RACSignal createSignal:^RACDisposable *(idsubscriber) {
        NSLog(@"關(guān)上冰箱門");
        [subscriber sendCompleted];
        return nil;
    }];
}] subscribeCompleted:^{
    NSLog(@"把大象塞進(jìn)冰箱了");
}];

11.onScheduler: 定時(shí)
[[RACSignal interval:60*60*8 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(id x) {
    NSLog(@"吃藥");
}];

12.delay: 延時(shí)
[[[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(@"經(jīng)歷了數(shù)百次失敗后");
        [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便利構(gòu)造函數(shù)

1.指定構(gòu)造方法侵贵,不允許出現(xiàn)構(gòu)造代理器届搁,self.init(...)
init(a:Int,b:Int) {
    self.a = a
    self.b = b
}
2.便利構(gòu)造方法 -- 一定是通過調(diào)用其他的構(gòu)造方法來實(shí)現(xiàn)初始化,self.init(...)
convenience init(a:Int) {
    self.init(a:a,b:0)
}
3.便利構(gòu)造方法也可以通過調(diào)用其他的便利構(gòu)造方法實(shí)現(xiàn)初始化
convenience init() {
    self.init(a:0)
}
4.當(dāng)有派生類時(shí):
4.1 構(gòu)造方法默認(rèn)是不會(huì)被繼承窍育,基類的存儲(chǔ)屬性只能通過基類的構(gòu)造方法來初始化
4.2 派生類引入的存儲(chǔ)屬性要先被初始化卡睦,然后再調(diào)用父類的構(gòu)造方法對(duì)父類的屬性進(jìn)行初始
4.3 只能通過調(diào)用父類的指定構(gòu)造方法來對(duì)父類的屬性進(jìn)行初始化,不能通過便利構(gòu)造方法
init(c:Int,d:Int) {
    self.c = c
    self.d = d
    super.init(a: 0, b: 0)
}
5.便利構(gòu)造器漱抓,只能通過調(diào)用本類中的構(gòu)造器完成初始化表锻,不允許出現(xiàn)super.init()
convenience init(a:Int,b:Int,c:Int,d:Int) {
    self.init(c:c,d:d)
}

9. RxSwift的使用

1.監(jiān)聽系統(tǒng)通知:
var disposeBag = DisposeBag()
//監(jiān)聽系統(tǒng)通知:
NotificationCenter.default.rx.notification(UIApplication.willEnterForegroundNotification).takeUntil(self.rx.deallocated).subscribe(onNext: { (value) in
    print(value)
}).disposed(by: self.disposeBag)

2.監(jiān)聽自定義通知:
NotificationCenter.default.rx.notification(Notification.Name(rawValue: "personSingal")).takeUntil(self.rx.deallocated).subscribe(onNext: { notification in
    //獲取通知數(shù)據(jù)
    let userInfo = notification.userInfo as! [String: AnyObject]
    let value1 = userInfo["name"] as! String
    let value2 = userInfo["age"] as! Int
    print("獲取到通知,用戶數(shù)據(jù)是[\(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("按鈕已被點(diǎn)擊")
})
.disposed(by: self.disposeBag)
doBtn.rx.tap.asObservable().subscribe(onNext: { (result) in
    print("按鈕已被點(diǎn)擊")
}, 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
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末乞娄,一起剝皮案震驚了整個(gè)濱河市瞬逊,隨后出現(xiàn)的幾起案子显歧,更是在濱河造成了極大的恐慌,老刑警劉巖确镊,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件士骤,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡蕾域,警方通過查閱死者的電腦和手機(jī)拷肌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來旨巷,“玉大人巨缘,你說我怎么就攤上這事∑跄” “怎么了带猴?”我有些...
    開封第一講書人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)懈万。 經(jīng)常有香客問我拴清,道長(zhǎng),這世上最難降的妖魔是什么会通? 我笑而不...
    開封第一講書人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任口予,我火速辦了婚禮,結(jié)果婚禮上涕侈,老公的妹妹穿的比我還像新娘沪停。我一直安慰自己,他們只是感情好裳涛,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開白布木张。 她就那樣靜靜地躺著,像睡著了一般端三。 火紅的嫁衣襯著肌膚如雪舷礼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,821評(píng)論 1 290
  • 那天郊闯,我揣著相機(jī)與錄音妻献,去河邊找鬼。 笑死团赁,一個(gè)胖子當(dāng)著我的面吹牛育拨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播欢摄,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼熬丧,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了怀挠?” 一聲冷哼從身側(cè)響起锹引,我...
    開封第一講書人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤矗钟,失蹤者是張志新(化名)和其女友劉穎唆香,沒想到半個(gè)月后嫌变,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡躬它,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年腾啥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冯吓。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡倘待,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出组贺,到底是詐尸還是另有隱情凸舵,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布失尖,位于F島的核電站啊奄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏掀潮。R本人自食惡果不足惜菇夸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望仪吧。 院中可真熱鬧庄新,春花似錦、人聲如沸薯鼠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽出皇。三九已至羞芍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間恶迈,已是汗流浹背涩金。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留暇仲,地道東北人步做。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像奈附,于是被迫代替她去往敵國和親全度。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • 16宿命:用概率思維提高你的勝算 以前的我是風(fēng)險(xiǎn)厭惡者斥滤,不喜歡去冒險(xiǎn)将鸵,但是人生放棄了冒險(xiǎn)勉盅,也就放棄了無數(shù)的可能。 ...
    yichen大刀閱讀 6,041評(píng)論 0 4
  • 公元:2019年11月28日19時(shí)42分農(nóng)歷:二零一九年 十一月 初三日 戌時(shí)干支:己亥乙亥己巳甲戌當(dāng)月節(jié)氣:立冬...
    石放閱讀 6,876評(píng)論 0 2