swift 的网络请求--Alamofire框架

[1]

import Alamofire

public struct DesignerNewsService {

    // Designer News API Doc: http://developers.news.layervault.com
    //                    V2: https://github.com/metalabdesign/dn_api_v2

    private static let baseURL = "https://www.designernews.com"
    private static let clientID = "750ab22aac78be1c6d4bbe584f0e3477064f646720f327c5464bc127100a1a6d"
    private static let clientSecret = "53e3822c49287190768e009a8f8e55d09041c5bf26d0ef982693f215c72d87da"

    private enum ResourcePath: Printable {
        case Login
        case Stories
        case StoryUpvote(storyId: Int)
        case StoryReply(storyId: Int)
        case CommentUpvote(commentId: Int)
        case CommentReply(commentId: Int)
        var description: String {
            switch self {
            case .Login: return "/oauth/token"
            case .Stories: return "/api/v1/stories"
            case .StoryUpvote(let id): return "/api/v1/stories/\(id)/upvote"
            case .StoryReply(let id): return "/api/v1/stories/\(id)/reply"
            case .CommentUpvote(let id): return "/api/v1/comments/\(id)/upvote"
            case .CommentReply(let id): return "/api/v1/comments/\(id)/reply"
            }
        }
    }

    public enum StorySection: Printable {
        case Default
        case Recent
        case Search(query: String)

        public var description : String {
            switch (self) {

            case .Default: return ""
            case .Recent: return "recent"
            case .Search(_): return "search"
            }
        }
    }

    public static func storiesForSection(section: StorySection, page: Int, response: ([Story]) -> ()) {
        let urlString = baseURL + ResourcePath.Stories.description + "/" + section.description
        var parameters : [String:AnyObject] = [
            "page": toString(page),
            "client_id": clientID
        ]

        let query: String?
        switch (section) {
        case let .Search(keyword):
            query = keyword
        default:
            query = nil
        }

        parameters["query"] = query
        Alamofire.request(.GET, urlString, parameters: parameters).response { (request, res, data, error) in
            let stories = JSONParser.parseStories(data as? NSData)
            response(stories)
        }
    }

    public static func loginWithEmail(email: String, password: String, response: (token: String?) -> ()) {
        let urlString = baseURL + ResourcePath.Login.description
        let parameters = [
            "grant_type": "password",
            "username": email,
            "password": password,
            "client_id": clientID,
            "client_secret": clientSecret
        ]

        Alamofire.request(.POST, urlString, parameters: parameters)
            .responseJSON { (_, _, json, _) in
                let responseDictionary = json as? NSDictionary
                let token = responseDictionary?["access_token"] as? String
                response(token: token)
        }
    }

    public static func upvoteStoryWithId(storyId: Int, token: String, response: (successful: Bool) -> ()) {
        let resourcePath = ResourcePath.StoryUpvote(storyId: storyId)
        upvoteWithResourcePath(resourcePath, token: token, response: response)
    }

    public static func upvoteCommentWithId(commentId: Int, token: String, response: (successful: Bool) -> ()) {
        let resourcePath = ResourcePath.CommentUpvote(commentId: commentId)
        upvoteWithResourcePath(resourcePath, token: token, response: response)
    }

    public static func replyStoryWithId(storyId: Int, token: String, body: String, response: (comment: Comment?, error: Error?) -> ()) {
        let resourcePath = ResourcePath.StoryReply(storyId: storyId)
        replyWithResourcePath(resourcePath, token: token, body: body, response: response)
    }

    public static func replyCommentWithId(commentId: Int, token: String, body: String, response: (comment: Comment?, error: Error?) -> ()) {
        let resourcePath = ResourcePath.CommentReply(commentId: commentId)
        replyWithResourcePath(resourcePath, token: token, body: body, response: response)
    }

    // MARK: Private Methods

    private static func upvoteWithResourcePath(path: ResourcePath, token: String, response: (successful: Bool) -> ()) {
        let urlString = baseURL + path.description
        let request = NSMutableURLRequest(URL: NSURL(string: urlString)!)
        request.HTTPMethod = "POST"
        request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")

        Alamofire.request(request).responseJSON { (_, urlResponse, _, _) in
            let successful = urlResponse?.statusCode == 200
            response(successful: successful)
        }
    }

    private static func replyWithResourcePath(path: ResourcePath, token: String, body: String, response: (comment: Comment?, error: Error?) -> ()) {

        let urlString = baseURL + path.description
        let request = NSMutableURLRequest(URL: NSURL(string: urlString)!)
        request.HTTPMethod = "POST"
        request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
        request.HTTPBody = "comment[body]=\(body)".dataUsingEncoding(NSUTF8StringEncoding)

        Alamofire.request(request).responseJSON { (_, urlResponse, json, error) in
            if let message = json?["error"] as? String {
                response(comment: nil, error: Error(message: message, code: urlResponse?.statusCode ?? 0))
            } else if let commentDict = json?["comment"] as? NSDictionary {
                let comment = JSONParser.parseComment(commentDict)
                response(comment: comment, error: nil)
            } else {
                response(comment: nil, error: Error(message: error?.localizedDescription ?? "Something went wrong", code: error?.code ?? 0))
            }
        }
    }
}

