More Related Content Similar to in in der 響應式編程 (20) in in der 響應式編程1. in in der
響應式編程
張景隆
!
iOS Dev Club
蘋果貓咖啡
MOPCON
2014
4. What is ReactiveCocoa
ReactiveCocoa is an open source library that brings
Functional Reactive Programming paradigm to
Objective-C. It was created by Josh Abernathy &
Justin Spahr-Summers in the development of GitHub
for Mac.
13. Agenda
• 介紹 FRP
• 事件與⾮非同步等問題
• 介紹 ReactiveCocoa
• RAC 基礎
• RAC Example
• iOS Dev Club 社群介紹
19. Functional Programming
Swift:
map(1...3){ $0 * 5 }
ObjC:
NSMutableArray *arr = [NSMutableArray new];
for(int i=1; i<=3; i++) {
[arr addObject:@(i * 5)];
}
22. RAC dealing with
One of the major advantages of RAC is
that it provides a single, unified approach
to dealing with
!
1. asynchronous behaviors,
2. including delegate methods,
3. callback blocks,
4. target-action mechanisms,
5. notifications,
6. and KVO.
24. Mattt Thompson :
“ The brave new era for Objective-C “
Justin DeWind :
“ The Future of Cocoa Programming “
http://nshipster.com/reactivecocoa/
http://spin.atomicobject.com/2013/04/28/reactivecocoa/
29. Cold or Hot Signals
• Hot Signals
• 按鈕事件
• 事件即時通知
!
• Cold Signals
• 網路事件
• 不會⾺馬上有結果
30. Macros
• RACObserve()
• 建⽴立 RACSignal
• 數值變動發動
!
!
• RAC()
• 放在 assignment operator 的左邊
• 綁定 RACSignal 給的數值
31. RACObserve
new value
!
!
[RACObserve(self,
username)
subscribeNext:^(NSString
*newName)
{
self.consoleLabel.text
=
newName;
}];
RACSignal Subscriber
35. Example I
! • rac_textSignal
• map
• avoiding retain cycles
37. Example I
#import <RACEXTScope.h>
@weakify(self);
[[self.textField.rac_textSignal
map:^id(id value) {
return [value uppercaseString];
}]
subscribeNext:^(id x) {
@strongify(self);
self.console.text = x;
}];
40. Example II
RACSignal *nameSignal = self.nameTextField.rac_textSignal;
RACSignal *passSignal = self.passTextField.rac_textSignal;
RAC(self.loginButton, enabled) =
[RACSignal combineLatest:@[nameSignal, passSignal]
reduce:^id(NSString *name, NSString *pass){
return @( ![name isEqualToString:@""] &&
![pass isEqualToString:@""] );
}];
42. Example III
!
RACSignal *tokenSignal = [[NSUserDefaults
standardUserDefaults]
rac_channelTerminalForKey:@"token"];
[[tokenSignal filter:^BOOL(NSString *token) {
return [token chuzzle]?YES:NO;
}]
subscribeNext:^(NSString *token) {
[self loadData];
}];
44. AFNetworkReachabilityManager *reachabilityManager =
[AFNetworkReachabilityManager sharedManager];
RACSignal *isReachable =
[RACObserve(
reachabilityManager, networkReachabilityStatus)
map:^(NSNumber *networkReachabilityStatus) {
switch (networkReachabilityStatus.intValue) {
case AFNetworkReachabilityStatusReachableViaWWAN:
case AFNetworkReachabilityStatusReachableViaWiFi:
return @YES;
}
return @NO;
}];
45. [[AFHTTPRequestOperationManager alloc] init];
!
NSString *URLString = @"http://ip.jsontest.com";
AFHTTPRequestOperationManager *manager =
RACSignal *myIPSignal = [RACSignal createSignal:^RACDisposable
*(id<RACSubscriber> subscriber) {
[manager GET:URLString parameters:nil
success:^(AFHTTPRequestOperation *op, id response) {
!
} failure:^(AFHTTPRequestOperation *op, NSError *e) {
!
}
];
return nil;
}];
[subscriber sendNext:response];
[subscriber sendCompleted];
[subscriber sendError:e];
[myIPSignal subscribeNext:^(id response) {
//
NSLog(@"My IP => %@", response[@"ip"]);
}];
46. Example V
• 檢查 網路狀態 以及 雲端伺服器 是否正常
• 使⽤用者是否啟⽤用同步功能
• 有待同步資料
• 需綁定 FB Account
• 可設定 WIFI 或 3G 底下同步
48. RACSignal *networkSignal = RACObserve(self, isNetworkReachable);
RACSignal *cloudSignal = RACObserve(self, isUsedCloud);
RACSignal *facebookSignal = RACObserve(self, isFacebookBinding);
RACSignal *wifiOnlySignal = RACObserve(self, isWifiSyncOnly);
!
NSArray *signals = @[networkSignal, cloudSignal, facebookSignal,
wifiOnlySignal];
RACSignal *preparedSignal = [RACSignal combineLatest:signals
reduce:^id (id network, id cloud, id facebook, id wifi){
return @([network boolValue] && [cloud boolValue] && [facebook
boolValue] && [wifi boolValue]);
}];
RACSignal *queueSignal = RACObserve(self, uploadQueue);
[[[RACSignal combineLatest:@[preparedSignal, queueSignal]]
filter:^BOOL(RACTuple *tuple) {
return [[tuple first] boolValue];
}]
subscribeNext:^(RACTuple *tuple) {
//
id task = [tuple second];
// do something ...
}];
49. RACSignal *queueSignal = RACObserve(self, uploadQueue);
[[[RACSignal combineLatest:@[preparedSignal, queueSignal]]
filter:^BOOL(RACTuple *tuple) {
return [[tuple first] boolValue];
}]
subscribeNext:^(RACTuple *tuple) {
deliverOn:[RACScheduler scheduler]]
//
id task = [tuple second];
// do something ...
}];
[
Asynchronous Operation
51. Recap
• RACSequence & RACSignal 的差別
• 熱信號 與 冷信號
• 實⽤用的 Macros: RACObserve() & RAC()
• 信號 的 建⽴立、訂閱、合併、轉換、過濾
• 如何建⽴立⾮非同步的網路信號
53. ! iOS Dev Club 開發者聚會
iOS Dev Club 成⽴立於 2011 年 5 ⽉月。
我們是以 Facebook 的社團(groups)成⽴立,主要是為了在中部附近的 iOS App 設計
開發同好,可以經常性碰⾯面互相學習的聚會,我們的地點都選擇在咖啡館,固
定在每個⽉月最後⼀一週的星期六上午,每次都會安排主題分享研習。
!
第⼀一年,我們在彰化的顏⽒氏牧場II舉辦。
第⼆二年,我們在台中的默契咖啡舉辦。
第三年,我們挑戰環島~
!
因為每個⽉月中旬發出聚會訊息時,最常⾒見的歎息就是:為什麼不是在XXX?
(XXX=請⾃自⾏行帶⼊入離⾃自⼰己居住熟悉或最近的城市)
於是第三年,我們分別在台北、新⽵竹、台中、⾼高雄辦了六場的 iOS Dev Club 開環
島開發這聚會,我們到這幾個城市拜訪當地的 iOS 開發社團、專業的程式設計社
團,互相交流也互相認識。
!
第四年,我們來到了台中市⻯⿓龍井區的蘋果貓咖啡舉辦,我們除了在這裡每個⽉月
舉辦⼀一次之外,也會陸續在每週都有研習課程加⼊入,請⼤大家密切注意我們在
Facebook 粉絲專⾴頁發佈的活動資訊。
http://iosdev.club/
66. 有問題 請上
iOS Dev Club
https://www.facebook.com/ios.dev.club