Alamofire的使用教程

环境:Alamofire 4, Xcode 8.2, iOS 10, and Swift 3.
Alamofire是一个基于HTTP的网络请求库,适用于iOS和OSX,针对apple的基本网络请求库作了封装,简化网络请求的复杂逻辑。
Alamofire提供了request/response方法,JSON参数形式,序列化功能,以及authentication等许多特性。在本篇文章中,你可以学到通过Alamofire实现基本的数据上传和下载。
首先,下载基本的空项目:https://koenig-media.raywenderlich.com/uploads/2016/12/PhotoTagger-starter-1.zip
这个项目名称叫做PhotoTagger,当你完成了这个项目,会实现以下的效果:当你从照片库选择一张照片,并且上传到我们指定的第三方服务器,就可以实现照片的智能识别,包含照片所包含的标签,和图片的合成颜色:
这里写图片描述
下载完项目,build运行后你可以看到下面的效果。
这里写图片描述
点击select Photo按钮,当前view的背景会换成你选择的图片的样子

Imagga 的API

Imagga是一个图片识别平台,为开发者免费提供了图片的上传获取API,有兴趣可以看看Imagga平台的这个小项目。https://imagga.com/auto-tagging-demo?url=https://imagga.com/static/images/tagging/vegetables.jpg
如果想使用Imagga,首页需要注册成为其平台的开发者,填下一下的表格即可https://imagga.com/auth/signup/hacker
当填完后这个表格后,点击确定进入主页面,能看到这个页面
这里写图片描述
注意Authorization 这个部分,在以后的网络请求中会有用到。
这里是imagga的文档详细使用说明,需要的可以看看。http://docs.imagga.com/

安装 Dependencies

创建cocoaPod环境,创建Podfile文件,如下

platform :ios, '10.0'

inhibit_all_warnings!
use_frameworks!

target 'PhotoTagger' do
  pod 'Alamofire', '~> 4.2.0'
end

然后在终端执行以下指令:

pod install

如果你的电脑上没有安装cocoaPods环境,查看这篇文章http://www.raywenderlich.com/97014/use-cocoapods-with-swift
关闭当前的项目,并且打开项目PhotoTagger.xcworkspace. 运行后发现还开始的页面都一样,没有变化,下面开始正式进入网络请求的介绍部分。

开始一个Alamofire请求

分为三个部分,
upload:上传multipart files和stream,file 或data
download:下载files或者重新开始一个已经开始的网络请求
,request:每一个不含文件上传和下载的Http请求。

上传 Files

打开ViewController.swift 并且引进头文件

import Alamofire

这样就可以使用Alamofire提供的function了
接着:添加一个extension到文件的最后面

// Networking calls
extension ViewController {
  func upload(image: UIImage,
              progressCompletion: @escaping (_ percent: Float) -> Void,
              completion: @escaping (_ tags: [String], _ colors: [PhotoColor]) -> Void) {
    guard let imageData = UIImageJPEGRepresentation(image, 0.5) else {
      print("Could not get JPEG representation of UIImage")
      return
    }
  }
}

这一步上传我们本地的图片到imagga的服务器,同时会返回给我们一个图片。

然后,在imagePickerController(_:didFinishPickingMediaWithInfo:)方法中的给imageView赋值image时添加以下代码:

// 1
takePictureButton.isHidden = true
progressView.progress = 0.0
progressView.isHidden = false
activityIndicatorView.startAnimating()

upload(
  image: image,
  progressCompletion: { [unowned self] percent in
    // 2
    self.progressView.setProgress(percent, animated: true)
  },
  completion: { [unowned self] tags, colors in
    // 3
    self.takePictureButton.isHidden = false
    self.progressView.isHidden = true
    self.activityIndicatorView.stopAnimating()

    self.tags = tags
    self.colors = colors

    // 4
    self.performSegue(withIdentifier: "ShowResults", sender: self)
  })

所有的alamofire的请求都是异步的,这样就意味着UI的刷新也是异步的,下面介绍每一步的含义:
1. 隐藏上传按钮,并且展示上传的进度和activity view
2. 上传文件的时候通过progress handler 来更新上传进度条:
3.当上传完成之后,通过completion handler来更新UI
4.当上传完成之后,通过storyBoard来实现跳转。
然后 在upload(image:progressCompletion:completion:) 的image转化之后添加以下代码:

Alamofire.upload(
  multipartFormData: { multipartFormData in
    multipartFormData.append(imageData,
                             withName: "imagefile",
                             fileName: "image.jpg",
                             mimeType: "image/jpeg")
  },
  to: "http://api.imagga.com/v1/content",
  headers: ["Authorization": "Basic xxx"],
  encodingCompletion: { encodingResult in
  }
)

记着更换Basic xxx 成你自己的。
然后,在encodingCompletion的闭包里面添加以下代码:

switch encodingResult {
case .success(let upload, _, _):
  upload.uploadProgress { progress in
    progressCompletion(Float(progress.fractionCompleted))
  }
  upload.validate()
  upload.responseJSON { response in
  }
case .failure(let encodingError):
  print(encodingError)
}

