SlideShare a Scribd company logo
1 of 74
Download to read offline
#kaneshin
© 2014 Shintaro Kaneko
Guide for Swift
and Viewer App
Shintaro Kaneko
iOS/Android/Web Developer
Agenda
Guide for Swift
Viewer App
Guide for Swift
Guide for Swift
Variables & Constants
Printing
Optional
Switch
Tuple
Function
Protocol
Variables & Constants
Use `let` for constants and `var` for variables in Swift.
var str1 = "Hello" // Variable
str1 = "Test"
let str2 = "World" // Constant
str2 = "Test" // Compile error
var arr1: [Int] = [] // Mutable array
arr1.append(1)
let arr2: [Int] = [] // Immutable array
arr2.append(1) // Compile error
Printing
Use `println()` method. It s very similar to `NSLog()`.
Values of variables are expandable inside String using `()` like below.
let hello = "Hello"
let world = "世界"
println("(hello), (world)") // Hello, 世界
Optional
To indicate it might be `nil`.
Use `Optional<T>` to declare a variable, method as optional.
var str3: Optional<String> = nil
var str4: String? = nil // Syntax Sugar
Optional
`Optional<T>` is kind of `enum`.
enum Optional<T> : Reflectable, NilLiteralConvertible {
case None
case Some(T)
/// Construct a `nil` instance.
init()
/// Construct a non- `nil` instance that stores `some`.
init(_ some: T)
So, it is able to express them.
var str5: Optional<String> = Optional<String>() // nil
var str6: Optional<String> = Optional<String>("Hello") // {Some "Hello"}
Optional
Use `!` mark after an optional value to force the unwrapping of its value.
var str6: Optional<String> = Optional<String>("Hello")
var str7: String = str6 // Compile error
var str8: String = str6! // "Hello"
An optional value fails when the optional is `nil`
var str5: Optional<String> = Optional<String>()
var str9: String = str5! // Runtime error
Switch
The `Switch` statement is like other languages.
Different points in Swift
Not only Integers.
Coverage case, all possible values.
`break` statement is NOT required.
Use `fallthrough` to go through explicitly
Adding other conditional statement
Switch
let country: String = "Canada"
switch country {
case "USA":
println("USA")
case "Canada":
println("Canada")
case "Japan":
fallthrough
default:
println("Other")
}
Tuple
var p: (x: Float, y: Float) = (1.0, 2.0)
println("x: (p.0), y: (p.1)")
println("x: (p.x), y: (p.y)")
Tuple with Switch
var p: (x: Float, y: Float) = (1.0, 2.0)
println("x: (p.0), y: (p.1)")
println("x: (p.x), y: (p.y)")
switch p {
case (0, 0):
println("Point is on origin.")
case (_, 0):
println("Point is on X-axes.")
case (0, _):
println("Point is on Y-axes.")
case (-2...2, -2...2):
println("Point is inside the box")
default:
println("Point is outside the box")
}
Function
Use `func` keyword to declare.
func myPow(x: Int, e: Int) -> Int {
var d = 1
for _ in 1...e {
d *= x
}
return d
}
myPow(3, 4)
```
func [Name](arg1: Type1,..) -> [Return Type] {
// Procedure
}
```
Protocol
protocol AProtocol {
func behaviour() -> Void
}
@objc protocol SomeProtocol {
func behaviour() -> Void
optional func optBehaviour() -> Void
}
class Foo: NSObject, AProtocol {
func behaviour() {
}
}
Protocolの詳しくは
後ほど話します
Viewer App
Viewer App
InstagramのAPIを使った簡単なViewerアプリ開発
0. アプリモック
1. 開発準備
2. 実装
3. おわりに
0. アプリモック
Specification
テーブルビューにInstagramの情報を並べる
→InstagramAPI連携が必要
あるセルをタップすると、詳細のビューへ遷移する
→GoogleAnalyticsを使ってViewのトラッキングをしたい
1. 開発準備
Instagram APIについて
フレームワーク/ライブラリの導入
Instagram APIについて
Instagram APIについて
今回使用するエンドポイント
https://api.instagram.com/v1/media/popular?client_id=CLIENT-ID
CLIENT-IDの発行 => InstagramへClient登録
http://instagram.com/developer/clients/register/
※注: 1時間につき5000リクエスト
詳細:Instagram API Endpoints
http://instagram.com/developer/endpoints/
Instagram APIについて
今回使用するエンドポイント
https://api.instagram.com/v1/media/popular?client_id=CLIENT-ID
人気のメディア(写真/動画)データが返却される
画像についての情報取得は下記のように行える
responseJSON["data"][i]["images"]["standard_resolution"]
/* { "url": "http://s.cdninstagram.com/hphotos-xap1/a.jpg",
"width": 640,
"height": 640
} */
フレームワーク/ライブラリの導入
Alamofire
SwiftyJSON
GoogleAnalytics
フレームワークの導入
今回使用するフレームワーク
Alamofire (https://github.com/Alamofire/Alamofire)
ネットワーク通信を手軽にする
SwiftyJSON (https://github.com/SwiftyJSON/SwiftyJSON)
JSONデータを構造体で扱える
この2つをダウンロードかGit-Submoduleでプロジェクトフォルダへ
※今回、ライブラリ管理ツールは使用しません
プロジェクトへ追加
フレームワークのプロジェクトを
作成しているプロジェクトへ追加
ターゲットへ追加
ターゲットにフレームワークを追
加
→ターゲット選択
→General選択
→Embedded Binariesの「+」
→追加したいフレームワーク選択
最近のXcodeならここへ追加する
とBuild Phasesへ適切に設定される
フレームワークの導入
フレームワークの準備は完了
あとは使用するコードにimportするだけです
import Alamofire
import SwiftyJSON
ライブラリの導入
今回使用するライブラリ(Non-フレームワーク形式)
GoogleAnalytics
https://developers.google.com/analytics/devguides/collection/ios/
v3/
CocoaPodsを使って導入します
gemからcocoapodsをインストール(最新は0.35.0)
CocoaPods - Podfile
CocoaPodsの管理ファイル<Podfile>を作成する
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
inhibit_all_warnings!
xcodeproj 'InstagramViewer'
link_with 'InstagramViewer'
pod 'GoogleAnalytics-iOS-SDK', '3.0.9'
pod install -> xcworkspace
ターミナル上で`pod install`を行いライブラリを取得する
pod install
`pod install`後からはxcworkspaceファイルを開く
CocoaPods側でPodsプロジェクトが作成されるため
xcodeproj: プロジェクト単体を管理
xcworkspace: xcodeprojプロジェクトを複数管理
ブリッジングヘッダー
SwiftでObjective-Cクラスを使用するにはブリッジングが必要
ブリッジングヘッダーファイルを定義する
#ifndef InstagramViewer_Objective_C_Bridging_Header
#define InstagramViewer_Objective_C_Bridging_Header
#import <GoogleAnalytics-iOS-SDK/GAI.h>
#import <GoogleAnalytics-iOS-SDK/GAIFields.h>
#import <GoogleAnalytics-iOS-SDK/GAILogger.h>
#import <GoogleAnalytics-iOS-SDK/GAIDictionaryBuilder.h>
#endif /* InstagramViewer_Objective_C_Bridging_Header */
※参考:http://qiita.com/kaneshinth/items/71f1c19d094e87e30a07
ブリッジングヘッダー
2. 実装
実装パターン
Storyboard
Instagram API → データ → TableView
Google Analytics
実装パターン
実装パターン(一例)
├── InstagramViewer
│   ├── AppDelegate.swift
│   ├── Application
│   │   ├── Controllers // ViewController
│   │   │   ├── DetailViewController.swift
│   │   │   └── MediaListController.swift
│   │   ├── Models // Logic layer
│   │   │   └── MediaModel.swift
│   │   ├── Requests // API Request
│   │   │   └── MediaRequest.swift
│   │   ├── Utilities // Utility
│   │   │   └── AnalyticsUtils.swift
│   │   └── Views // View, Cell
│   │   └── MediaListCell.swift
│   └── Objective-C-Bridging-Header.h
実装パターン
実装パターン(グループ構成)
アプリケーションの規模
使用するデザインパターン
Observer Pattern, Reactive Pattern, MVVM, …
Storyboard
Main.storyboard
Initial View Controller
UINavigationController
ViewControllerをチェーンで管理
MediaListController
UITableViewController
Cellはデフォルトで使用する
CellにDetailViewControllerへの
Segueを設定している 
DetailViewController
UIViewController
UIImageViewを設置
Segue
Segueをフックしたい場合
Segue Identifier
Segueの遷移元、遷移先を設定す
るときに指定
Instagram API → データ
Instagram API → データ
データ取得の流れ
1. Alamofire.Requestクラスを使用してInstagram APIへリクエスト
→MediaRequestクラス
2. レスポンスのデータをSwiftJSON.JSON構造体へ
→MediaRequestクラス
3. Media構造体に必要な情報をJSON構造体から取得
→MediaModelクラス
Instagram APIとの連携
JSON
Media
Media
Media
Instagram APIApp
Swifty
JSON
Swifty
JSON
Alamofire
MediaRequestクラス
1. Alamofire.Requestクラスを使用してInstagram APIへリクエスト
→ requestメソッドが用意されているので、それを使用する
let urlString = "https://api.instagram.com/v1/media/popular"
let param = ["client_id": "<#CLIENT-ID#>"]
let req = request(.GET, urlString, parameters: param)
MediaRequestクラス
Instagram APIApp
JSON
Media
Media
Media
Swifty
JSON
Swifty
JSON
Alamofire
MediaRequestクラス
2. レスポンスのデータをSwiftJSON.JSON構造体へ
→ Requestの拡張にresponseメソッドがあるのでこれを使用する
let urlString = "https://api.instagram.com/v1/media/popular"
let param = ["client_id": "<#CLIENT-ID#>"]
let req = request(.GET, urlString, parameters: param)
req.response { (request, response, responseData, error) -> Void in
if error == nil {
if let data = responseData as? NSData {
let json = JSON(data: data)
// ……
}
}
}
SwiftyJSON.JSON
MediaModelクラス
Media
Media
Media
Swifty
JSON
Instagram APIApp
JSON
Swifty
JSON
Alamofire
MediaModelクラス
3. Media構造体に必要な情報をJSON構造体から取得
→ まず、Media構造体を作成
struct Caption {
var username: String?
var text: String?
}
struct Media {
var thumbnailURL: NSURL?
var imageURL: NSURL?
var caption: Caption?
}
MediaModelクラス
Media
Media
Media
Instagram APIApp
Swifty
JSON
JSON
Swifty
JSON
Alamofire
MediaRequestクラス
3. Media構造体に必要な情報をJSON構造体から取得
→ JSON構造体からMedia構造体へ
let json = JSON(data: data)
if let array = json["data"].array {
array.map({ (elm: JSON) -> Void in
var caption = Caption(
username: elm["caption"]["from"]["username"].string,
text: elm["caption"]["text"].string)
var media = Media(
thumbnailURL: elm["images"]["thumbnail"]["url"].URL,
imageURL: elm["images"]["standard_resolution"]["url"].URL,
caption: caption)
self.mediaList.append(media)
})
}
SwiftyJSONを
使わない場合
Instagramから情報を取得
req.responseJSON { (request, response, jsonData, error) -> Void in
if error == nil {
if let json = jsonData as? NSDictionary {
self.mediaList = []
if let array = json["data"] as? NSArray {
for d in array {
if let dict = d as? NSDictionary {
var caption = Caption(
username: ((dict["caption"] as? NSDictionary)?["from"] as?
NSDictionary)?["username"] as? NSString,
text: (dict["caption"] as? NSDictionary)?["text"] as NSString
)
var media = Media(
thumbnailURL: NSURL(string: ((dict["images"] as? NSDictionary)?
["thumbnail"] as? NSDictionary)?["url"] as NSString)!,
imageURL: NSURL(string: ((dict["images"] as? NSDictionary)?
["standard_resolution"] as? NSDictionary)?["url"] as NSString)!,
caption: caption
)
}}}}}}
Downcastを
多用する必要がある
(foo as? Type)
データ → UITableView
UITableView
UITableViewにて、テーブルを表示させる
UITableViewDataSource Protocol
テーブル表示の構成に必要なデータを取得する
UITableViewDelegate Protocol
テーブルのビューやアクションをフックする
UITableViewDataSourceとUITableViewDelegateを混在しないように
UITableViewDataSource
下記は必ず実装する必要がある
func tableView(tableView: UITableView,
numberOfRowsInSection section: Int) -> Int
func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
UITableViewDelegate
セルの高さ
セルの表示やタップ時の挙動
セルの編集挙動
セクションヘッダー/フッタービューの高さ
セクションヘッダー/フッタービューのビュー
MediaをUITableViewへ
Mediaを表示するには…
セルの数
→MediaListの中にあるmediaの数
セルの高さ(不変?可変?)
→可変ならばmediaから計算
セルの中身
→mediaから必要な情報を取得
今回のプロジェクトではInstagram APIから取得したデータはMediaModelが
内部で保持している
UITableView - セルの数
MediaModelが保持している配列の中身の数
override func tableView(tableView: UITableView,
numberOfRowsInSection section: Int) -> Int
{
return MediaModel.sharedInstance.mediaList.count
}
UITableView - セルの高さ
可変のときを考えて、MediaListCellクラスからセルの高さを取得する
override func tableView(tableView: UITableView,
heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
let media = MediaModel.sharedInstance.mediaList[indexPath.row]
return MediaListCell.heightForRow(media)
}
// ===
// MediaListCell.swift内部
class func heightForRow(media: Media) -> CGFloat {
return 100.0
}
UITableView - セルの中身
"疎"にするため、MediaListCellのインスタンスへmediaを渡す
override func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("Cell",
forIndexPath: indexPath) as MediaListCell
let media = MediaModel.sharedInstance.mediaList[indexPath.row]
return cell.configure(media)
}
MediaListCell - configure
画像データは非同期の別スレッドで取得する
取得完了したら、同期でメインスレッドに戻る
func configure(media: Media) -> MediaListCell {
self.textLabel?.text = media.caption?.text
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
let data = NSData(contentsOfURL: media.thumbnailURL!)
dispatch_sync(dispatch_get_main_queue(), {
self.imageView!.image = UIImage(data: data!,
scale: UIScreen.mainScreen().scale)
self.setNeedsLayout()
})
})
return self
}
Google Analytics
Google Analytics の初期化
初期化はGAIインスタンスから`GAITracker`を取得する
var tracker: GAITracker?
class func setupGoogleAnalytics() {
GAI.sharedInstance().trackUncaughtExceptions = true;
GAI.sharedInstance().dispatchInterval = 20
GAI.sharedInstance().logger.logLevel = .Verbose
AnalyticsUtils.sharedInstance.tracker =
GAI.sharedInstance().trackerWithTrackingId("UA-XXXXXXXX-X")
}
Google Analytics へ送信
GoogleAnalyticsへ情報を送信
`GAITracker`の`send`メソッド
class func trackView(screenName: String) {
if let tracker = AnalyticsUtils.sharedInstance.tracker {
let build = GAIDictionaryBuilder.createAppView()
.set(screenName, forKey: kGAIScreenName).build()
AnalyticsUtils.sharedInstance.tracker?.send(build)
}
}
ViewWillAppearでトラッキング
作った`trackView`メソッドを必要なときに使用する
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let screenName = reflect(self).summary
AnalyticsUtils.trackView(screenName)
}
おわりに
時間があれば
聞きたいことをライブコーディングします
- Delegateとか

