使用iOS应用程序抓取Firebase服务

那是晴天的时候之一,那时我回到家,终于有时间从我的购物清单中计划好美食应用程序。 不管是好是坏,我不仅需要进行应用程序设计,而且:

  • 身份验证。
  • 我可以在其中保存和检索内容(数据,信息,图像)的数据库。
  • 可搜索的食品API。

大概,我需要一个认真的人加入我自己的小团队。 或者,我可以一个人做吗? 或多或少😃。 简短答案-是的! 因为我一方面找到了价格合理的可搜索食物API,另一方面又找到了Firebase 。 长答案? 继续阅读!

Firebase是面向移动开发人员的统一平台(是的,适用于Android和iOS),提供了许多很棒的功能,其中包括实时数据库,崩溃报告,分析,身份验证等。最好在以下位置查看整个列表:他们的官方网站。

我写的最后一篇文章包括一个项目 名为Unicorner,旨在接收带有Unicorner用户看到并拍照的独角兽图像的远程通知。 这次,该项目将要拍摄独角兽的图片并将其上传到数据库。 然后,来自数据库的数据将被馈送到一个列表,在该列表中可以看到上传的图片和信息。 通知不会发送,但我们可以在另一篇文章中进行处理,对吗?

无论如何,这是计划的文章工作流程:

  • Firebase帐户注册和iOS应用程序配置。
  • 在Xcode中设置Demo项目。
  • 编写一些代码以与Firebase实时数据库和存储进行通信。

实际上,这很简单。 首先转到此链接,然后单击屏幕右上方的“ 登录”按钮。 可以使用gmail帐户( 大多数人都拥有一个 )登录,也可以按照注册步骤创建新帐户来登录。

完成后,再次点击右上方的转到控制台进入 Firebase控制台。 这是可见的:

我的Firebase控制台中已经有一个正在处理的应用程序项目。 要添加另一个,只需点击添加项目,然后看到此模式:

我为我的项目选择的名称是UnicornUploader 我选择的地区是美国。 根据需要选择,然后单击创建项目

在创建项目时稍等一下,瞧:

点击“ 继续”后 ,您将进入“ 项目概述”页面:

在这里可以访问Firebase提供的所有功能。 确实,在本文中,我将仅关注三个方面-身份验证,数据库和存储。 您确保在时间允许的情况下将它们全部检查出来。

将Firebase添加到iOS应用

是时候选择将Firebase添加到您的iOS 应用程序中,以将Firebase添加到我的iOS应用程序中

我已经输入了演示项目的iOS Bundle ID,对您的演示文稿也做了同样的操作,然后点击Register App

加载后,出现Xcode指令,最好遵循它们! 下载该GoogleService-Info.plist文件并将其添加到Xcode项目中:

点击Continue之后 ,第3步包含有关如何以Cocoapod依赖项的形式将Firebase添加到项目的说明:

不用担心,如果您使用的是演示项目,那么我已经为所需的所有依赖项完成了Cocoapod的设置。 不过,请务必使用.xcworkspace文件。 再次单击继续 ,然后查看Firebase设置的最后一步:

如果使用自己的项目,请执行此操作。 如果使用我的,不用担心,我也将设置配置添加到了AppDelegate文件中 。 单击完成,然后看到这个不太有趣的窗口,其中显示了项目的应用程序信息:

其他Firebase配置

出于演示项目的目的,还有一些其他事情需要注意。

第一个是身份验证配置 。 在左侧的Firebase控制台上,点击身份验证

然后,您将看到以下内容:

单击蓝色按钮后,将显示“ 身份验证选项”的整个列表。 太棒了!

为了简单起见,我将仅启用“ 匿名”选项。 单击“ 保存” ,您就可以完成演示项目

接下来需要设置的是实时数据库 。 在左侧的Firebase控制台上 ,这次点击“ 数据库”以查看以下内容:

单击“ 实时数据库”“入门”按钮,原因是该演示所需的原因:

在启用实时数据库之前,我需要确定安全规则。 好吧,由于我将仅进行测试,因此我现在将选择“ 以测试模式启动” 。 我可以继续,单击“ 启用” ,现在就完成“数据库”部分。

最后但并非最不重要的一点是,我还需要启用Firebase Storage 。 同样,在左侧的Firebase控制台上 ,这次单击“ 存储” ,然后单击“入门”按钮以弹出此模式窗口:

您可以看到默认安全规则的内容-允许所有写入和读取,但必须经过身份验证。 因此,更改这段代码:

 允许读写:if request.auth!= null; 

为了即使未经身份验证也可以使用存储:

 允许读写:if request.auth == null; 

它绝对是反交互的,因此请确保这不是您为真实应用处理身份验证的方式!

使用Firebase实时数据库

Firebase Realtime Database实际上很容易工作。 在AppDelegate中配置Firebase连接之后,要做的第一件事是确保将Firebase导入有问题的VC中(显然是within)。 然后,建立与数据库的连接,或者用Firebase的话-通过首先定义属性来定义和创建对数据库的引用,如下所示:

  var ref:DatabaseReference! 

