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

Swift InstagramViewer

Swift InstagramViewer

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) } }