iOS开发的可重用框架入门

编写iOS应用程序时,通常会导入FoundationUIKit框架,而对此一无所知。 如果要使用字符串,日期,文件系统或线程,则可以“导入Foundation”,而如果要使用UITableViewControllerUIAlertController ,则可以import UIKit 。 如果要导入UIKit则可以完全忘记Foundation ,因为UIKit是在后台进行的。

关键是这些框架定义了您可以在代码中访问的所有方法,函数和类。 如果您忘记import CoreBluetooth ,将很难连接到自定义的蓝牙设备。 更重要的是,如果您不import SpriteKit ,那么肯定会让独立SpriteKit游戏import SpriteKit

这些框架均由Apple构建。 它们可供开发人员使用,因此我们可以利用使iOS应用程序成功的技术。

但是什么是框架,为什么我们要使用它们呢?

框架是模块化的和可重用的代码集,用作高级软件的组成部分。

使用框架的最好理由是它们可以被构建一次,并且可以无限制地重复使用!

让我们再次看一下UIKitUIKit由Apple开发,并且会不断更新。 这是一个项目,开发人员可以重复使用它来构建新的应用程序。 我们可以使用它在我们的项目中定义出色的功能,例如动画,(UI)按钮,过渡和(UI)颜色。

我们知道苹果已经在iOS平台上广泛开发和使用了框架,但是我们呢?

创建框架是一个相对容易的任务,使用它们就像let greenColor = UIColor.black一样容易。 让我们开始制作自定义的Cocoa Touch框架!

我们将构建一个框架来模仿Apple多年来在iOS上一直使用的自定义状态警报。 我通常在“音乐”应用程序,“播客”应用程序和“新闻”应用程序中注意到它们。

这些自定义状态警报已经开始在各处弹出,但是Apple没有提供公共框架来利用它们!

总体而言,这些警报相对简单。 它们由一个UIVisualEffectView (with a blur) (作为背景),一个UIImage和一些文本组成。 创建一个框架来生成这些框架有多难? 实际上还不错!

入门

让我们打开Xcode并创建一个新项目。 选择iOS选项卡,向下滚动到Framework & Library然后选择Cocoa Touch Framework

我将其命名为“ AOModalStatus”,其中“ AO”代表我的姓名缩写。

您会在GitHub上注意到这种模式,人们可以在其中上载其框架,供其他开发人员社区充分利用。

苹果的框架也遵循两个字母的前缀。 考虑UIKit的UI和GLKit的GL; 前者代表用户界面,而后者则引用OpenGL(或OpenGL ES),而GLKit是基于OpenGL建立的。

对于本教程,选择Swift作为您的语言。 将项目保存到您想要的任何地方,然后开始吧!

首先创建一个新文件。 在Source ,选择Cocoa Touch Class ,然后从下拉列表中选择UIView 。 我将其命名为AOModalStatusView

让我们添加另一个文件。 这次在“ User Interface选择“ View并将其命名为AOModalStatusView.xib

XIB文件的行为很像情节提要,只是它是为单个视图而不是一组视图。

打开XIB文件并删除当前存在的视图。 在对象库中搜索Visual Effects View with BlurVisual Effects View with Blur并将其拖到XIB中。 在尺寸检查器中,从下拉列表中选择“ Alignment Rectangle ”,然后在宽度和高度中输入230个点。

现在,就像情节提要一样,我们将向视图添加一些对象,这些对象将包含我们的自定义“ AOModalStatusView”。

将一个Image View和两个Label拖动到视觉效果视图中,并将其放置为:

我将图像的宽度和高度设置为130点。 图像水平居中,距视觉效果视图顶部10个点。 第一个标签位于其下方20点的位置,第二个标签位于仅低5点的位置。 两个标签都具有前导和尾随约束,以使其到达视图的每一侧。 对于第二个标签,将“属性”检查器中的“ Lines选项设置为2,因为它是一个子标题,可能占用多行。

那是一口气,但是一旦设置了约束,最困难的部分就完成了!

由于XIB是文件中的单个视图,因此应将类分配给“文件的所有者”部分。 故事板包含多个视图,因此我们在此处不做相同的事情。

在XIB的文档大纲中选择File's Owner (1)。 转到身份检查器(2)并将“ Class部分分配给AOModalStatusView (3)。

现在我们准备开始将XIB与代码混合!

我们将从为视图中最重要的对象,图像和两个标签制作一些出口开始。 选择助手编辑器,以便您可以同时查看.xib和.swift文件。

像这样添加一个基本类:

  AOModalStatusView类:UIView { 
}

就像在情节提要中一样,按住Control并单击并拖动几分钟前我们创建的类中的每个元素。 它看起来应该像这样:

如果添加插座时遇到问题,请构建项目(command + B),然后重试。 如果这样不起作用,请确保将File Owner's类设置为“ AOModalStatusView”,而不是视图的类。

