Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Swift InstagramViewer

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

Swift InstagramViewer

Avatar for Shintaro Kaneko

Shintaro Kaneko

December 17, 2014
Tweet

More Decks by Shintaro Kaneko

Other Decks in Programming

Transcript

  1. 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
  2. 0QUJPOBM A0QUJPOBM5AJTLJOEPGAFOVNA 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) 4P JUJTBCMFUPFYQSFTTUIFN var str5: Optional<String> = Optional<String>() // nil var str6: Optional<String> = Optional<String>("Hello") // {Some "Hello"}
  3. 0QUJPOBM 6TFAANBSLBGUFSBOPQUJPOBMWBMVFUPGPSDFUIFVOXSBQQJOHPGJUTWBMVF var str6: Optional<String> = Optional<String>("Hello") var str7: String

    = str6 // Compile error var str8: String = str6! // "Hello" "OPQUJPOBMWBMVFGBJMTXIFOUIFPQUJPOBMJTAOJMA var str5: Optional<String> = Optional<String>() var str9: String = str5! // Runtime error
  4. 4XJUDI let country: String = "Canada" switch country { case

    "USA": println("USA") case "Canada": println("Canada") case "Japan": fallthrough default: println("Other") }
  5. 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)")
  6. 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") }
  7. '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 } ```
  8. 1SPUPDPM protocol AProtocol { func behaviour() -> Void } @objc

    protocol SomeProtocol { func behaviour() -> Void optional func optBehaviour() -> Void } class Foo: NSObject, AProtocol { func behaviour() { } }
  9. ϒϦοδϯάϔομʔ 4XJGUͰ0CKFDUJWF$ΫϥεΛ࢖༻͢Δʹ͸ϒϦοδϯά͕ඞཁ ϒϦοδϯάϔομʔϑΝΠϧΛఆٛ͢Δ #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 */ ˞ࢀߟɿIUUQRJJUBDPNLBOFTIJOUIJUFNTGDEFFB
  10. ࣮૷ύλʔϯʢҰྫʣ ├── 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
  11. .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
  12. .FEJB.PEFMΫϥε .FEJBߏ଄ମʹඞཁͳ৘ใΛ+40/ߏ଄ମ͔Βऔಘ ˠ·ͣɺ.FEJBߏ଄ମΛ࡞੒ struct Caption { var username: String? var

    text: String? } struct Media { var thumbnailURL: NSURL? var imageURL: NSURL? var caption: Caption? }
  13. .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) }) }
  14. *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 ) }}}}}}
  15. 6*5BCMF7JFX%BUB4PVSDF Լه͸ඞ࣮ͣ૷͢Δඞཁ͕͋Δ func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
  16. 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 }
  17. 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) }
  18. .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 }
  19. (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") }
  20. (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) } }