然后。在upload.responseJSON:添加以下代码

// 1.
guard response.result.isSuccess else {
  print("Error while uploading file: \(response.result.error)")
  completion([String](), [PhotoColor]())
  return
}

// 2.
guard let responseJSON = response.result.value as? [String: Any],
  let uploadedFiles = responseJSON["uploaded"] as? [[String: Any]],
  let firstFile = uploadedFiles.first,
  let firstFileID = firstFile["id"] as? String else {
    print("Invalid information received from service")
    completion([String](), [PhotoColor]())
    return
}

print("Content uploaded with ID: \(firstFileID)")

// 3.
completion([String](), [PhotoColor]())

这里分步介绍每一步的含义:
1. 查看请求是否成功,如果失败,打印失败信息,并且调用completion handler。
2. 分离每一部分的数据,并查看返回的状态是否有效,如果有错误,打印失败信息,并且调用completion handler。
3. 更新UI
运行项目,选择一张图片上传,可以在打印台看到以下信息:
图片
这个时候,已经完成了基本的数据上传

数据下载

接下来就是讲刚刚上传照片的分析数据下载下来。
在ViewController的upload(image:progress:completion:):中添加以下代码

func downloadTags(contentID: String, completion: @escaping ([String]) -> Void) {
  Alamofire.request(
    "http://api.imagga.com/v1/tagging",
    parameters: ["content": contentID],
    headers: ["Authorization": "Basic xxx"]
  )
  .responseJSON { response in
    guard response.result.isSuccess else {
      print("Error while fetching tags: \(response.result.error)")
      completion([String]())
      return
    }

    guard let responseJSON = response.result.value as? [String: Any] else {
      print("Invalid tag information received from the service")
      completion([String]())
      return
    }

    print(responseJSON)
    completion([String]())
  }
}

然后upload(image:progress:completion:) 替换completion handler为以下代码

self.downloadTags(contentID: firstFileID) { tags in
  completion(tags, [PhotoColor]())
}

运行项目,上传你的文件并且查看控制台信息。如下图:
这里写图片描述
然后返回downloadTags(contentID:completion:) 并且替换.responseJSON
下的代码为以下代码

// 1.
guard response.result.isSuccess else {
  print("Error while fetching tags: \(response.result.error)")
  completion([String]())
  return
}

// 2.
guard let responseJSON = response.result.value as? [String: Any],
  let results = responseJSON["results"] as? [[String: Any]],
  let firstObject = results.first,
  let tagsAndConfidences = firstObject["tags"] as? [[String: Any]] else {
    print("Invalid tag information received from the service")
    completion([String]())
    return
}

// 3.
let tags = tagsAndConfidences.flatMap({ dict in
  return dict["tag"] as? String
})

// 4.
completion(tags)

运行项目,上传一张图片就可以看到以下效果:
这里写图片描述
下面开始获取图片的colors的接口,同样的:
在ViewController的downloadTags(contentID:completion:):下面添加以下代码

func downloadColors(contentID: String, completion: @escaping ([PhotoColor]) -> Void) {
  Alamofire.request(
    "http://api.imagga.com/v1/colors",
    parameters: ["content": contentID],
    // 1.
    headers: ["Authorization": "Basic xxx"]
  )
  .responseJSON { response in
    // 2.
    guard response.result.isSuccess else {
      print("Error while fetching colors: \(response.result.error)")
      completion([PhotoColor]())
      return
    }

    // 3.
    guard let responseJSON = response.result.value as? [String: Any],
      let results = responseJSON["results"] as? [[String: Any]],
      let firstResult = results.first,
      let info = firstResult["info"] as? [String: Any],
      let imageColors = info["image_colors"] as? [[String: Any]] else {
        print("Invalid color information received from service")
        completion([PhotoColor]())
        return
    }

    // 4.
    let photoColors = imageColors.flatMap({ (dict) -> PhotoColor? in
      guard let r = dict["r"] as? String,
        let g = dict["g"] as? String,
        let b = dict["b"] as? String,
        let closestPaletteColor = dict["closest_palette_color"] as? String else {
          return nil
      }

      return PhotoColor(red: Int(r),
                        green: Int(g),
                        blue: Int(b),
                        colorName: closestPaletteColor)
    })

    // 5.
    completion(photoColors)
  }
}

最后在upload(image:progress:completion:)的completion handler下面添加以下代码:

self.downloadTags(contentID: firstFileID) { tags in
  self.downloadColors(contentID: firstFileID) { colors in
    completion(tags, colors)
  }
}

运行项目,并且点击colors 按钮可以看到以下效果。
这里写图片描述

项目地址:https://github.com/LINDreaming/DailyTools
原文地址:https://www.raywenderlich.com/147086/alamofire-tutorial-getting-started-2

猜你喜欢

转载自blog.csdn.net/SunFlowerInRain/article/details/76207022