SlideShare une entreprise Scribd logo
1  sur  48
Télécharger pour lire hors ligne
var$RAC3$=$Reac,veCocoa$+$Swi2 
@ikesyo 
#rac_tokyo 
Reac%veCocoa)Tokyo)2014110118)Sat)@freee株式会社
@ikesyo 
いけしょー/池田翔 
京都でフリーランスのiOS/Android 
エンジニアしています 
甘いもの大好き!! 
!!お仕事待ってます!!! 
現在フリュー㈱にて 
一部RAC3を使ってお仕事中!
Reac%veCocoaのコミッター(Contributor)やってます
今日はSwi$ベースになった 
Reac%veCocoa)3.0のご紹介
※!注意 
2014%10%16,(Xcode(6.1(GM(seed(2時点,( 
swi4%api%reduxブランチ(#1532)の内容に基づきます 
APIやクラス名など今後変更される可能性は大いにあります 
※!実際に7/26の!#rac_kansai!から大きく変わっています……!※
RAC$3.0
元々はこれ 
h"ps://github.com/Reac3veCocoa/ 
Reac3veCocoa/pull/966
_人人人人人人人_ 
> 突然のSwi$ < 
‾Y^Y^Y^Y^Y^Y‾
だけではなく 
RACDC%2014:%June%3rd@Github 
• The$Future$Of$Reac.veCocoa$by$Jus.n$Spahr9Summers$•$ 
GitHub$Reac.ve$Cocoa$Developer$Conference 
• h#p://vimeo.com/98100163 
• h#ps://github.com/jspahrsummers/the<future<of< 
reac>vecocoa
h"ps://github.com/jspahrsummers/ 
RxSwi8 
を経て
The$Great$Swi,ening$(a.k.a.$the$ 
new$3.0) 
h"ps://github.com/Reac3veCocoa/ 
Reac3veCocoa/pull/1382
New$Concepts 
• Generics)Support 
• ColdSignal)!)Producer)! 
• Subscriber)!)Consumer)! 
• HotSignal)!)Signal)! 
• ObservableProperty)!)SignalingProperty)! 
• !)Promise)! 
• Action
Generics(Support 
型パラメータは当然サポート 
public struct ColdSignal<T> {} 
public final class Subscriber<T>: SinkType {} 
extension NSNotificationCenter { 
public func rac_notifications 
(name: String? = nil, object: AnyObject? = nil) 
-> HotSignal<NSNotification> 
} 
extension NSURLSession { 
public func rac_dataWithRequest 
(request: NSURLRequest) 
-> ColdSignal<(NSData, NSURLResponse)> 
}
ColdSignal 
• Cold&RACSignal:&Event&Stream 
• Subscriberをアタッチしてイベントを購読する 
• Subscriber毎に受け取るイベントやタイミングは異なる 
• SubscriberがDisposableを持っていて、ColdSignal生成 
時のクロージャではDisposableを返さない 
• subscriber.disposable.addDisposable(...)
ColdSignal.swi-public 
struct ColdSignal<T> { 
public init(generator: Subscriber<T> -> ()) // +[RACSignal createSignal:] 
public static func empty() -> ColdSignal // +[RACSignal empty] 
public static func single(value: T) -> ColdSignal // +[RACSignal return:] 
public static func error(error: NSError) -> ColdSignal // +[RACSignal error:] 
public static func never() -> ColdSignal // +[RACSignal never] 
// -[RACSignal subscribe:] 
public func subscribe(subscriber: Subscriber<T>) -> Disposable 
// -[RACSignal subscribeNext:error:completed:] 
public func subscribe( 
next: T -> () = doNothing, 
error: NSError -> () = doNothing, 
completed: () -> () = doNothing 
) -> Disposable 
}
ColdSignalの生成例 
extension RACSignal { 
public func asColdSignal() -> ColdSignal<AnyObject?> { 
return ColdSignal { subscriber in 
let next = { (obj: AnyObject?) -> () in 
subscriber.put(.Next(Box(obj))) 
} 
let error = { (maybeError: NSError?) -> () in 
let nsError = maybeError.orDefault(RACError.Empty.error) 
subscriber.put(.Error(nsError)) 
} 
let completed = { 
subscriber.put(.Completed) 
} 
let disposable: RACDisposable? = self.subscribeNext(next, error: error, completed: completed) 
subscriber.disposable.addDisposable(disposable) 
} 
} 
}
Subscriber 
• like:'id<RACSubscriber> subscriber 
• SinkTypeプロトコルのputにEvent<T>でラップした値を渡す 
• public func put(event: Event<T>) {} 
• 従来の'-sendNext:'などの代わり 
• Event<T> -> ()'のクロージャをハンドラー本体として 
Subscriberを初期化し、ColdSignalのsubscribeに渡せる
Subscriber.swi+ 
public final class Subscriber<T>: SinkType { 
public typealias Element = Event<T> 
public let disposable = CompositeDisposable() 
public init<S: SinkType where S.Element == Event<T>>(_ sink: S) 
public convenience init(handler: Event<T> -> ()) 
public convenience init( 
next: T -> (), 
error: NSError -> (), 
completed: () -> ()) 
public func put(event: Event<T>) 
}
Subscriberの使用例 
extension ColdSignal { 
public func asDeferredRACSignal<U: AnyObject> 
(evidence: ColdSignal -> ColdSignal<U?>) -> RACSignal { 
return RACSignal.createSignal { subscriber in 
let selfDisposable = evidence(self).subscribe(next: { value in 
subscriber.sendNext(value) 
}, error: { error in 
subscriber.sendError(error) 
}, completed: { 
subscriber.sendCompleted() 
}) 
return RACDisposable { 
selfDisposable.dispose() 
} 
} 
} 
}
補足1 
• evidenceという型チェックにより、特定の型パラメータを持 
つColdSignalでのみメソッドを呼べるように制限 
• Objec've)CとのブリッジなのでStructやEnumは渡せず、 
AnyObjectでクラスオブジェクトだけに制限 
• 使い方:,引数に,identityという関数を渡すだけ
Iden%ty.swi, 
/// The identity function, which returns its argument. 
/// 
/// This can be used to prove to the typechecker that a given type A is 
/// equivalent to a given type B. 
/// 
/// For example, the following global function is normally impossible to bring 
/// into the `Signal<T>` class: 
/// 
/// func merge<U>(signal: Signal<Signal<U>>) -> Signal<U> 
/// 
/// However, you can work around this restriction using an instance method with 
/// an “evidence” parameter: 
/// 
/// func merge<U>(evidence: Signal<T> -> Signal<Signal<U>>) -> Signal<U> 
/// 
/// Which would then be invoked with the identity function, like this: 
/// 
/// signal.merge(identity) 
/// 
/// This will verify that `signal`, which is nominally `Signal<T>`, is logically 
/// equivalent to `Signal<Signal<U>>`. If that's not actually the case, a type 
/// error will result. 
public func identity<T>(id: T) -> T { 
return id 
}
補足2 
• 例えばScalaではGeneralized-Type-Constraintsという言語機能で 
同様の制限が可能 
• h6p://yuroyoro.hatenablog.com/entry/ 
20100914/1284471301 
• h6p://www.ne.jp/asahi/hishidama/home/tech/scala/ 
generics.html#hgeneralizedtype_constraints
HotSignal 
• Hot%RACSignal:%Push+driven%stream 
• CompletedやErrorによる終了はない 
• T -> ()%のクロージャがオブサーバー%SinkOf<T>%となって 
observeする 
• ColdSignalのSubscriberと異なり、全てのオブザーバー 
が同じイベントを同じタイミングで受け取る
HotSignal.swi-public 
final class HotSignal<T> { 
public init(_ generator: SinkOf<T> -> ()) 
public class func never() -> HotSignal 
public func observe<S: SinkType where S.Element == T> 
(observer: S) -> Disposable 
public func observe(next: T -> ()) -> Disposable 
}
HotSignalの生成例 
extension NSNotificationCenter { 
public func rac_notifications 
(name: String? = nil, object: AnyObject? = nil) 
-> HotSignal<NSNotification> 
{ 
let disposable = ScopedDisposable(SerialDisposable()) 
return HotSignal { sink in 
let observer = self.addObserverForName(name, object: object, queue: nil) { notification in 
sink.put(notification) 
} 
disposable.innerDisposable.innerDisposable = ActionDisposable { 
self.removeObserver(observer) 
} 
return () 
} 
} 
}
HotSignal/Observer(SinkOf<T>)の使用例 
extension HotSignal { 
/// Creates a RACSignal that will forward values from the receiver. 
/// 
/// evidence - Used to prove to the typechecker that the receiver is 
/// a signal of objects. Simply pass in the `identity` function. 
/// 
/// Returns an infinite signal that will forward all values from the 
/// underlying HotSignal. The returned RACSignal will never complete or 
/// error, so it must be disposed manually. 
public func asInfiniteRACSignal<U: AnyObject> 
(evidence: HotSignal -> HotSignal<U?>) -> RACSignal { 
return RACSignal.createSignal { subscriber in 
evidence(self).observe { subscriber.sendNext($0) } 
return nil 
} 
} 
}
ObservableProperty 
• 値の変更をColdSignalとして通知することができるプロパテ 
ィ用オブジェクト 
• KVOの代替手段:&Swi*のクラスにはKVOがなく、監視される側 
が自分から通知できるように公開するため? 
• !&func __conversion()&によりラップされた値を透過的に 
使用することができる&!&Swi*&1.0でなくなりました!
ObservableProperty.swi1 
public final class ObservableProperty<T> { 
public func values() -> ColdSignal<T> 
// setするとvalues()の戻り値のColdSignalのsubscriberに通知される 
public var value: T 
// not public: ミス or 他からの変換? 
init(_ value: T) 
/** 
public func __conversion() -> T 
public func __conversion() -> Signal<T> 
*/ 
} 
extension ObservableProperty: SinkType { 
public func put(value: T) 
}
ObservablePropertyの使用例 
public class Hoge { 
let name: ObservableProperty<String> = ObservableProperty("nanashi") 
} 
public func printName(name: String) { 
println(name) 
} 
let hoge = Hoge() 
printName(hoge.name.value) 
// => nanashi 
hoge.name.values().subscribe(next: { name in 
println("(name): name was changed!") 
}) 
// => nanashi: name was changed! : 最初に現在値が通知される 
hoge.name.value = "ikesyo" 
// or 
hoge.name.put("ikesyo") // by SinkType 
// => ikesyo: name was changed!
!!Promise!! 
• 単一の値を生成(resolve)する遅延タスクを表現する 
• ProducerのようなEvent-Streamではないので複数の値を通知 
したりはしない 
• 値は-public let signal: Signal<T?>-でSignalとして参 
照できる 
• resolve前:-nil,-resolve後:-生成された値-を通知
Ac#on 
• RACCommandの置き換え 
• インプットからアウトプットを返すアクション(主にUI用:&メイ 
ンスレッドで動作)の実行・結果を提供する 
• 個別のアクション実行の結果はColdSignal<T>で返す 
• 結果のチェックは戻り値がColdSignalなのでsubscribeで
Ac#on.swi* 
public final class Action<Input, Output> { 
// RACCommand.executionSignals相当は現時点でなし 
public let executing: ColdSignal<Bool> // 実行中かどうか 
public let enabled: ColdSignal<Bool> // 有効かどうか 
public let values: HotSignal<Output> // 成功結果 
public let errors: HotSignal<NSError> // 失敗結果 
// アクションとなるクロージャを渡す 
public init(enabledIf: HotSignal<Bool>, 
execute: Input -> ColdSignal<Output>) 
public func execute(input: Input) -> ColdSignal<Output> // アクションの実行 
}
おまけ
Xcode&6.1,&iOS&7/8両対応で 
Swi$版のReac)veCocoaを組み込む 
方法を共有します。
1. git submodule add https://github.com/ 
ReactiveCocoa/ReactiveCocoa.git External/ 
ReactiveCocoa 
2. (LlamaKitの微修正……) 
3. LlamaKit.framework5/5Reac9veCocoa.framework5をビルドする 
4. ビルドしたFrameworkをリンクする 
5. Frameworkをアプリにコピーする 
6. importして使うだけ!!
https://github.com/ikesyo/rac_tokyo_rac3_installation_sample
まとめ
!!RAC!3.0はまだ早い……!!
Q&A?
ありがとうございました!

