開發(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
一:配置工程的打包環(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
}