现在,我们可以回到标准编辑器,并略微忽略XIB文件。 打开AOModalStatusView.swift。

由于我们将创建公共功能来编辑这些属性,因此我们希望隐藏对原始出口的访问。 对于每个网点,在关键字weak之前添加关键字private ,例如:

接下来,在网点后添加以下代码:

  //标记:设置Viewpublic重写init(frame:CGRect){ 
//用于代码
super.init(frame:框架)
setUpView()
}
公用必需的init?(编码器aDecoder:NSCoder){
//用于Interface Builder
super.init(编码器:aDecoder)
setUpView()
}

这两个初始化程序是Xcode在创建新的AOModalStatusView时所使用的初始化AOModalStatusView 。 第一个可以直接从代码运行,而第二个可以在Interface Builder中工作。

您可能已经注意到setUpView()函数引起了麻烦……主要是因为我们尚未创建它。

但是在添加func setUpView()我们需要添加一些支持变量。 将以下内容添加到网点正下方的课程中。

 让nibName =“ AOModalStatusView” 
var contentView:UIView!

现在我们准备将setUpView()添加到文件中。 在我们编写的最后一个初始化程序之后添加以下代码。

 私人功能setUpView(){ 
let bundle = Bundle(for:type(of:self))
让笔尖= UINib(nibName:self.nibName,bundle:bundle)
self.contentView = nib.instantiate(withOwner:self,选项:nil)。 UIView
addSubview(contentView)

contentView.center = self.center
contentView.autoresizingMask = []
contentView.translatesAutoresizingMaskIntoConstraints = true

headlineLabel.text =“”
subheadLabel.text =“”
}

这里发生了很多事情,所以我会尽快解决它! 首先,我们需要将变量contentView设置为我们创建的XIB文件内部的视图。 这是通过访问该框架的捆绑包,NIB(引用已编译的XIB)以及NIB内部的视图来完成的。

接下来,我们想使用addSubview(contentView)刚刚创建的contentView添加到此类的视图中。

然后,我们将contentView的框架设置为等于该类中父视图的边界。 此后,我们要告诉我们,我们不批准任何调整大小的操作,因为该视图具有特定的大小。 这就是为什么我们将autoresizingMask传递给一个空数组的原因。

最后,我们希望将标签设置为在其中包含空文本,以便我们的框架是完全可定制的。

AOModalStatusView.swift将关键字public添加到类的开头,以便以后可以直接引用它。

我们的框架几乎完成了! 建立和使用我们的框架之前的最后一件事。 还记得我们如何将网点标记为私人吗? 添加这三个功能,以便框架的用户可以从其代码中设置图像和标签出口。

  //提供更新视图的功能 
公共功能集(图片:UIImage){
self.statusImage.image =图片
}
公共功能集(标题文本:字符串){
self.headlineLabel.text =文字
}
公共功能集(子标题文本:字符串){
self.subheadLabel.text =文字
}

瞧! 我们有一个框架,花了很长时间才将它们放在一起! 但是它本身并不能做很多事情,所以让我们测试一下吧!

我们将创建一个新项目来测试框架。 我认为,互联网上有很多猫,但肯定可以使用更多的小狗! 我将模拟一个快速的小狗照片应用程序。 我们称之为“小狗天堂”!

可以从我的GitHub下载Puppy Paradise的起点。

继续并在Xcode中打开starter项目。

入门

转到项目检查器的“常规”选项卡,然后向下滚动到显示“嵌入式二进制文件”的位置。单击+按钮,然后单击“ Add Other 。 Finder窗口将下拉,在这里您需要选择我们之前创建的AOModalStatus.xcodeproj框架。 您会注意到,我们的框架已添加到项目导航器中!

现在返回嵌入式二进制文件,然后再次单击+按钮。 这次您将看到我们添加的框架! 单击它以将其添加到项目的“嵌入式二进制文件”。

给项目一个快速构建(命令+ B),以确保到目前为止一切顺利! 现在应该没有任何错误。

现在我们有了自己的框架,我们需要确保Xcode确实在引用它,然后才能开始对其进行编码。 跳转到ViewController.swift文件,并在import UIKit下方import UIKit import AOModalStatus

ViewController.swift具有用户在查看图片时单击“保存”时执行的操作。 在saveTapped(_:)函数内部添加presentModalStatusView() 。 现在,我们将presentModalStatusView()函数添加到该类中,以便编译器presentModalStatusView()会我们。

  func presentModalStatusView(){ 
让modalView = AOModalStatusView(frame:self.view.bounds)
让downloadImage = UIImage(named:“ download”)?? UIImage()
modalView.set(图片:downloadImage)
modalView.set(标题:“正在下载”)
view.addSubview(modalView)
}