More Related Content

What's hot

MTDDC Meetup Tokyo 2011:もっとディープにMovable Type
MTDDC Meetup Tokyo 2011:もっとディープにMovable TypeMTDDC Meetup Tokyo 2011:もっとディープにMovable Type
MTDDC Meetup Tokyo 2011:もっとディープにMovable TypeYujiro Araki
 
負荷テストことはじめ
負荷テストことはじめ負荷テストことはじめ
負荷テストことはじめKazumune Katagiri
 
Javaプログラミング入門【第3回】
Javaプログラミング入門【第3回】Javaプログラミング入門【第3回】
Javaプログラミング入門【第3回】Yukiko Kato
 
JavaのGenericsとは?
JavaのGenericsとは?JavaのGenericsとは?
JavaのGenericsとは?Kenji Nakamura
 
Active Directoryデータの Security Descriptor
Active Directoryデータの Security DescriptorActive Directoryデータの Security Descriptor
Active Directoryデータの Security DescriptorMichio Koyama
 

What's hot (8)

MTDDC Meetup Tokyo 2011:もっとディープにMovable Type
MTDDC Meetup Tokyo 2011:もっとディープにMovable TypeMTDDC Meetup Tokyo 2011:もっとディープにMovable Type
MTDDC Meetup Tokyo 2011:もっとディープにMovable Type
 