Contenu connexe

Tendances

Everyday Life with clojure.spec
Everyday Life with clojure.specEveryday Life with clojure.spec
Everyday Life with clojure.specKent Ohashi
 
Postgresql advent calender 2014 using jsonb by ecpg
Postgresql advent calender 2014 using jsonb by ecpgPostgresql advent calender 2014 using jsonb by ecpg
Postgresql advent calender 2014 using jsonb by ecpgToshi Harada
 
20130215 fluentd esper_2
20130215 fluentd esper_220130215 fluentd esper_2
20130215 fluentd esper_2Ogibayashi
 
Spectacular Future with clojure.spec
Spectacular Future with clojure.specSpectacular Future with clojure.spec
Spectacular Future with clojure.specKent Ohashi
 
これからのJavaScriptー関数型プログラミングとECMAScript6
これからのJavaScriptー関数型プログラミングとECMAScript6これからのJavaScriptー関数型プログラミングとECMAScript6
これからのJavaScriptー関数型プログラミングとECMAScript6TanUkkii
 
初級者向けレッスン 51回 ─── 例外
初級者向けレッスン 51回 ─── 例外初級者向けレッスン 51回 ─── 例外
初級者向けレッスン 51回 ─── 例外higaki
 
「Grails-1.1を斬る!〜Grails-1.1からのチーム開発〜」
「Grails-1.1を斬る!〜Grails-1.1からのチーム開発〜」「Grails-1.1を斬る!〜Grails-1.1からのチーム開発〜」
「Grails-1.1を斬る!〜Grails-1.1からのチーム開発〜」Tsuyoshi Yamamoto
 
