欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Alamofire的使用教程

程序员文章站 2024-03-23 12:02:10
...

环境: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,当你完成了这个项目,会实现以下的效果:当你从照片库选择一张照片,并且上传到我们指定的第三方服务器,就可以实现照片的智能识别,包含照片所包含的标签,和图片的合成颜色:
Alamofire的使用教程
下载完项目,build运行后你可以看到下面的效果。
Alamofire的使用教程
点击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
当填完后这个表格后,点击确定进入主页面,能看到这个页面
Alamofire的使用教程
注意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]())
}

运行项目,上传你的文件并且查看控制台信息。如下图:
Alamofire的使用教程
然后返回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)

运行项目,上传一张图片就可以看到以下效果:
Alamofire的使用教程
下面开始获取图片的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 按钮可以看到以下效果。
Alamofire的使用教程

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