負荷テストことはじめ
負荷テストことはじめ負荷テストことはじめ
負荷テストことはじめ
 
Javaプログラミング入門【第3回】
Javaプログラミング入門【第3回】Javaプログラミング入門【第3回】
Javaプログラミング入門【第3回】
 
Ajax 応用
Ajax 応用Ajax 応用
Ajax 応用
 
OSC京都2011
OSC京都2011OSC京都2011
OSC京都2011
 
講座Java入門
講座Java入門講座Java入門
講座Java入門
 
JavaのGenericsとは?
JavaのGenericsとは?JavaのGenericsとは?
JavaのGenericsとは?
 
Active Directoryデータの Security Descriptor
Active Directoryデータの Security DescriptorActive Directoryデータの Security Descriptor
Active Directoryデータの Security Descriptor
 

Similar to Guide for Swift and Viewer app

Leap Motion - 1st Review
Leap Motion - 1st ReviewLeap Motion - 1st Review
Leap Motion - 1st ReviewTsukasa Sugiura
 
Synthesijer and Synthesijer.Scala in HLS-friends 201512
Synthesijer and Synthesijer.Scala in HLS-friends 201512Synthesijer and Synthesijer.Scala in HLS-friends 201512
Synthesijer and Synthesijer.Scala in HLS-friends 201512Takefumi MIYOSHI
 