Flow.js
Flow.jsFlow.js
Flow.jsuupaa
 
Kotlin勉強会 in ehime
Kotlin勉強会 in ehimeKotlin勉強会 in ehime
Kotlin勉強会 in ehimeEigoro Yamamura
 
OSSから学ぶSwift実践テクニック
OSSから学ぶSwift実践テクニックOSSから学ぶSwift実践テクニック
OSSから学ぶSwift実践テクニック庸介 高橋
 
はてなブックマーク in Scala
はてなブックマーク in Scalaはてなブックマーク in Scala
はてなブックマーク in ScalaLintaro Ina
 
CPANの依存モジュールをもう少し正しく検出したい
CPANの依存モジュールをもう少し正しく検出したいCPANの依存モジュールをもう少し正しく検出したい
CPANの依存モジュールをもう少し正しく検出したいcharsbar
 
ちょっと詳しくJavaScript 第2回【関数と引数】
ちょっと詳しくJavaScript 第2回【関数と引数】ちょっと詳しくJavaScript 第2回【関数と引数】
ちょっと詳しくJavaScript 第2回【関数と引数】株式会社ランチェスター
 
Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered archi...
Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered archi...Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered archi...
Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered archi...Shohei Okada
 
サイ本読書会4章変数
サイ本読書会4章変数サイ本読書会4章変数
サイ本読書会4章変数ztyper
 
Swift 2.0 の Error Handling #yhios
Swift 2.0 の Error Handling #yhiosSwift 2.0 の Error Handling #yhios
Swift 2.0 の Error Handling #yhiosTomohiro Kumagai
 

Tendances (20)

Everyday Life with clojure.spec
Everyday Life with clojure.specEveryday Life with clojure.spec
Everyday Life with clojure.spec
 
Postgresql advent calender 2014 using jsonb by ecpg
Postgresql advent calender 2014 using jsonb by ecpgPostgresql advent calender 2014 using jsonb by ecpg
Postgresql advent calender 2014 using jsonb by ecpg
 
20130215 fluentd esper_2
20130215 fluentd esper_220130215 fluentd esper_2
20130215 fluentd esper_2
 
Rx java x retrofit
Rx java x retrofitRx java x retrofit
Rx java x retrofit
 
Spectacular Future with clojure.spec
Spectacular Future with clojure.specSpectacular Future with clojure.spec
Spectacular Future with clojure.spec
 
これからのJavaScriptー関数型プログラミングとECMAScript6
これからのJavaScriptー関数型プログラミングとECMAScript6これからのJavaScriptー関数型プログラミングとECMAScript6
これからのJavaScriptー関数型プログラミングとECMAScript6
 
