Slide 1

Slide 1 text

LBOFTIJO ˜4IJOUBSP,BOFLP (VJEFGPS4XJGU BOE7JFXFS"QQ 4IJOUBSP,BOFLP J04"OESPJE8FC%FWFMPQFS

Slide 2

Slide 2 text

"HFOEB (VJEFGPS4XJGU 7JFXFS"QQ

Slide 3

Slide 3 text

(VJEFGPS4XJGU

Slide 4

Slide 4 text

(VJEFGPS4XJGU 7BSJBCMFT$POTUBOUT 1SJOUJOH 0QUJPOBM 4XJUDI 5VQMF 'VODUJPO 1SPUPDPM

Slide 5

Slide 5 text

7BSJBCMFT$POTUBOUT 6TFAMFUAGPSDPOTUBOUTBOEAWBSAGPSWBSJBCMFTJO4XJGU 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

Slide 6

Slide 6 text

1SJOUJOH 6TFAQSJOUMO ANFUIPE*U`TWFSZTJNJMBSUPA/4-PH A 7BMVFTPGWBSJBCMFTBSFFYQBOEBCMFJOTJEF4USJOHVTJOHAa AMJLFCFMPX let hello = "Hello" let world = "世界" println("\(hello), \(world)") // Hello, 世界

Slide 7

Slide 7 text

0QUJPOBM 5PJOEJDBUFJUNJHIUCFAOJMA 6TFA0QUJPOBM5AUPEFDMBSFBWBSJBCMF NFUIPEBTPQUJPOBM var str3: Optional = nil var str4: String? = nil // Syntax Sugar

Slide 8

Slide 8 text

0QUJPOBM A0QUJPOBM5AJTLJOEPGAFOVNA enum Optional : Reflectable, NilLiteralConvertible { case None case Some(T) /// Construct a `nil` instance. init() /// Construct a non-\ `nil` instance that stores `some`. init(_ some: T) 4P JUJTBCMFUPFYQSFTTUIFN var str5: Optional = Optional() // nil var str6: Optional = Optional("Hello") // {Some "Hello"}

Slide 9

Slide 9 text

0QUJPOBM 6TFAANBSLBGUFSBOPQUJPOBMWBMVFUPGPSDFUIFVOXSBQQJOHPGJUTWBMVF var str6: Optional = Optional("Hello") var str7: String = str6 // Compile error var str8: String = str6! // "Hello" "OPQUJPOBMWBMVFGBJMTXIFOUIFPQUJPOBMJTAOJMA var str5: Optional = Optional() var str9: String = str5! // Runtime error

Slide 10

Slide 10 text

4XJUDI 5IFA4XJUDIATUBUFNFOUJTMJLFPUIFSMBOHVBHFT %J⒎FSFOUQPJOUTJO4XJGU /PUPOMZ*OUFHFST $PWFSBHFDBTF BMMQPTTJCMFWBMVFT ACSFBLATUBUFNFOUJT/05SFRVJSFE 6TFAGBMMUISPVHIAUPHPUISPVHIFYQMJDJUMZ "EEJOHPUIFSDPOEJUJPOBMTUBUFNFOU

Slide 11

Slide 11 text

4XJUDI let country: String = "Canada" switch country { case "USA": println("USA") case "Canada": println("Canada") case "Japan": fallthrough default: println("Other") }

Slide 12

Slide 12 text

5VQMF var p: (x: Float, y: Float) = (1.0, 2.0) println("x: \(p.0), y: \(p.1)") println("x: \(p.x), y: \(p.y)")

Slide 13

Slide 13 text

5VQMFXJUI4XJUDI 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") }

Slide 14

Slide 14 text

'VODUJPO 6TFAGVODALFZXPSEUPEFDMBSF 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 } ```

Slide 15

Slide 15 text

1SPUPDPM protocol AProtocol { func behaviour() -> Void } @objc protocol SomeProtocol { func behaviour() -> Void optional func optBehaviour() -> Void } class Foo: NSObject, AProtocol { func behaviour() { } }

Slide 16

Slide 16 text

1SPUPDPMͷৄ͘͠͸ ޙ΄Ͳ࿩͠·͢

Slide 17

Slide 17 text

7JFXFS"QQ

Slide 18

Slide 18 text

7JFXFS"QQ *OTUBHSBNͷ"1*Λ࢖ͬͨ؆୯ͳ7JFXFSΞϓϦ։ൃ ΞϓϦϞοΫ ։ൃ४උ ࣮૷ ͓ΘΓʹ

Slide 19

Slide 19 text

ΞϓϦϞοΫ

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

4QFDJpDBUJPO ςʔϒϧϏϡʔʹ*OTUBHSBNͷ৘ใΛฒ΂Δ ˠ*OTUBHSBN"1*࿈ܞ͕ඞཁ ͋ΔηϧΛλοϓ͢ΔͱɺৄࡉͷϏϡʔ΁ભҠ͢Δ ˠ(PPHMF"OBMZUJDTΛ࢖ͬͯ7JFXͷτϥοΩϯάΛ͍ͨ͠

Slide 22

Slide 22 text

։ൃ४උ *OTUBHSBN"1*ʹ͍ͭͯ ϑϨʔϜϫʔΫϥΠϒϥϦͷಋೖ

Slide 23

Slide 23 text

*OTUBHSBN"1*ʹ͍ͭͯ

Slide 24

Slide 24 text

*OTUBHSBN"1*ʹ͍ͭͯ ࠓճ࢖༻͢ΔΤϯυϙΠϯτ IUUQTBQJJOTUBHSBNDPNWNFEJBQPQVMBS DMJFOU@JE$-*&/5*% $-*&/5*%ͷൃߦ*OTUBHSBN΁$MJFOUొ࿥ IUUQJOTUBHSBNDPNEFWFMPQFSDMJFOUTSFHJTUFS ˞஫࣌ؒʹ͖ͭϦΫΤετ ৄࡉɿ*OTUBHSBN"1*&OEQPJOUT IUUQJOTUBHSBNDPNEFWFMPQFSFOEQPJOUT

Slide 25

Slide 25 text

*OTUBHSBN"1*ʹ͍ͭͯ ࠓճ࢖༻͢ΔΤϯυϙΠϯτ IUUQTBQJJOTUBHSBNDPNWNFEJBQPQVMBS DMJFOU@JE$-*&/5*% ਓؾͷϝσΟΞʢࣸਅಈըʣσʔλ͕ฦ٫͞ΕΔ ը૾ʹ͍ͭͯͷ৘ใऔಘ͸ԼهͷΑ͏ʹߦ͑Δ responseJSON["data"][i]["images"]["standard_resolution"] /* { "url": "http://s.cdninstagram.com/hphotos-xap1/a.jpg", "width": 640, "height": 640 } */

Slide 26

Slide 26 text

ϑϨʔϜϫʔΫϥΠϒϥϦͷಋೖ "MBNPpSF 4XJGUZ+40/ (PPHMF"OBMZUJDT

Slide 27

Slide 27 text

ϑϨʔϜϫʔΫͷಋೖ ࠓճ࢖༻͢ΔϑϨʔϜϫʔΫ "MBNPpSF IUUQTHJUIVCDPN"MBNPpSF"MBNPpSF ωοτϫʔΫ௨৴Λखܰʹ͢Δ 4XJGUZ+40/ IUUQTHJUIVCDPN4XJGUZ+40/4XJGUZ+40/ +40/σʔλΛߏ଄ମͰѻ͑Δ ͜ͷ̎ͭΛμ΢ϯϩʔυ͔(JU4VCNPEVMFͰϓϩδΣΫτϑΥϧμ΁ ˞ࠓճɺϥΠϒϥϦ؅ཧπʔϧ͸࢖༻͠·ͤΜ

Slide 28

Slide 28 text

ϓϩδΣΫτ΁௥Ճ ϑϨʔϜϫʔΫͷϓϩδΣΫτΛ ࡞੒͍ͯ͠ΔϓϩδΣΫτ΁௥Ճ

Slide 29

Slide 29 text

λʔήοτ΁௥Ճ λʔήοτʹϑϨʔϜϫʔΫΛ௥ Ճ ˠλʔήοτબ୒ ˠ(FOFSBMબ୒ ˠ&NCFEEFE#JOBSJFTͷʮʴʯ ˠ௥Ճ͍ͨ͠ϑϨʔϜϫʔΫબ୒ ࠷ۙͷ9DPEFͳΒ͜͜΁௥Ճ͢Δ ͱ#VJME1IBTFT΁ద੾ʹઃఆ͞ΕΔ

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

ϑϨʔϜϫʔΫͷಋೖ ϑϨʔϜϫʔΫͷ४උ͸׬ྃ ͋ͱ͸࢖༻͢ΔίʔυʹJNQPSU͢Δ͚ͩͰ͢ JNQPSU"MBNPpSF JNQPSU4XJGUZ+40/

Slide 32

Slide 32 text

ϥΠϒϥϦͷಋೖ ࠓճ࢖༻͢ΔϥΠϒϥϦʢ/POϑϨʔϜϫʔΫܗࣜʣ (PPHMF"OBMZUJDT IUUQTEFWFMPQFSTHPPHMFDPNBOBMZUJDTEFWHVJEFTDPMMFDUJPOJPT W $PDPB1PETΛ࢖ͬͯಋೖ͠·͢ HFN͔ΒDPDPBQPETΛΠϯετʔϧʢ࠷৽͸ʣ

Slide 33

Slide 33 text

$PDPB1PET1PEpMF $PDPB1PETͷ؅ཧϑΝΠϧ1PEpMFΛ࡞੒͢Δ 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'

Slide 34

Slide 34 text

QPEJOTUBMMYDXPSLTQBDF λʔϛφϧ্ͰAQPEJOTUBMMAΛߦ͍ϥΠϒϥϦΛऔಘ͢Δ pod install AQPEJOTUBMMAޙ͔Β͸YDXPSLTQBDFϑΝΠϧΛ։͘ $PDPB1PETଆͰ1PETϓϩδΣΫτ͕࡞੒͞ΕΔͨΊa YDPEFQSPKϓϩδΣΫτ୯ମΛ؅ཧ YDXPSLTQBDFYDPEFQSPKϓϩδΣΫτΛෳ਺؅ཧ

Slide 35

Slide 35 text

ϒϦοδϯάϔομʔ 4XJGUͰ0CKFDUJWF$ΫϥεΛ࢖༻͢Δʹ͸ϒϦοδϯά͕ඞཁ ϒϦοδϯάϔομʔϑΝΠϧΛఆٛ͢Δ #ifndef InstagramViewer_Objective_C_Bridging_Header #define InstagramViewer_Objective_C_Bridging_Header #import #import #import #import #endif /* InstagramViewer_Objective_C_Bridging_Header */ ˞ࢀߟɿIUUQRJJUBDPNLBOFTIJOUIJUFNTGDEFFB

Slide 36

Slide 36 text

ϒϦοδϯάϔομʔ

Slide 37

Slide 37 text

࣮૷ ࣮૷ύλʔϯ 4UPSZCPBSE *OTUBHSBN"1*ˠσʔλˠ5BCMF7JFX (PPHMF"OBMZUJDT

Slide 38

Slide 38 text

࣮૷ύλʔϯ

Slide 39

Slide 39 text

࣮૷ύλʔϯʢҰྫʣ ├── 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

Slide 40

Slide 40 text

࣮૷ύλʔϯ ࣮૷ύλʔϯʢάϧʔϓߏ੒ʣ ΞϓϦέʔγϣϯͷن໛ ࢖༻͢ΔσβΠϯύλʔϯ 0CTFSWFS1BUUFSO 3FBDUJWF1BUUFSO .77. ʜ

Slide 41

Slide 41 text

4UPSZCPBSE

Slide 42

Slide 42 text

.BJOTUPSZCPBSE

Slide 43

Slide 43 text

*OJUJBM7JFX$POUSPMMFS 6*/BWJHBUJPO$POUSPMMFS 7JFX$POUSPMMFSΛνΣʔϯͰ؅ཧ

Slide 44

Slide 44 text

.FEJB-JTU$POUSPMMFS 6*5BCMF7JFX$POUSPMMFS $FMM͸σϑΥϧτͰ࢖༻͢Δ $FMMʹ%FUBJM7JFX$POUSPMMFS΁ͷ 4FHVFΛઃఆ͍ͯ͠Δɹ

Slide 45

Slide 45 text

%FUBJM7JFX$POUSPMMFS 6*7JFX$POUSPMMFS 6**NBHF7JFXΛઃஔ

Slide 46

Slide 46 text

4FHVF 4FHVFΛϑοΫ͍ͨ͠৔߹ 4FHVF*EFOUJpFS 4FHVFͷભҠݩɺભҠઌΛઃఆ͢ Δͱ͖ʹࢦఆ

Slide 47

Slide 47 text

*OTUBHSBN"1*ˠσʔλ

Slide 48

Slide 48 text

*OTUBHSBN"1*ˠσʔλ σʔλऔಘͷྲྀΕ "MBNPpSF3FRVFTUΫϥεΛ࢖༻ͯ͠*OTUBHSBN"1*΁ϦΫΤετ ˠ.FEJB3FRVFTUΫϥε ϨεϙϯεͷσʔλΛ4XJGU+40/+40/ߏ଄ମ΁ ˠ.FEJB3FRVFTUΫϥε .FEJBߏ଄ମʹඞཁͳ৘ใΛ+40/ߏ଄ମ͔Βऔಘ ˠ.FEJB.PEFMΫϥε

Slide 49

Slide 49 text

*OTUBHSBN"1*ͱͷ࿈ܞ JSON Media Media Media Instagram API App Swifty JSON Swifty JSON Alamofire

Slide 50

Slide 50 text

.FEJB3FRVFTUΫϥε "MBNPpSF3FRVFTUΫϥεΛ࢖༻ͯ͠*OTUBHSBN"1*΁ϦΫΤετ ˠSFRVFTUϝιου͕༻ҙ͞Ε͍ͯΔͷͰɺͦΕΛ࢖༻͢Δ let urlString = "https://api.instagram.com/v1/media/popular" let param = ["client_id": "<#CLIENT-ID#>"] let req = request(.GET, urlString, parameters: param)

Slide 51

Slide 51 text

.FEJB3FRVFTUΫϥε Instagram API App JSON Media Media Media Swifty JSON Swifty JSON Alamofire

Slide 52

Slide 52 text

.FEJB3FRVFTUΫϥε ϨεϙϯεͷσʔλΛ4XJGU+40/+40/ߏ଄ମ΁ ˠ3FRVFTUͷ֦ுʹSFTQPOTFϝιου͕͋ΔͷͰ͜ΕΛ࢖༻͢Δ 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

Slide 53

Slide 53 text

.FEJB.PEFMΫϥε Media Media Media Swifty JSON Instagram API App JSON Swifty JSON Alamofire

Slide 54

Slide 54 text

.FEJB.PEFMΫϥε .FEJBߏ଄ମʹඞཁͳ৘ใΛ+40/ߏ଄ମ͔Βऔಘ ˠ·ͣɺ.FEJBߏ଄ମΛ࡞੒ struct Caption { var username: String? var text: String? } struct Media { var thumbnailURL: NSURL? var imageURL: NSURL? var caption: Caption? }

Slide 55

Slide 55 text

.FEJB.PEFMΫϥε Media Media Media Instagram API App Swifty JSON JSON Swifty JSON Alamofire

Slide 56

Slide 56 text

.FEJB3FRVFTUΫϥε .FEJBߏ଄ମʹඞཁͳ৘ใΛ+40/ߏ଄ମ͔Βऔಘ ˠ+40/ߏ଄ମ͔Β.FEJBߏ଄ମ΁ 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) }) }

Slide 57

Slide 57 text

4XJGUZ+40/Λ ࢖Θͳ͍৔߹

Slide 58

Slide 58 text

*OTUBHSBN͔Β৘ใΛऔಘ 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 ) }}}}}}