[2] 登陆按钮按下 调用接口

    // MARK: Button
    @IBAction func signupButtonPressed(sender: AnyObject) {
        view.showLoading()
        DesignerNewsService.loginWithEmail(emailTextField.text, password: passwordTextField.text) { token in
            self.view.hideLoading()
            if let token = token {
                LocalStore.setAccessToken(token)
                self.dialogView.animation = "zoomOut"
                self.dialogView.animate()
                self.dismissViewControllerAnimated(true, completion: nil)
                UIApplication.sharedApplication().sendAction("reset:", to: nil, from: self, forEvent: nil)
                self.delegate?.loginViewControllerDidLogin(self)
            } else {
                self.dialogView.animation = "shake"
                self.dialogView.animate()
            }
        }
    }

[3] 加载本地数据

//
//  LocalStore.swift
//

import UIKit

struct LocalStore {
    private static let visitedStoriesKey = "visitedStoriesKey"
    private static let upvotedStoriesKey = "upvotedStoriesKey"
    private static let repliedStoriesKey = "repliedStoriesKey"
    private static let upvotedCommentsKey = "upvotedCommentsKey"
    private static let accessTokenKey = "accessTokenKey"
    private static let userDefaults = NSUserDefaults.standardUserDefaults()

    static func setIntroAsVisited() {
        userDefaults.setObject(true, forKey: "introKey")
    }

    static func isIntroVisited() -> Bool {
        return userDefaults.boolForKey("introKey")
    }

    static func setStoryAsReplied(storyId: Int) {
        appendId(storyId, toKey: repliedStoriesKey)
    }

    static func setStoryAsVisited(storyId: Int) {
        appendId(storyId, toKey: visitedStoriesKey)
    }

    static func setStoryAsUpvoted(storyId: Int) {
        appendId(storyId, toKey: upvotedStoriesKey)
    }

    static func removeStoryFromUpvoted(storyId: Int) {
        removeId(storyId, forKey: upvotedStoriesKey)
    }

    static func setCommentAsUpvoted(commentId: Int) {
        appendId(commentId, toKey: upvotedCommentsKey)
    }

    static func removeCommentFromUpvoted(commentId: Int) {
        removeId(commentId, forKey: upvotedCommentsKey)
    }

    static func isStoryReplied(storyId: Int) -> Bool {
        return arrayForKey(repliedStoriesKey, containsId: storyId)
    }

    static func isStoryVisited(storyId: Int) -> Bool {
        return arrayForKey(visitedStoriesKey, containsId: storyId)
    }

    static func isStoryUpvoted(storyId: Int) -> Bool {
        return arrayForKey(upvotedStoriesKey, containsId: storyId)
    }

    static func isCommentUpvoted(commentId: Int) -> Bool {
        return arrayForKey(upvotedCommentsKey, containsId: commentId)
    }

    static func setAccessToken(token: String) {
        userDefaults.setObject(token, forKey: accessTokenKey)
        userDefaults.synchronize()
    }

    private static func deleteAccessToken() {
        userDefaults.removeObjectForKey(accessTokenKey)
        userDefaults.synchronize()
    }

    static func removeUpvotes() {
        userDefaults.removeObjectForKey(upvotedStoriesKey)
        userDefaults.removeObjectForKey(upvotedCommentsKey)
        userDefaults.synchronize()
    }

    static func accessToken() -> String? {
        return userDefaults.stringForKey(accessTokenKey)
    }

    static func logout() {
        self.deleteAccessToken()
    }

    // MARK: Helper

    static private func arrayForKey(key: String, containsId id: Int) -> Bool {
        let elements = userDefaults.arrayForKey(key) as? [Int] ?? []
        return contains(elements, id)
    }

    static private func appendId(id: Int, toKey key: String) {
        let elements = userDefaults.arrayForKey(key) as? [Int] ?? []
        if !contains(elements, id) {
            userDefaults.setObject(elements + [id], forKey: key)
            userDefaults.synchronize()
        }
    }

    static private func removeId(id: Int, forKey key: String) {
        var elements = userDefaults.arrayForKey(key) as? [Int] ?? []
        if let index = find(elements, id) {
            elements.removeAtIndex(index)
            userDefaults.setObject(elements, forKey: key)
            userDefaults.synchronize()
        }
    }
}

[4]将数据存储在本地

//
//  StoriesLoader.swift
//

import Foundation
import DesignerNewsKit

class StoriesLoader {

    typealias StoriesLoaderCompletion = (stories:[Story]) ->()

    private (set) var hasMore : Bool = false
    private var page : Int = 1
    private var isLoading : Bool = false
    private let section : DesignerNewsService.StorySection

    init(_ section: DesignerNewsService.StorySection = .Default) {
        self.section = section
    }

    func load(page: Int = 1, completion: StoriesLoaderCompletion) {
        if isLoading {
            return
        }

        isLoading = true
        DesignerNewsService.storiesForSection(section, page: page) { [weak self] stories in
            if let strongSelf = self {
                switch (strongSelf.section) {
                case .Search(_):
                    strongSelf.hasMore = false
                default:
                    strongSelf.hasMore = stories.count > 0
                }
                strongSelf.isLoading = false
                completion(stories: stories)
            }
        }
    }

    func next(completion: (stories:[Story]) ->()) {
        if isLoading {
            return
        }

        ++page
        load(page: page, completion: completion)
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值