初級者向けレッスン 51回 ─── 例外
初級者向けレッスン 51回 ─── 例外初級者向けレッスン 51回 ─── 例外
初級者向けレッスン 51回 ─── 例外
 
「Grails-1.1を斬る!〜Grails-1.1からのチーム開発〜」
「Grails-1.1を斬る!〜Grails-1.1からのチーム開発〜」「Grails-1.1を斬る!〜Grails-1.1からのチーム開発〜」
「Grails-1.1を斬る!〜Grails-1.1からのチーム開発〜」
 
Flow.js
Flow.jsFlow.js
Flow.js
 
Kotlin勉強会 in ehime
Kotlin勉強会 in ehimeKotlin勉強会 in ehime
Kotlin勉強会 in ehime
 
OSSから学ぶSwift実践テクニック
OSSから学ぶSwift実践テクニックOSSから学ぶSwift実践テクニック
OSSから学ぶSwift実践テクニック
 
はてなブックマーク in Scala
はてなブックマーク in Scalaはてなブックマーク in Scala
はてなブックマーク in Scala
 
CPANの依存モジュールをもう少し正しく検出したい
CPANの依存モジュールをもう少し正しく検出したいCPANの依存モジュールをもう少し正しく検出したい
CPANの依存モジュールをもう少し正しく検出したい
 
ちょっと詳しくJavaScript 第2回【関数と引数】
ちょっと詳しくJavaScript 第2回【関数と引数】ちょっと詳しくJavaScript 第2回【関数と引数】
ちょっと詳しくJavaScript 第2回【関数と引数】
 
Rubyize
RubyizeRubyize
Rubyize
 
Jsonp
JsonpJsonp
Jsonp
 
Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered archi...
Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered archi...Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered archi...
Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered archi...
 
20140929 ecmascript
20140929 ecmascript20140929 ecmascript
20140929 ecmascript
 
サイ本読書会4章変数
サイ本読書会4章変数サイ本読書会4章変数
サイ本読書会4章変数
 
Swift 2.0 の Error Handling #yhios
Swift 2.0 の Error Handling #yhiosSwift 2.0 の Error Handling #yhios
Swift 2.0 の Error Handling #yhios
 

En vedette

エンジニア戦記 〜小さなチーム、大きな未来〜
エンジニア戦記 〜小さなチーム、大きな未来〜エンジニア戦記 〜小さなチーム、大きな未来〜
エンジニア戦記 〜小さなチーム、大きな未来〜Yuki Hirai
 
Swift 1.2からSwift 2への移行 #cocoa_kansai
Swift 1.2からSwift 2への移行 #cocoa_kansaiSwift 1.2からSwift 2への移行 #cocoa_kansai
Swift 1.2からSwift 2への移行 #cocoa_kansaiSyo Ikeda
 
Xcode and iTC submission topics
Xcode and iTC submission topicsXcode and iTC submission topics
Xcode and iTC submission topicsSyo Ikeda
 
Dynamic frameworks tips
Dynamic frameworks tipsDynamic frameworks tips
Dynamic frameworks tipsSyo Ikeda
 
Audio QueueでSin波再生
Audio QueueでSin波再生Audio QueueでSin波再生
Audio QueueでSin波再生Yuichi Fujishige
 
iOS 通信のパフォーマンス改善 ・ iOSオールスターズ登壇資料
iOS 通信のパフォーマンス改善 ・ iOSオールスターズ登壇資料iOS 通信のパフォーマンス改善 ・ iOSオールスターズ登壇資料
iOS 通信のパフォーマンス改善 ・ iOSオールスターズ登壇資料yohei sugigami
 
効率的なアプリ開発のベストプラクティス
効率的なアプリ開発のベストプラクティス効率的なアプリ開発のベストプラクティス
効率的なアプリ開発のベストプラクティスyayugu
 
let UIWebView as WKWebView
let UIWebView as WKWebViewlet UIWebView as WKWebView
let UIWebView as WKWebViewTaketo Sano
 
How to handle bitcode
How to handle bitcodeHow to handle bitcode
How to handle bitcodeSyo Ikeda
 
Himotoki: A type-safe JSON decoding library #関モバ
Himotoki: A type-safe JSON decoding library #関モバHimotoki: A type-safe JSON decoding library #関モバ
Himotoki: A type-safe JSON decoding library #関モバSyo Ikeda
 
ObjectMapperでJSONマッピング
ObjectMapperでJSONマッピングObjectMapperでJSONマッピング
ObjectMapperでJSONマッピングSyo Ikeda
 
1画面から始めるStoryboard
1画面から始めるStoryboard1画面から始めるStoryboard
1画面から始めるStoryboardYuichi Fujishige
 
SwiftでAndroidアプリ書けるってよ
SwiftでAndroidアプリ書けるってよSwiftでAndroidアプリ書けるってよ
SwiftでAndroidアプリ書けるってよSyo Ikeda
 
iOSでのFramework導入のおさらい #関モバ
iOSでのFramework導入のおさらい #関モバiOSでのFramework導入のおさらい #関モバ
iOSでのFramework導入のおさらい #関モバSyo Ikeda
 
インフラで実践したチームビルディングそれはサバ天
インフラで実践したチームビルディングそれはサバ天インフラで実践したチームビルディングそれはサバ天
インフラで実践したチームビルディングそれはサバ天ume3_
 

En vedette (20)