Slide 59

Slide 59 text

%PXODBTUΛ ଟ༻͢Δඞཁ͕͋Δ GPPBT 5ZQF

Slide 60

Slide 60 text

σʔλˠ6*5BCMF7JFX

Slide 61

Slide 61 text

6*5BCMF7JFX 6*5BCMF7JFXʹͯɺςʔϒϧΛදࣔͤ͞Δ 6*5BCMF7JFX%BUB4PVSDF1SPUPDPM ςʔϒϧදࣔͷߏ੒ʹඞཁͳσʔλΛऔಘ͢Δ 6*5BCMF7JFX%FMFHBUF1SPUPDPM ςʔϒϧͷϏϡʔ΍ΞΫγϣϯΛϑοΫ͢Δ 6*5BCMF7JFX%BUB4PVSDFͱ6*5BCMF7JFX%FMFHBUFΛࠞࡏ͠ͳ͍Α͏ʹ

Slide 62

Slide 62 text

6*5BCMF7JFX%BUB4PVSDF Լه͸ඞ࣮ͣ૷͢Δඞཁ͕͋Δ func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell

Slide 63

Slide 63 text

6*5BCMF7JFX%FMFHBUF ηϧͷߴ͞ ηϧͷදࣔ΍λοϓ࣌ͷڍಈ ηϧͷฤूڍಈ ηΫγϣϯϔομʔϑολʔϏϡʔͷߴ͞ ηΫγϣϯϔομʔϑολʔϏϡʔͷϏϡʔ