然后,在viewDidLoad方法中,实例化DatabaseReference到数据库的根目录:

  ref = Database.database()。reference() 

容易吧? 让我们将另一个独角兽记录添加到独角兽列表中。 那里是:

  ref.child(“ unicorns”)。child(“独角兽的某些唯一参考ID”)。setValue( 
[“ AddedBy”:“ Tony”,
“ imagePath”:“一些图像路径”,
“ seenAt”:“东京”]

此处要做的是访问数据库中的“ 独角兽 ”引用,然后访问独角兽的唯一引用,这就是为什么需要唯一ID的原因。 此处的唯一性有助于避免意外覆盖。 setValue方法用于设置新值。 是的,我一直在说“ 访问此内容的引用 ”,但这也意味着如果没有要访问的内容,则会创建该内容。 甜!

再一次,我为您提供了一个非常简单的示例。 要查看如何立即完成所有操作,请查看官方的Firebase实时数据库文档。

要注意的另一件事是在Firebase实时数据库中构造数据。 您可以像JSON树一样构造它, 因为其中的所有数据都存储为JSON对象! 有关如何执行此操作的最佳说明,请参见此处。

但是当前演示应用程序的结构将是什么样?

好吧,对于独角兽模型,有三个属性-addBy,imagePath,seedAt 。 因此,这是用于两个Unicorn对象列表的JSON对象的样子:

  { 
“独角兽”:{
“ unicorn1”:{
“ add byBy”:“ Peter”,
“ imagePath”:“一些图像路径”,
“ seenAt”:“伦敦”
},“ unicorn2”:{
“ add byBy”:“ John”,
“ imagePath”:“一些图像路径”,
“ seenAt”:“纽约”
}
}
}

使用Firebase存储

使用Firebase存储非常相似,也很容易。 一切都以引用属性开始:

  var storageRef:StorageReference! 

然后在viewDidLoad方法中,正确初始化根StorageReference

  storageRef = Storage.storage()。reference() 

storageRef可用于一整套操作-创建引用以上传,下载或删除文件等。请参阅官方文档,以检查所有可能的事情。 在演示项目中,我将展示如何处理图像的上传和下载。

好吧,让我们开始吧。 因为我真的很想专注于本文的Firebase部分,所以我在GitHub上创建了一个由独角兽上传的入门项目,其中包含了所有需要预先加载的内容。 因此,继续下载并取消存档。 确保您在master分支上,因为其中存在启动程序项目,而完成的项目位于已实现的分支下 。 另外,请确保您打开unicornUploader.xcworkspace- 它已经安装了所需的Cocoapods项目。

下一步要做的是继续进行,构建项目,然后花时间检查一下。 实际上,它非常简单,它只有两个嵌入在导航控制器中的视图控制器和一些特殊的类:

  • UnicornsTableViewController.swift —标准的UITableViewController实现,没有什么特别的,将填充所有已上传的独角兽的列表。
  • UploadUnicornViewController.swift —有目的地未完成的标准UIImagePickerController实现。 您可以单击按钮,但没有任何反应。 这也是用于将记录发送到Firebase实时数据库的地方
  • 在“ 模型” 文件夹中 ,有一个Unicorn.swift和Unicorn类。
  • Cells文件夹中 ,有一个UnicornTableViewCell.swift文件,其中包含UnicornsTableViewController.swift表视图中使用的单元格的自定义类。

独角兽模型

我已经向您展示了一种写入数据库的简单方法。 如果可以隐藏模型属性到JSON的转换怎么办? 他们可以并且向数据库写入可能是这样的:

  ref.child(“ unicorns”)。child(“独角兽的某些唯一参考ID”)。setValue(unicorn.toAnyObject()) 

官方文档说我们可以观察到这样的数据( 针对单个独角兽示例进行了调整 ):

  ref.observe(.value){(快照)在 
让unicorn = snapshot.value为? [String:AnyObject] [:]
// ...
}

如果也可以隐藏JSON到模型属性的转换怎么办? 调整独角兽模型后,可以执行以下操作,而不是执行以下操作:

  ref.observe(.value){(快照)在 
如果让unicorn = Unicorn(快照:快照为?DataSnapshot){
// ....}
}

为了实现以上两个目的,应将Unicorn模型更改为:

更新了Unicorn模型以处理数据库读写

UploadUnicornViewController类

要做的第一件事是获取实时数据库存储的引用。 将这两行放在picker属性之前:

  fileprivate var ref:DatabaseReference! 
fileprivate var storageRef:StorageReference!

然后在viewDidLoad方法中:

  ref = Database.database()。reference() 
storageRef = Storage.storage()。reference()

好吧,到目前为止,没有什么太复杂了! 尽管如此,在将新的独角兽记录添加到数据库之前,必须先将独角兽的图像上载到存储 。 如果需要,上传应允许轻松地将其取消。 无需在存储中占用不必要的文件空间! 因此,让我们使用一个StorageUploadTask变量并将其放在参考属性下面:

  fileprivate var storageUploadTask:StorageUploadTask! 

还需要一个名为storageImagePath的属性来跟踪Storage中的存储映像路径。

  fileprivate var storageImagePath =“” 

再次,还需要一个属性来帮助显示和隐藏网络活动指示器:

  fileprivate var showNetworkActivityIndi​​cator = false { 
didSet {
UIApplication.shared.isNetworkActivityIndi​​catorVisible = showNetworkActivityIndi​​cator
}
}

好的,终于可以使用存储了 ! 转到imagePickerController(_:didFinishPickingMediaWithInfo 🙂方法( UploadUnicornViewController扩展中的第一个方法),将其删除并将其替换为最终实现( 为澄清 起见 添加了注释 ):

imagePickerController(_:didFinishPickingMediaWithInfo :)方法的图像选择器控制器最终实现

我认为该实现非常简单-将图像挑选出来,将其转换为Firebase存储可以处理的适当图像数据,为其提供唯一的访问路径和适当的内容类型,然后上传。 之前的storageRef用于具有创建的唯一图像路径的自身上载-在此再次需要唯一性,以避免意外覆盖图像。 putData方法异步工作以启动上载,并且实际上返回分配给storageUploadTask属性的StorageUploadTask类型。 每个文档的StorageUploadTask类型 ,除了开始上传外,还可以用于暂停,继续和取消上传。 然后, putData方法的完成处理程序将返回错误或StorageMetadata对象,在这种情况下可以安全地忽略该对象,但它确实会通知成功。

将Unicorn图像上传到存储

最后,调用uploadSuccess(_ storagePath :, _ storageImage 🙂方法 里面看起来像这样:

将图像成功上传到Firebase存储时调用的方法

首先,将图像设置为unicornImageView ,更新storageImagePath属性并启用提交按钮( 我们在viewDidLoad方法中禁用了该按钮)。 这样就完成了演示所需的Firebase Storage上传。

接下来,将新的独角兽录制到Firebase实时数据库中 ,让我们首先为Submit按钮连接一个outlet方法。 我将其命名为didTapSubmit(_ sender 🙂 ,这是其中的代码:

在提交时记录新的独角兽

在这里,独角兽对象的其余属性将首先使用。 然后,将调用将处理写入数据库的函数并将其传递给新的unicorn实例。 这是内部的writeUnicornToDatabase(_ unicorn 🙂方法的外观:

用独角兽写数据库

如前所述,几乎是写入Firebase实时数据库的标准方式。 再一次,我使用与以前相同的策略来创建唯一引用—将独角兽属性连接到2001年1月1日UTC 00:00:00 UTC与当前日期和时间之间的时间间隔(作为整数)。

回到didTapSubmit(_ sender:UIButton)方法,最后要做的就是弹出VC,并在处理独角兽的新记录时回到初始VC。

将Unicorn记录添加到Firebase实时数据库

UnicornsTableViewController

这里的计划只是获取记录的独角兽并将其显示在表格中,而这一切都首先从获取数据库的引用属性开始:

  var ref:DatabaseReference! 

然后在viewDidLoad方法中:

  ref = Database.database()。reference() 

接下来要做的是使用数据库中的独角兽设置unicorns数组变量。 可以在viewWillAppear方法中完成 像这样:

更新独角兽数组

按照我们的初始设置,当执行这段代码时,每个表视图单元格也会更新其独角兽对象。 所以,是的,接下来要在UnicornTableViewCell中处理更多的事情。

UnicornTableViewCell

在这里, addBy和seenAt标签已经配置为在更新独角兽对象时进行更新。 剩下的就是用Firebase Storage中的正确图像设置unicornImageView图像

再说一次,这一切都从通常的Firebase存储设置开始-参考和任务( 这次 StorageDownload 类型 ):

  var storageRef:StorageReference! 
var storageDownloadTask:StorageDownloadTask!

接下来,以与viewDidLoad方法等效的方式初始化storageRef 但对于UITableViewCell类— awakeFromNib方法将其添加到prepareForReuse方法之前:

 覆盖func awakeFromNib(){ 
super.awakeFromNib()
storageRef = Storage.storage()。reference()
}

谈论prepareForReuse方法 —最好在此处添加这段代码,以免完成不必要的下载:

  storageDownloadTask.cancel() 

是的,我知道,尚未执行任何下载内容的尝试,更不用说取消它们了。 为此,我准备了一个名为downloadImage(from storageImagePath 🙂的不错的方法,该方法显然具有一个属性,并且是图像的路径。 将其放在最后一个TODO位置:didSet中从前离开的unicorn属性:

独角兽didSet最终实施

不用担心,我没有忘记,这是内部方法的外观,并附有相关注释以供澄清:

downloadImage方法实现

以及演示项目全部设定🎊。 让我们运行它!

结论

但是在此之前,请随时查看Firebase为我们(开发人员)提供的所有内容。 此外,如果您难以按照本文的要求完成,请在GitHub上浏览完成的项目。 谢谢你! 🙇