エンジニア戦記 〜小さなチーム、大きな未来〜
エンジニア戦記 〜小さなチーム、大きな未来〜エンジニア戦記 〜小さなチーム、大きな未来〜
エンジニア戦記 〜小さなチーム、大きな未来〜
 
Swift 1.2からSwift 2への移行 #cocoa_kansai
Swift 1.2からSwift 2への移行 #cocoa_kansaiSwift 1.2からSwift 2への移行 #cocoa_kansai
Swift 1.2からSwift 2への移行 #cocoa_kansai
 
Xcode and iTC submission topics
Xcode and iTC submission topicsXcode and iTC submission topics
Xcode and iTC submission topics
 
Dynamic frameworks tips
Dynamic frameworks tipsDynamic frameworks tips
Dynamic frameworks tips
 
Auto Layout の小技
Auto Layout の小技Auto Layout の小技
Auto Layout の小技
 
iOS 6 のAuto Rotation
iOS 6 のAuto RotationiOS 6 のAuto Rotation
iOS 6 のAuto Rotation
 
SwiftLint
SwiftLintSwiftLint
SwiftLint
 
Audio QueueでSin波再生
Audio QueueでSin波再生Audio QueueでSin波再生
Audio QueueでSin波再生
 
CAKeyframeAnimation
CAKeyframeAnimationCAKeyframeAnimation
CAKeyframeAnimation
 
iOSのFileProtection
iOSのFileProtectioniOSのFileProtection
iOSのFileProtection
 
iOS 通信のパフォーマンス改善 ・ iOSオールスターズ登壇資料
iOS 通信のパフォーマンス改善 ・ iOSオールスターズ登壇資料iOS 通信のパフォーマンス改善 ・ iOSオールスターズ登壇資料
iOS 通信のパフォーマンス改善 ・ iOSオールスターズ登壇資料
 
効率的なアプリ開発のベストプラクティス
効率的なアプリ開発のベストプラクティス効率的なアプリ開発のベストプラクティス
効率的なアプリ開発のベストプラクティス
 
let UIWebView as WKWebView
let UIWebView as WKWebViewlet UIWebView as WKWebView
let UIWebView as WKWebView
 
How to handle bitcode
How to handle bitcodeHow to handle bitcode
How to handle bitcode
 
Himotoki: A type-safe JSON decoding library #関モバ
Himotoki: A type-safe JSON decoding library #関モバHimotoki: A type-safe JSON decoding library #関モバ
Himotoki: A type-safe JSON decoding library #関モバ
 
ObjectMapperでJSONマッピング
ObjectMapperでJSONマッピングObjectMapperでJSONマッピング
ObjectMapperでJSONマッピング
 
1画面から始めるStoryboard
1画面から始めるStoryboard1画面から始めるStoryboard
1画面から始めるStoryboard
 
SwiftでAndroidアプリ書けるってよ
SwiftでAndroidアプリ書けるってよSwiftでAndroidアプリ書けるってよ
SwiftでAndroidアプリ書けるってよ
 
iOSでのFramework導入のおさらい #関モバ
iOSでのFramework導入のおさらい #関モバiOSでのFramework導入のおさらい #関モバ
iOSでのFramework導入のおさらい #関モバ
 
インフラで実践したチームビルディングそれはサバ天
インフラで実践したチームビルディングそれはサバ天インフラで実践したチームビルディングそれはサバ天
インフラで実践したチームビルディングそれはサバ天
 

Similaire à var RAC3 = ReactiveCocoa + Swift @ ReactiveCocoa Tokyo #rac_tokyo 10/18

サーバー実装いろいろ
サーバー実装いろいろサーバー実装いろいろ
サーバー実装いろいろkjwtnb
 
みんな大好き! Hello, World
みんな大好き! Hello, Worldみんな大好き! Hello, World
みんな大好き! Hello, WorldNaohiro Aota
 
Composable Callbacks & Listeners
Composable Callbacks & ListenersComposable Callbacks & Listeners
Composable Callbacks & ListenersTaisuke Oe
 
ServiceMesh と仲間たち 〜Istio & Conduit & Linkerd〜 @Cloud Native Meetup Tokyo #1
ServiceMesh と仲間たち 〜Istio & Conduit & Linkerd〜 @Cloud Native Meetup Tokyo #1ServiceMesh と仲間たち 〜Istio & Conduit & Linkerd〜 @Cloud Native Meetup Tokyo #1
ServiceMesh と仲間たち 〜Istio & Conduit & Linkerd〜 @Cloud Native Meetup Tokyo #1Masaya Aoyama
 
Scripting Layer for Android + Perl
Scripting Layer for Android + PerlScripting Layer for Android + Perl
Scripting Layer for Android + PerlNaoya Ito
 
Web技術勉強会23回目
Web技術勉強会23回目Web技術勉強会23回目
Web技術勉強会23回目龍一 田中
 
CloudWatch Logsについて
CloudWatch LogsについてCloudWatch Logsについて
CloudWatch LogsについてSugawara Genki
 
Kubernete Meetup Tokyo #18 - Kubebuilder/controller-runtime 入門
Kubernete Meetup Tokyo #18 - Kubebuilder/controller-runtime 入門Kubernete Meetup Tokyo #18 - Kubebuilder/controller-runtime 入門
Kubernete Meetup Tokyo #18 - Kubebuilder/controller-runtime 入門Preferred Networks
 
Apacheの展望とmod_perlの超絶技巧 #yapcasia
Apacheの展望とmod_perlの超絶技巧 #yapcasiaApacheの展望とmod_perlの超絶技巧 #yapcasia
Apacheの展望とmod_perlの超絶技巧 #yapcasia鉄次 尾形
 