Slide 64

Slide 64 text

.FEJBΛ6*5BCMF7JFX΁ .FEJBΛදࣔ͢Δʹ͸ʜ ηϧͷ਺ ˠ.FEJB-JTUͷதʹ͋ΔNFEJBͷ਺ ηϧͷߴ͞ʢෆมʁՄมʁʣ ˠՄมͳΒ͹NFEJB͔Βܭࢉ ηϧͷத਎ ˠNFEJB͔Βඞཁͳ৘ใΛऔಘ ࠓճͷϓϩδΣΫτͰ͸*OTUBHSBN"1*͔Βऔಘͨ͠σʔλ͸.FEJB.PEFM͕ ಺෦Ͱอ͍࣋ͯ͠Δ

Slide 65

Slide 65 text

6*5BCMF7JFXηϧͷ਺ .FEJB.PEFM͕อ͍࣋ͯ͠Δ഑ྻͷத਎ͷ਺ override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return MediaModel.sharedInstance.mediaList.count }

Slide 66

Slide 66 text

6*5BCMF7JFXηϧͷߴ͞ Մมͷͱ͖Λߟ͑ͯɺ.FEJB-JTU$FMMΫϥε͔Βηϧͷߴ͞Λऔಘ͢Δ 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 }

Slide 67

Slide 67 text