这里发生了几件事。 首先,我们初始化了一个AOModalStatusView并将其命名为modalView 。 然后,我们使用资产中存储的“ download.png”图像创建了一个UIImage 。 然后,将图像和一些文本设置到视图,并将其作为子视图添加到ViewController

在模拟器上生成并运行该应用程序,然后尝试保存照片! 而且有效! 除此以外,似乎在某些方面缺乏。 例如,我们无法关闭它。 也没有圆角。 最重要的是,Apple使用微妙的动画来显示和删除其模式状态视图。

好吧,事实证明,这些实现起来并不难! 由于我们导入了框架的项目而不是已编译的框架,因此我们可以对其进行更改,并且每次构建PuppyParadise时Xcode都会对其进行编译。

计时器

点击框架项目旁边的下拉菜单,然后导航到我们之前创建的AOModalStatusView.swift文件。 第一步是使视图在给定的几秒钟后关闭。

添加var timer: Timer?contentView变量的声明之后。 然后添加以下代码:

 公共重写func didMoveToSuperview(){ 
//添加计时器以删除视图
self.timer = Timer.scheduledTimer(
timeInterval:TimeInterval(3.0),
目标:自我,
选择器:#selector(self.removeSelf),
userInfo:无,
重复:false)
}
@objc私人功能removeSelf(){
self.removeFromSuperview()
}

这是一些简单的代码,“经过三秒钟后,请摆脱该视图。”

圆角

接下来是圆角,这将大大降低AOModalStatusView的清晰度。 也将以下代码添加到该类中:

  //允许视图自行控制 
公共重写func layoutSubviews(){
//圆角
self.layoutIfNeeded()
self.contentView.layer.masksToBounds = true
self.contentView.clipsToBounds = true
self.contentView.layer.cornerRadius = 10
}

这是可用于创建圆角的典型代码。 要提到的重要部分是,这是在子视图(AKA contentView )布局后发生的,并且我们将clipsToBounds设置为true ,因此contentView包含的子视图不能从圆角后面滑出。

现在运行吧! 当我们去保存可爱的小狗照片时,它会在几秒钟后消失,并且我们有圆角。

现在要做的一件事情就是使其真正成为“流行音乐”。让我们添加一些动画。

动画

可以理解,很多人都害怕在Swift中使用动画,但是我将向您展示如何做得如此简单和有效,以至于您可能会在此之后查阅动画教程!

用以下内容替换didMoveToSuperviewremoveSelf函数:

 公共重写func didMoveToSuperview(){ 
//加入超级视图时淡入
//然后添加计时器以删除视图
self.contentView.transform = CGAffineTransform(scaleX:0.5,y:0.5)
UIView.animate(withDuration:0.15,动画:{
self.contentView.alpha = 1.0
self.contentView.transform = CGAffineTransform.identity
}){_ in
self.timer = Timer.scheduledTimer(
timeInterval:TimeInterval(3.0),
目标:自我,
选择器:#selector(self.removeSelf),
userInfo:无,
重复:false)
}
}
@objc私人功能removeSelf(){
//动画移除视图
UIView.animate(
withDuration:0.15,
动画:{
self.contentView.transform = CGAffineTransform(scaleX:0.5,y:0.5)
self.contentView.alpha = 0.0
}){_ in
self.removeFromSuperview()
}
}

然后将contentView.alpha = 0.0添加到setUpView

这里发生的事情并不那么复杂。 在didMoveToSuperview我们将contentView转换为其宽度和高度的一半。 然后,我们使用UIView.animate(withDuration)运行动画。 在其中,我们将动画设置为CGAffineTransform.identity ,这是一种奇特的说法,即“它通常看起来如何(又不是其大小的一半)。”我们还将动画中的alpha值设置回1.0。 这告诉contentView在动画期间淡入时从其一半的大小开始增长。 动画结束后,我们设置最初立即创建的计时器。

removeSelf我们做相反的事情。 在动画过程中,我们希望Alpha值回落到0.0(或透明),并希望变换使其再次使contentView变为其通常大小的一半。 动画完成后,我们可以完全摆脱该视图。

我想指出的是,所有这些代码都发生在框架内部,当我们在项目中使用它时,我们仍然只需要几行通用代码。

现在运行该项目,然后尝试“保存”该照片。 现在,您应该有一个工作框架和项目来测试该框架。 不仅如此,您可以在另一个项目中重用此框架,甚至可以将代码推送到GitHub,以供其他人开始使用!

您可以从Github下载Puppy Paradise和AOModalStatusView的最终版本!

怎么样了 要使它继续下去可能要付出很多努力,但是每次您编写一个新框架时,它只会变得越来越快!

我想在下面阅读您的评论! 有很多方法可以编写框架,因此请告知您是否做过一些不同的事情。 您也可以在Twitter上通过@_alecoconnor与我联系。

感谢您的阅读,并祝您编程愉快!