Leap Motion - 1st Review
Leap Motion - 1st ReviewLeap Motion - 1st Review
Leap Motion - 1st ReviewTsukasa Sugiura
 
Quarkus による超音速な Spring アプリケーション開発
Quarkus による超音速な Spring アプリケーション開発Quarkus による超音速な Spring アプリケーション開発
Quarkus による超音速な Spring アプリケーション開発Chihiro Ito
 
Serf / Consul 入門 ~仕事を楽しくしよう~
Serf / Consul 入門 ~仕事を楽しくしよう~Serf / Consul 入門 ~仕事を楽しくしよう~
Serf / Consul 入門 ~仕事を楽しくしよう~Masahito Zembutsu
 
Okinawa.rb 第2回勉強会
Okinawa.rb 第2回勉強会Okinawa.rb 第2回勉強会
Okinawa.rb 第2回勉強会Naoki Takaesu
 
GitHub Actions + Cloudflare API
GitHub Actions + Cloudflare APIGitHub Actions + Cloudflare API
GitHub Actions + Cloudflare APITakahiro Kudo
 
20200528_AWSでサーバーレスなLINEBotLIFFアプリ環境をIaCな感じで構築するよ!.pdf
20200528_AWSでサーバーレスなLINEBotLIFFアプリ環境をIaCな感じで構築するよ!.pdf20200528_AWSでサーバーレスなLINEBotLIFFアプリ環境をIaCな感じで構築するよ!.pdf
20200528_AWSでサーバーレスなLINEBotLIFFアプリ環境をIaCな感じで構築するよ!.pdfSumihiro Kagawa
 
How Smalltalker Works
How Smalltalker WorksHow Smalltalker Works
How Smalltalker WorksSho Yoshida
 
Continuation with Boost.Context
Continuation with Boost.ContextContinuation with Boost.Context
Continuation with Boost.ContextAkira Takahashi
 

Similaire à var RAC3 = ReactiveCocoa + Swift @ ReactiveCocoa Tokyo #rac_tokyo 10/18 (20)

サーバー実装いろいろ
サーバー実装いろいろサーバー実装いろいろ
サーバー実装いろいろ
 
VerilatorとSystemC
VerilatorとSystemCVerilatorとSystemC
VerilatorとSystemC
 
みんな大好き! Hello, World
みんな大好き! Hello, Worldみんな大好き! Hello, World
みんな大好き! Hello, World
 
Composable Callbacks & Listeners
Composable Callbacks & ListenersComposable Callbacks & Listeners
Composable Callbacks & Listeners
 
ServiceMesh と仲間たち 〜Istio & Conduit & Linkerd〜 @Cloud Native Meetup Tokyo #1
ServiceMesh と仲間たち 〜Istio & Conduit & Linkerd〜 @Cloud Native Meetup Tokyo #1ServiceMesh と仲間たち 〜Istio & Conduit & Linkerd〜 @Cloud Native Meetup Tokyo #1
ServiceMesh と仲間たち 〜Istio & Conduit & Linkerd〜 @Cloud Native Meetup Tokyo #1
 
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
 
Scripting Layer for Android + Perl
Scripting Layer for Android + PerlScripting Layer for Android + Perl
Scripting Layer for Android + Perl
 
Web技術勉強会23回目
Web技術勉強会23回目Web技術勉強会23回目
Web技術勉強会23回目
 
CloudWatch Logsについて
CloudWatch LogsについてCloudWatch Logsについて
CloudWatch Logsについて
 
Tottoruby 20110903
Tottoruby 20110903Tottoruby 20110903
Tottoruby 20110903
 
Kubernete Meetup Tokyo #18 - Kubebuilder/controller-runtime 入門
Kubernete Meetup Tokyo #18 - Kubebuilder/controller-runtime 入門Kubernete Meetup Tokyo #18 - Kubebuilder/controller-runtime 入門
Kubernete Meetup Tokyo #18 - Kubebuilder/controller-runtime 入門
 
Apacheの展望とmod_perlの超絶技巧 #yapcasia
Apacheの展望とmod_perlの超絶技巧 #yapcasiaApacheの展望とmod_perlの超絶技巧 #yapcasia
Apacheの展望とmod_perlの超絶技巧 #yapcasia
 
Leap Motion - 1st Review
Leap Motion - 1st ReviewLeap Motion - 1st Review
Leap Motion - 1st Review
 
Quarkus による超音速な Spring アプリケーション開発
Quarkus による超音速な Spring アプリケーション開発Quarkus による超音速な Spring アプリケーション開発
Quarkus による超音速な Spring アプリケーション開発
 
Serf / Consul 入門 ~仕事を楽しくしよう~
Serf / Consul 入門 ~仕事を楽しくしよう~Serf / Consul 入門 ~仕事を楽しくしよう~
Serf / Consul 入門 ~仕事を楽しくしよう~
 
Okinawa.rb 第2回勉強会
Okinawa.rb 第2回勉強会Okinawa.rb 第2回勉強会
Okinawa.rb 第2回勉強会
 
GitHub Actions + Cloudflare API
GitHub Actions + Cloudflare APIGitHub Actions + Cloudflare API
GitHub Actions + Cloudflare API
 
20200528_AWSでサーバーレスなLINEBotLIFFアプリ環境をIaCな感じで構築するよ!.pdf
20200528_AWSでサーバーレスなLINEBotLIFFアプリ環境をIaCな感じで構築するよ!.pdf20200528_AWSでサーバーレスなLINEBotLIFFアプリ環境をIaCな感じで構築するよ!.pdf
20200528_AWSでサーバーレスなLINEBotLIFFアプリ環境をIaCな感じで構築するよ!.pdf
 