6*5BCMF7JFXηϧͷத਎ ૄʹ͢ΔͨΊɺ.FEJB-JTU$FMMͷΠϯελϯε΁NFEJBΛ౉͢ 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) }

Slide 68

Slide 68 text

.FEJB-JTU$FMMDPOpHVSF ը૾σʔλ͸ඇಉظͷผεϨουͰऔಘ͢Δ औಘ׬ྃͨ͠ΒɺಉظͰϝΠϯεϨουʹ໭Δ 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 }

Slide 69

Slide 69 text

(PPHMF"OBMZUJDT

Slide 70

Slide 70 text

(PPHMF"OBMZUJDTͷॳظԽ ॳظԽ͸("*Πϯελϯε͔ΒA("*5SBDLFSAΛऔಘ͢Δ 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") }

Slide 71

Slide 71 text

(PPHMF"OBMZUJDT΁ૹ৴ (PPHMF"OBMZUJDT΁৘ใΛૹ৴ A("*5SBDLFSAͷATFOEAϝιου 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) } }

Slide 72

Slide 72 text

7JFX8JMM"QQFBSͰτϥοΩϯά ࡞ͬͨAUSBDL7JFXAϝιουΛඞཁͳͱ͖ʹ࢖༻͢Δ override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) let screenName = reflect(self).summary AnalyticsUtils.trackView(screenName) }

Slide 73

Slide 73 text

͓ΘΓʹ

Slide 74

Slide 74 text

͕࣌ؒ͋Ε͹ ฉ͖͍ͨ͜ͱΛϥΠϒίʔσΟϯά͠·͢ %FMFHBUFͱ͔