swift 的网络请求--Alamofire框架
2015-09-08 15:45
471 查看
[1]
[2] 登陆按钮按下 调用接口
[3] 加载本地数据
[4]将数据存储在本地
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) } }