iOS:使用服务器中的图像

如果您是移动应用程序开发人员,则有时需要与后端进行交互。 您可能需要执行的任务之一是从服务器检索并显示图像,或将图像提交到该服务器。 提交图像时应使用哪种格式? 您如何将从服务调用中收到的字节转换为图像?

让我们构建从服务器到iOS App的整个堆栈,以了解操作方法。

设置一个后端

我们将首先构建一个Kitura服务器,该服务器提供RESTful API来完成两件事:

  • 从客户端接收图像
  • 提供接收到客户端的最新图像

我已经把完成的服务器放在我的Github上了 。

创建服务器项目

创建一个目录,并初始化一个新的可执行Swift包。

  mkdir mkdir SwiftImageServer && cd SwiftImageServer 
  swift package init --type可执行文件 

编辑您的Package.swift文件,以指定您需要Kitura软件包。

  导入PackageDescription 让package = Package( 
      名称:“ SwiftImageServer”, 
      依赖项:[ 
        .Package(URL:“ https://github.com/IBM-Swift/Kitura.git”,majorVersion:1 ) 
      ]) 

您可以运行swift package fetch并且应该看到SwiftPM克隆Kitura及其所需的一切。

使用swift package generate-xcodeproj ,让我们开始编码!

创建一个Kitura服务器

后端将非常简单,因此我们将在main.swift

让我们从添加所需的所有样板开始:

  进口Kitura 
  import Foundation //创建一个可用于创建REST端点的路由器 
  let router = Router() //指定我们要使用http:// localhost:8090可以访问的HTTP服务器 
  Kitura.addHTTPServer(onPort:8090,with:router) //启动服务器 
  Kitura.run() 

我爱这些天创建一件东西是多么容易。 三行代码,您就可以运行服务器。 可惜它做不了多少。 让我们修复它。

从GET端点返回图像

  var LatestImage:数据?  =零 // http:// localhost:8090 / latestImage 
  router.get(“ / latestImage”){ 
      请求,响应, 推迟进行下一步{next()} 保护let image = LatestImage else { 
          response.status(.preconditionFailed).send(“没有可用的图像”) 
          返回 
      } response.send(data:image) 
  } 

您以为我们正在发送图像,您说吗? 看起来像数据对象, 而不是 UIImage? 这就是乐趣所在。您永远不会将图像作为图像发送。 所有图像都只是以易于使用的格式打包的数据 。 当我们向服务器发送图像或从服务器发送图像时,我们需要将其打包为Data对象并发送。 我们将在iOS应用中将其表示为UIImage。

注意guard let image = latestImage 。 直到我们设置了latestImage变量,该操作latestImage失败。 让我们构建接收图像的端点,以便我们可以设置latestImage变量。

将图像提交到POST端点

接下来,我们将构建用于提交图像的端点。

  //创建POST端点: http:// localhost:8090 / image 
  router.post(“ / image”){ 
      请求,响应, 延后进行下一步{next()} var data = Data() 做{ 
          //将请求的主体读入数据对象 
          尝试_ = request.read(进入:&data) 
          LatestImage =数据 
          response.status(.OK).send(“已收到图片”) 
      } catch(让错误出现){ 
          response.status(.internalServerError) 
                  .send(“读取图像数据时出了点问题”) 
      } 
  } 

我们创建了一个端点,该端点期望带有图像数据原始内容的POST请求。 请记住,服务器仅知道数据,而不是UIImage,因此iOS应用将不得不将图像转换为Data对象。

这就是我们整个服务器的工作!

启动并运行

这是完成的服务器的链接: https : //github.com/TheCodedSelf/SwiftImageServer

运行可执行目标。 那是具有Matrix样式的计算机屏幕的屏幕,而不是黄色的便当盒。

保持运行,我们将构建iOS应用。

客户端应用

我的Github上提供了iOS应用程序的完整示例代码。

创建项目

创建一个新的Single View iOS应用程序。 我们将需要修改Info.plist 。 我们需要访问照片库的权限才能选择图像。 我们还需要修改App Transport Security设置以发出HTTP网络请求,而不是HTTPS(我们的本地Kitura服务器是HTTP)。

将以下内容添加到项目的Info.plist

我们将添加一个按钮,该按钮将使我们能够从相册中选择图像,并将其提交给我们之前构建的服务器。

首先,向Main.storyboard的视图控制器添加一个按钮:

现在,将其连接到ViewController.swift并添加代码以将其发布到我们的后端。

让我们将IBAction连接到“选择图像”按钮,在此处使用UIImagePickerController拾取图像。

  @IBAction func pickImage(_ sender:Any){ 保护UIImagePickerController.isSourceTypeAvailable(.photoLibrary)否则{return} 
          让imagePickerController = UIImagePickerController() 
          imagePickerController.sourceType = .photoLibrary 
          imagePickerController.delegate =自我 
          present(imagePickerController,动画:true,完成:无) 
      } 

我们将ViewController设置为UIImagePickerController的委托。 添加一个符合委托协议的扩展,该协议还可以处理所有拾取的图像。 设置委托还需要符合UINavigationControllerDelegate,因此也要添加它。

 extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate { public func imagePickerController( _ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: Any]) { if let image = info[UIImagePickerControllerOriginalImage] as? UIImage { submit(image: image) } else if let image = info[UIImagePickerControllerEditedImage as? UIImage { submit(image: image) } picker.dismiss(animated: true) } } 

我们可以选择一个图像,并且已经准备好处理它。 注意上面示例中的submit(image:)函数。 我们现在将创建该函数,并将图像提交到我们的服务器。

 func submit(image: UIImage) { let session = URLSession( configuration: URLSessionConfiguration.default) guard let url = URL(string: "http://localhost:8090/image") else { return } var request = URLRequest(url: url) request.httpMethod = "POST" request.httpBody = UIImagePNGRepresentation(image) let dataTask = session.dataTask(with: request) { (data, response, error) in if let error = error { print("Something went wrong: \(error)") } if let response = response { print("Response: \n \(response)") } } dataTask.resume() } 

从服务器接收图像

现在我们已经能够将图像提交为Data对象,我们需要构建功能来接收图像作为Data并将其转换为简单的旧UIImage。

首先向Main.storyboard中的视图控制器添加图像视图和另一个按钮:

当用户点击新按钮时,我们将调用最新图像端点,以检索作为数据对象发送到我们服务器的最后一个图像。 然后,我们将其转换为UIImage并将其显示在图像视图中。

 @IBOutlet weak var imageView: UIImageView! @IBAction func showLatestImage(_ sender: Any) { let session = URLSession( configuration: URLSessionConfiguration.default) guard let url = URL( string: "http://localhost:8090/latestImage") else { return } var request = URLRequest(url: url) request.httpMethod = "GET" session.dataTask(with: request) { (data, response, error) in if let error = error { print("Something went wrong: \(error)") } if let imageData = data { DispatchQueue.main.async { self.imageView.image = UIImage(data: imageData) } } }.resume() } 

成品

这是我们的应用程序,它已将图像提交到服务器并从服务器拉出图像进行显示。

当您点击“选择图像”时,会看到一个UIIImagePickerController,它允许您从“照片库”中选择一个图像,并将其转换为数据对象后将其提交给我们的后端。 “显示最新图像”按钮向我们的服务器发出GET请求,以检索发送的最后一个图像,将其转换为UIImage,然后将其显示在我们的UIImageView中。

现在,您应该对如何将除文本以外的objecs发送到服务器以及如何检索它们有了基本的了解。 恭喜你!

祝您玩得开心,Swifting开心!