2014年の社内新人教育テキスト #2(関数型言語からオブジェクト指向言語へ)
2014年の社内新人教育テキスト #2(関数型言語からオブジェクト指向言語へ)2014年の社内新人教育テキスト #2(関数型言語からオブジェクト指向言語へ)
2014年の社内新人教育テキスト #2(関数型言語からオブジェクト指向言語へ)Shin-ya Koga
 
Android Lecture #04 @PRO&BSC Inc.
Android Lecture #04 @PRO&BSC Inc.Android Lecture #04 @PRO&BSC Inc.
Android Lecture #04 @PRO&BSC Inc.Yuki Higuchi
 
Python standard 2022 Spring
Python standard 2022 SpringPython standard 2022 Spring
Python standard 2022 Springanyakichi
 
広告配信現場で使うSpark機械学習
広告配信現場で使うSpark機械学習広告配信現場で使うSpark機械学習
広告配信現場で使うSpark機械学習x1 ichi
 
Swift 2.0 で変わったところ「後編」 #cswift
Swift 2.0 で変わったところ「後編」 #cswiftSwift 2.0 で変わったところ「後編」 #cswift
Swift 2.0 で変わったところ「後編」 #cswiftTomohiro Kumagai
 
Android Lecture #03 @PRO&BSC Inc.
Android Lecture #03 @PRO&BSC Inc.Android Lecture #03 @PRO&BSC Inc.
Android Lecture #03 @PRO&BSC Inc.Yuki Higuchi
 