How Smalltalker Works
How Smalltalker WorksHow Smalltalker Works
How Smalltalker Works
 
Continuation with Boost.Context
Continuation with Boost.ContextContinuation with Boost.Context
Continuation with Boost.Context
 

var RAC3 = ReactiveCocoa + Swift @ ReactiveCocoa Tokyo #rac_tokyo 10/18

  • 1. var$RAC3$=$Reac,veCocoa$+$Swi2 @ikesyo #rac_tokyo Reac%veCocoa)Tokyo)2014110118)Sat)@freee株式会社
  • 2. @ikesyo いけしょー/池田翔 京都でフリーランスのiOS/Android エンジニアしています 甘いもの大好き!! !!お仕事待ってます!!! 現在フリュー㈱にて 一部RAC3を使ってお仕事中!
  • 5. ※!注意 2014%10%16,(Xcode(6.1(GM(seed(2時点,( swi4%api%reduxブランチ(#1532)の内容に基づきます APIやクラス名など今後変更される可能性は大いにあります ※!実際に7/26の!#rac_kansai!から大きく変わっています……!※
  • 8.
  • 10. だけではなく RACDC%2014:%June%3rd@Github • The$Future$Of$Reac.veCocoa$by$Jus.n$Spahr9Summers$•$ GitHub$Reac.ve$Cocoa$Developer$Conference • h#p://vimeo.com/98100163 • h#ps://github.com/jspahrsummers/the<future<of< reac>vecocoa
  • 13. New$Concepts • Generics)Support • ColdSignal)!)Producer)! • Subscriber)!)Consumer)! • HotSignal)!)Signal)! • ObservableProperty)!)SignalingProperty)! • !)Promise)! • Action
  • 14. Generics(Support 型パラメータは当然サポート public struct ColdSignal<T> {} public final class Subscriber<T>: SinkType {} extension NSNotificationCenter { public func rac_notifications (name: String? = nil, object: AnyObject? = nil) -> HotSignal<NSNotification> } extension NSURLSession { public func rac_dataWithRequest (request: NSURLRequest) -> ColdSignal<(NSData, NSURLResponse)> }
  • 15. ColdSignal • Cold&RACSignal:&Event&Stream • Subscriberをアタッチしてイベントを購読する • Subscriber毎に受け取るイベントやタイミングは異なる • SubscriberがDisposableを持っていて、ColdSignal生成 時のクロージャではDisposableを返さない • subscriber.disposable.addDisposable(...)
  • 16. ColdSignal.swi-public struct ColdSignal<T> { public init(generator: Subscriber<T> -> ()) // +[RACSignal createSignal:] public static func empty() -> ColdSignal // +[RACSignal empty] public static func single(value: T) -> ColdSignal // +[RACSignal return:] public static func error(error: NSError) -> ColdSignal // +[RACSignal error:] public static func never() -> ColdSignal // +[RACSignal never] // -[RACSignal subscribe:] public func subscribe(subscriber: Subscriber<T>) -> Disposable // -[RACSignal subscribeNext:error:completed:] public func subscribe( next: T -> () = doNothing, error: NSError -> () = doNothing, completed: () -> () = doNothing ) -> Disposable }
  • 17. ColdSignalの生成例 extension RACSignal { public func asColdSignal() -> ColdSignal<AnyObject?> { return ColdSignal { subscriber in let next = { (obj: AnyObject?) -> () in subscriber.put(.Next(Box(obj))) } let error = { (maybeError: NSError?) -> () in let nsError = maybeError.orDefault(RACError.Empty.error) subscriber.put(.Error(nsError)) } let completed = { subscriber.put(.Completed) } let disposable: RACDisposable? = self.subscribeNext(next, error: error, completed: completed) subscriber.disposable.addDisposable(disposable) } } }
  • 18. Subscriber • like:'id<RACSubscriber> subscriber • SinkTypeプロトコルのputにEvent<T>でラップした値を渡す • public func put(event: Event<T>) {} • 従来の'-sendNext:'などの代わり • Event<T> -> ()'のクロージャをハンドラー本体として Subscriberを初期化し、ColdSignalのsubscribeに渡せる
  • 19. Subscriber.swi+ public final class Subscriber<T>: SinkType { public typealias Element = Event<T> public let disposable = CompositeDisposable() public init<S: SinkType where S.Element == Event<T>>(_ sink: S) public convenience init(handler: Event<T> -> ()) public convenience init( next: T -> (), error: NSError -> (), completed: () -> ()) public func put(event: Event<T>) }
  • 20. Subscriberの使用例 extension ColdSignal { public func asDeferredRACSignal<U: AnyObject> (evidence: ColdSignal -> ColdSignal<U?>) -> RACSignal { return RACSignal.createSignal { subscriber in let selfDisposable = evidence(self).subscribe(next: { value in subscriber.sendNext(value) }, error: { error in subscriber.sendError(error) }, completed: { subscriber.sendCompleted() }) return RACDisposable { selfDisposable.dispose() } } } }
  • 21. 補足1 • evidenceという型チェックにより、特定の型パラメータを持 つColdSignalでのみメソッドを呼べるように制限 • Objec've)CとのブリッジなのでStructやEnumは渡せず、 AnyObjectでクラスオブジェクトだけに制限 • 使い方:,引数に,identityという関数を渡すだけ
  • 22. Iden%ty.swi, /// The identity function, which returns its argument. /// /// This can be used to prove to the typechecker that a given type A is /// equivalent to a given type B. /// /// For example, the following global function is normally impossible to bring /// into the `Signal<T>` class: /// /// func merge<U>(signal: Signal<Signal<U>>) -> Signal<U> /// /// However, you can work around this restriction using an instance method with /// an “evidence” parameter: /// /// func merge<U>(evidence: Signal<T> -> Signal<Signal<U>>) -> Signal<U> /// /// Which would then be invoked with the identity function, like this: /// /// signal.merge(identity) /// /// This will verify that `signal`, which is nominally `Signal<T>`, is logically /// equivalent to `Signal<Signal<U>>`. If that's not actually the case, a type /// error will result. public func identity<T>(id: T) -> T { return id }
  • 23. 補足2 • 例えばScalaではGeneralized-Type-Constraintsという言語機能で 同様の制限が可能 • h6p://yuroyoro.hatenablog.com/entry/ 20100914/1284471301 • h6p://www.ne.jp/asahi/hishidama/home/tech/scala/ generics.html#hgeneralizedtype_constraints
  • 24. HotSignal • Hot%RACSignal:%Push+driven%stream • CompletedやErrorによる終了はない • T -> ()%のクロージャがオブサーバー%SinkOf<T>%となって observeする • ColdSignalのSubscriberと異なり、全てのオブザーバー が同じイベントを同じタイミングで受け取る
  • 25. HotSignal.swi-public final class HotSignal<T> { public init(_ generator: SinkOf<T> -> ()) public class func never() -> HotSignal public func observe<S: SinkType where S.Element == T> (observer: S) -> Disposable public func observe(next: T -> ()) -> Disposable }
  • 26. HotSignalの生成例 extension NSNotificationCenter { public func rac_notifications (name: String? = nil, object: AnyObject? = nil) -> HotSignal<NSNotification> { let disposable = ScopedDisposable(SerialDisposable()) return HotSignal { sink in let observer = self.addObserverForName(name, object: object, queue: nil) { notification in sink.put(notification) } disposable.innerDisposable.innerDisposable = ActionDisposable { self.removeObserver(observer) } return () } } }
  • 27. HotSignal/Observer(SinkOf<T>)の使用例 extension HotSignal { /// Creates a RACSignal that will forward values from the receiver. /// /// evidence - Used to prove to the typechecker that the receiver is /// a signal of objects. Simply pass in the `identity` function. /// /// Returns an infinite signal that will forward all values from the /// underlying HotSignal. The returned RACSignal will never complete or /// error, so it must be disposed manually. public func asInfiniteRACSignal<U: AnyObject> (evidence: HotSignal -> HotSignal<U?>) -> RACSignal { return RACSignal.createSignal { subscriber in evidence(self).observe { subscriber.sendNext($0) } return nil } } }
  • 28. ObservableProperty • 値の変更をColdSignalとして通知することができるプロパテ ィ用オブジェクト • KVOの代替手段:&Swi*のクラスにはKVOがなく、監視される側 が自分から通知できるように公開するため? • !&func __conversion()&によりラップされた値を透過的に 使用することができる&!&Swi*&1.0でなくなりました!
  • 29. ObservableProperty.swi1 public final class ObservableProperty<T> { public func values() -> ColdSignal<T> // setするとvalues()の戻り値のColdSignalのsubscriberに通知される public var value: T // not public: ミス or 他からの変換? init(_ value: T) /** public func __conversion() -> T public func __conversion() -> Signal<T> */ } extension ObservableProperty: SinkType { public func put(value: T) }
  • 30. ObservablePropertyの使用例 public class Hoge { let name: ObservableProperty<String> = ObservableProperty("nanashi") } public func printName(name: String) { println(name) } let hoge = Hoge() printName(hoge.name.value) // => nanashi hoge.name.values().subscribe(next: { name in println("(name): name was changed!") }) // => nanashi: name was changed! : 最初に現在値が通知される hoge.name.value = "ikesyo" // or hoge.name.put("ikesyo") // by SinkType // => ikesyo: name was changed!
  • 31. !!Promise!! • 単一の値を生成(resolve)する遅延タスクを表現する • ProducerのようなEvent-Streamではないので複数の値を通知 したりはしない • 値は-public let signal: Signal<T?>-でSignalとして参 照できる • resolve前:-nil,-resolve後:-生成された値-を通知
  • 32. Ac#on • RACCommandの置き換え • インプットからアウトプットを返すアクション(主にUI用:&メイ ンスレッドで動作)の実行・結果を提供する • 個別のアクション実行の結果はColdSignal<T>で返す • 結果のチェックは戻り値がColdSignalなのでsubscribeで
  • 33. Ac#on.swi* public final class Action<Input, Output> { // RACCommand.executionSignals相当は現時点でなし public let executing: ColdSignal<Bool> // 実行中かどうか public let enabled: ColdSignal<Bool> // 有効かどうか public let values: HotSignal<Output> // 成功結果 public let errors: HotSignal<NSError> // 失敗結果 // アクションとなるクロージャを渡す public init(enabledIf: HotSignal<Bool>, execute: Input -> ColdSignal<Output>) public func execute(input: Input) -> ColdSignal<Output> // アクションの実行 }
  • 36. 1. git submodule add https://github.com/ ReactiveCocoa/ReactiveCocoa.git External/ ReactiveCocoa 2. (LlamaKitの微修正……) 3. LlamaKit.framework5/5Reac9veCocoa.framework5をビルドする 4. ビルドしたFrameworkをリンクする 5. Frameworkをアプリにコピーする 6. importして使うだけ!!
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 47. Q&A?