TypeScript 1.0 オーバービュー
TypeScript 1.0 オーバービューTypeScript 1.0 オーバービュー
TypeScript 1.0 オーバービューAkira Inoue
 
みんな大好き! Hello, World
みんな大好き! Hello, Worldみんな大好き! Hello, World
みんな大好き! Hello, WorldNaohiro Aota
 
From Swing to JavaFX - SwingからJavaFXへのマイグレーションガイド
From Swing to JavaFX  - SwingからJavaFXへのマイグレーションガイドFrom Swing to JavaFX  - SwingからJavaFXへのマイグレーションガイド
From Swing to JavaFX - SwingからJavaFXへのマイグレーションガイドYuichi Sakuraba
 
var RAC3 = ReactiveCocoa + Swift @ ReactiveCocoa Tokyo #rac_tokyo 10/18
var RAC3 = ReactiveCocoa + Swift @ ReactiveCocoa Tokyo #rac_tokyo 10/18var RAC3 = ReactiveCocoa + Swift @ ReactiveCocoa Tokyo #rac_tokyo 10/18
var RAC3 = ReactiveCocoa + Swift @ ReactiveCocoa Tokyo #rac_tokyo 10/18Syo Ikeda
 
速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-Kazunari Hara
 
Start FRP
Start FRPStart FRP
Start FRPrf0444
 
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesasm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesNoritada Shimizu
 

Similar to Guide for Swift and Viewer app (20)

R intro
R introR intro
R intro
 
Leap Motion - 1st Review
Leap Motion - 1st ReviewLeap Motion - 1st Review
Leap Motion - 1st Review
 
Synthesijer and Synthesijer.Scala in HLS-friends 201512
Synthesijer and Synthesijer.Scala in HLS-friends 201512Synthesijer and Synthesijer.Scala in HLS-friends 201512
Synthesijer and Synthesijer.Scala in HLS-friends 201512
 
2014年の社内新人教育テキスト #2(関数型言語からオブジェクト指向言語へ)
2014年の社内新人教育テキスト #2(関数型言語からオブジェクト指向言語へ)2014年の社内新人教育テキスト #2(関数型言語からオブジェクト指向言語へ)
2014年の社内新人教育テキスト #2(関数型言語からオブジェクト指向言語へ)
 
Android Lecture #04 @PRO&BSC Inc.
Android Lecture #04 @PRO&BSC Inc.Android Lecture #04 @PRO&BSC Inc.
Android Lecture #04 @PRO&BSC Inc.
 
Python standard 2022 Spring
Python standard 2022 SpringPython standard 2022 Spring
Python standard 2022 Spring
 
広告配信現場で使うSpark機械学習
広告配信現場で使うSpark機械学習広告配信現場で使うSpark機械学習
広告配信現場で使うSpark機械学習
 
Swift 2.0 で変わったところ「後編」 #cswift
Swift 2.0 で変わったところ「後編」 #cswiftSwift 2.0 で変わったところ「後編」 #cswift
Swift 2.0 で変わったところ「後編」 #cswift
 
Android Lecture #03 @PRO&BSC Inc.
Android Lecture #03 @PRO&BSC Inc.Android Lecture #03 @PRO&BSC Inc.
Android Lecture #03 @PRO&BSC Inc.
 
TypeScript 1.0 オーバービュー
TypeScript 1.0 オーバービューTypeScript 1.0 オーバービュー
TypeScript 1.0 オーバービュー
 
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
 
みんな大好き! Hello, World
みんな大好き! Hello, Worldみんな大好き! Hello, World
みんな大好き! Hello, World
 
From Swing to JavaFX - SwingからJavaFXへのマイグレーションガイド
From Swing to JavaFX  - SwingからJavaFXへのマイグレーションガイドFrom Swing to JavaFX  - SwingからJavaFXへのマイグレーションガイド
From Swing to JavaFX - SwingからJavaFXへのマイグレーションガイド
 
var RAC3 = ReactiveCocoa + Swift @ ReactiveCocoa Tokyo #rac_tokyo 10/18
var RAC3 = ReactiveCocoa + Swift @ ReactiveCocoa Tokyo #rac_tokyo 10/18var RAC3 = ReactiveCocoa + Swift @ ReactiveCocoa Tokyo #rac_tokyo 10/18
var RAC3 = ReactiveCocoa + Swift @ ReactiveCocoa Tokyo #rac_tokyo 10/18
 
速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-
 
Stream2の基本
Stream2の基本Stream2の基本
Stream2の基本
 
Scala on Hadoop
Scala on HadoopScala on Hadoop
Scala on Hadoop
 
Start FRP
Start FRPStart FRP
Start FRP
 
[xDNCL] 配布資料
[xDNCL] 配布資料[xDNCL] 配布資料
[xDNCL] 配布資料
 
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesasm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web games
 

Guide for Swift and Viewer app