适用于Objective C开发人员的30个Swift概念-扩展
因此,让我猜想,您曾经是iOS开发人员一段时间,或者自己是初级开发人员,与Objective-C一起工作,并且擅长于此,您不想在您的应用程序中使用其他任何东西,如果没有将代码放在方括号中,将无法想象您的生活。
如果是这种情况,则此博客文章适合您。 如您所知,Swift如今变得越来越受欢迎,招聘人员和公司都要求开发人员更加了解这种语言。
这是我在过去的采访中曾问过的一些主题与其他一些主题之间的简短混合,这将有助于使从Objective-C过渡到Swift的过程稍微容易一些。
1 —结构和类之间有什么区别?
结构和类之间最重要的区别之一是,结构是值类型,并且在代码中传递它们时总是被复制,而类是引用类型并通过引用传递。 而且,类具有继承,该继承使一个类可以继承另一个类的特征。
2 —值类型和引用类型之间有什么区别?
要扩展有关结构和类之间差异的答案,有必要了解值和引用类型之间的差异,
当您复制值类型时,它会将要复制的内容中的所有数据复制到新变量中。 它们是2个独立的事物,更改其中一项不会影响另一项。
复制引用类型时,新变量将指向与要复制的对象相同的内存位置。 这意味着更改一个将更改另一个,因为它们都引用相同的存储位置。
如果还不清楚,这是一个例子
3 —关键字“ mutating”在Swift中是什么意思?
我们无法在实现中直接更改值类型的值,只有在创建副本并将我们想要的值分配给新副本时,才有可能。 但是,如果要在实现中更改值类型,可以在函数声明之前使用“ mutating”关键字。它表示该方法将修改结构的值,从而允许编译器创建该结构的副本。
这是一个代码示例
4 —“静态”,“类”,“最终”关键字在Swift类型方法中意味着什么?
在类型方法中,这些关键字的意思是:
- static:在值类型(例如结构)中,此关键字表示方法在类型级别而不是在实例级别关联。 在引用类型中,这还意味着该方法在类的类型级别上关联,但也不允许该方法可为子类覆盖。
- class:在目标C中创建类方法的方式,它们可以被子类覆盖。
- final:它是方法中static的别名,但是您也可以在类声明之前使用它,以使其不可变。
对于类,通常总是使用“静态”来创建类型方法,只有在您的子类确实需要重写它时,才应使用“ class”关键字。
这是代码示例。
5 — Swift中的可选项是什么?
在许多语言中,当遇到数据缺失时,必须通过编写代码的另一条路径来处理它。 没有迹象表明数据不存在,因此在程序中的许多地方都必须编写防御性代码。 这不是Swift中的情况,可选类型是Apple处理应用程序中数据缺失的方式。
有关可选项的更多信息,请转到此处
6 — Swift中的let和var是什么?
在Swift中,var表示变量。 变量是可以更改或更改的对象。 另一方面,let表示常量,表示分配给对象的值永远不会更改。 设置完成后,就完成了。 当需要设置永远不变的值时,可以使用常量。
欲了解更多详情,请点击这里
7 — Swift中的元组是什么?
元组只是值的有序集合,出于我们的目的,它们将多个值分组为一个复合值。
为什么这很重要? 在Objective-C中,如果希望一种方法返回多个值,则有两个选择-返回一个自定义对象,该对象具有存储返回值的属性或将这些值粘贴在字典中。 但是,借助Swift,我们可以使用元组返回多个值。 元组中的值可以是任何类型,而不必彼此相同。
例如, ("Sasha", "Blumenfeld")
拥有一个人的名字和姓氏。 您可以使用点号( .
)加上值的索引来访问内部值:
var person =(“ Sasha”,“ Blumenfeld”)
var firstName = person.0 //萨沙
var lastName = person.1 // Blumenfeld
命名元素
您可以从元组中命名元素,并使用这些名称来引用它们。 元素名称是标识符,后跟冒号(:)。
var person =(名字:“ Sasha”,姓氏:“ Blumenfeld”)
var firstName = person.firstName //萨莎
var lastName = person.lastName // Blumenfeld
创建一个元组
您可以像其他任何变量或常量一样声明一个元组。 要初始化它,您将需要另一个元组或元组文字。 元组文字是一对用逗号分隔的值的列表。 如果将元组声明为变量,则可以使用点表示法来更改其值。
变量点=(0,0)
点0 = 10
点1 = 15
点//(10,15)
注意 :元组是值类型。 当您使用另一个元组初始化变量元组时,它实际上会创建一个副本。
var origin =(x:0,y:0)
变量点=原点
point.x = 3
point.y = 5
print(origin)//(0,0)
print(point)//(3,5)
有关元组的更多信息,请访问此链接
8-在Swift错误处理中,关键字try,catch,do,guard和throws关键字是什么意思?
如果您是Swift新手,您肯定会在不同的代码示例中看到这些关键字。 这些关键字负责处理应用程序中的错误。 这是一个很棒的话题,我建议您去阅读文档以了解它们,让我分享一些想法。
当您使用“ do”时,您是对代码说要在do语句内执行某些操作,这可能是不安全的。 如果实现可能引发错误,则可以使用“ try”方法,并且catch语句最终将捕获该错误(如果存在)。
Guard类似于可选绑定,但是带有一个外部变量,它以else子句结尾,您可以在其中处理错误。
抛出该错误,如果此方法的执行可能不安全,则在函数的返回类型之前添加此关键字。
我在这里为您附上了一些代码。
9-在Swift中,什么是计算属性?
除了存储的属性外,类,结构和枚举还可以定义计算的属性 ,而实际上并不存储值。 相反,它们提供了一个getter和一个可选的setter,以间接检索和设置其他属性和值。
这是一个详细的例子
10 —在Swift中,什么是可失败的并引发初始化程序?
初始化通常取决于外部数据,该数据可能存在也可能不存在,因为Swift提供了两种方法来处理此问题。
失败的初始化程序将返回nil,表示没有数据,然后让开发人员根据该数据在应用程序中“创建”不同的路径。
另一方面,抛出初始化器将在初始化时返回错误,而不是返回nil。
这是一个例子。
11 — Swift中的扩展是什么,如何使用?
如果您有使用Objective-C的经验,则可能会找到类似于类别的扩展。
在Swift中,您可以使用Extensions
向现有的类,结构和枚举类型添加新功能。 它们还用于提高可读性并使现有类型符合协议。
另外,扩展提供了协议的默认实现。
这是一个例子。
12 —在枚举中,原始值和相关值是什么?
原始值适用于枚举中的每种情况都由编译时设置值表示的情况。 类似于常量,即
let A = 0
let B = 1
类似于:
enum E: Int {
case A // if you don't specify, IntegerLiteralConvertible-based enums start at 0
case B
}
因此, A
在编译时设置的固定原始值为0
, B
为1
等。 它们都必须是同一类型(原始值的类型适用于整个枚举,而不是每种情况)。 它们只能是文字可转换的字符串,字符或数字。 它们都必须是不同的 (两个枚举不能具有相同的原始值)。
关联值更像变量,与枚举情况之一关联:
enum E {
case A(Int)
case B
case C(String)
}
在这里, A
现在具有一个关联的Int
,该Int
可以容纳任何整数值。 另一方面, B
没有关联值。 C
具有关联的String
。 关联类型可以是任何类型,而不仅仅是字符串或数字。
类型E
任何给定值将仅持有关联类型之一,即,如果枚举为A
,则为Int
如果枚举为A
,则为String
。 它仅需要足够的空间来容纳两者中的较大者。 像这样的类型有时称为“区分联合”(undiscriminated unions)-联合是可以容纳多种不同类型的变量,但是(从枚举的情况下)您知道它持有哪种类型。
它们甚至可以是通用的。 最常见的示例是Optional
,其定义如下:
enum Optional {
case .Some(T)
case .None
}
从Stackoverflow
13 —在Swift中,什么是类型别名?
Swift带有两个类型别名来表示非特定类型“ Any”和“ AnyObject”。
AnyObject代表任何类类型的实例,而Any是Swift中一种类型的最通用表示,它可以代表包括函数在内的任何类型的实例。
14 —在Swift中,什么是便捷初始化器?
指定的初始化程序是:
- 类的初始化的中心点。
- 班级必须至少有一个。
- 负责初始化存储的属性。
- 是负责调用super init的。
便利的初始化程序是:
- 次要的支持类的初始化器。
- 它只能调用在同一类中定义的指定初始化程序
- 它还可以调用在同一类中定义的另一个便捷初始化程序
- 它们不是必需的,这种暗示。 它们只是我们可以为便利用例编写的初始化程序
- 在课堂上,他们在init关键字之前使用关键字“ convenience”。
最后是类初始化的3条基本规则:
- 每个类都必须具有指定的初始化器,如果该类从另一个继承,则指定的初始化器负责调用其直接超类的指定初始化器。
- 类可以具有任意数量的便捷初始化程序,便捷初始化程序必须从同一类调用另一个初始化程序,无论它是指定的初始化程序还是其他便捷初始化程序。
- 便利的初始化程序必须最终调用指定的初始化程序。
这是一个代码示例
15 —在Swift中,“ required”关键字是什么意思?
有时,我们可能希望特定超类的所有子类都实现某个初始化程序。 通过在init方法中添加“ required”,我们表示所有子类都必须为此特定init方法提供一个实现。 同样,如果您在符合实现的类型时在协议中定义初始化方法,则该方法也将标记为必需的初始化方法。
16 —数组均匀性规则代表什么?
这意味着在Swift中,数组中的所有项目都必须具有相同的类型,以便保留此Swift将不同的子类强制转换为大括号类。
例如。
17 —在Swift中,什么是访问控制?
访问控制限制从其他源文件和模块中的代码访问部分代码。 使用此功能,您可以隐藏代码的实现细节,并指定可以访问和使用该代码的首选接口。
有5个访问级别:
- 开放.-是最高访问级别或最低限制访问级别。 您可以将标记为打开的类作为子类。
- Public。-在源文件中编写的开放式和公共启用代码,可在模块内的任何位置以及导入该模块的另一个模块中使用。 您可以使用标有Public的类,但不能对其进行子类化。
- 内部。-允许实体在其定义模块的任何源文件中使用,但不能在模块外部的任何源文件中使用。 这是默认的访问级别。
- Fileprivate。 —允许您限制实体在其定义的源文件中的使用。
- 专用。-是最严格的访问级别。 这意味着实体的使用仅限于封闭声明。 例如,私有存储的属性只能在其类内使用。
在编写框架或编写测试时,访问控制在两种特定情况下最有用。
最后,非常重要的一点是要知道您不能根据具有较低或更高限制访问级别的另一个实体来定义一个实体。
18 —什么时候应该使财产强而有弱?
默认情况下,对对象的任何引用都是强引用,以帮助克服可能出现的引用周期,ARC还允许“弱”引用,弱引用是一种不能完全保持其引用实例的引用。 并不会阻止ARC的使用。要使用它,我们将弱关键字添加到商店属性声明接口构建器出口中,默认情况下将其创建为弱存储属性,这是因为视图控制器维护对出口的引用,并且出口保持对视图控制器的引用。 所有带有弱引用的属性都必须是可选类型,并且根据定义必须是变量,以便可以将它们设置为nil。
这是一个代码示例。
19 —在闭包中“捕获自身”是什么意思,为什么会导致内存泄漏?
闭包是引用类型,它的实现依赖于捕获变量及其定义的上下文,当我们在闭包内使用self时,我们会对其保持强烈的引用,因此,它可能导致内存泄漏。
20 —推断键入在Swift中是什么意思?
这意味着,如果可以从目标C字中得知,则Swift语言会在编译时推断类型,区别在于在Objective-C中,您始终需要为此类属性提供类型。
NSString *名称= @“ Sasha Blumenfeld”
在Swift中,您只需像这样声明它,编译器就会推断出类型
让名字=“萨沙”
21 —什么是隐式展开的可选?
隐式解开的可选值是在后台正常使用的可选内容,但也可以像非可选值一样使用。由于使用时会自动解开隐式解开的可选值,因此无需使用! 操作员将其拆开。 就是说,如果您尝试使用值为nil的隐式展开的可选内容,则会出现运行时错误。 那么什么时候使用呢? …只有在可以保证变量在被调用时不会为零的情况下,才应将其标记为“隐式展开的可选”。
22 —铸造时,什么时候使用? vs as!
从派生类到基类的转换可以在编译时检查,并且永远不会失败。 但是,向下转换可能会失败,因为您无法始终确定特定的类别。 如果您有UIView,则可能是UITableView或UIButton。 如果您的垂头丧气选择正确的类型,那就太好了! 但是,如果您碰巧指定了错误的类型,则会遇到运行时错误,并且应用程序将崩溃。像可选的选项一样,最好使用as吗? 因为这样可以避免应用无法崩溃时应用崩溃。
23 —解开可选值的正确方法是什么?
解开可选值的最佳方法是通过可选绑定和/或使用保护语句,
使用哪一个取决于您的实现,if let将为您提供一个常量变量,您可以在if let花括号的范围内使用,guard语句将为您提供一个常量变量,您可以在它的范围之外使用保护括号,它将处理自己范围内的错误。
这是一个代码示例
24 —什么是可选链接?
使用可选值有时会感到有些笨拙,并且所有展开和检查工作都变得如此繁重,以至于您可能会想起一些感叹号来强制展开内容,因此可以继续工作。
Swift提供了可选的链接,它使您仅在可选具有值时才运行代码。 例如…
这是例子
25 —什么是财产观察员?
通过属性观察器,您可以在设置或将要设置任何值时执行一些代码。
在初始化期间不会调用它们,而是在可以将属性观察者添加到任何非延迟加载的存储属性之后。
他们像这样使用willSet和didSet关键字…
var值:Double = 0.0 {
//就在我们更改属性值之前
willSet {
打印(“旧值:\(值)”)
}
//在我们为存储的属性分配一个值之后,即被称为中间
didSet {
打印(“新值:\(值)”)
}
}
26 — Objective-C和Swift处理错误有什么区别?
Swift可以处理错误的自动和手动传播,而目标C则不能。 Objective-C仅通过手动传播来处理错误,首先检查结果是否为nil,如果为nil,则检查错误。
27 —弱者和无人者有什么区别,应该如何使用?
弱引用和无所有权引用使一个实例可以引用另一个实例而无需保持强大的控制力,从而避免了引用周期,当我们持有的另一个实例的生存期较短时(即当捕获的实例首先被释放,例如在Swift的委托中,或者如果您在oBjective C中看到它们,则应该告诉他们被标记为弱引用,这是因为在父对象仍然存在的情况下,委托可以被取消,总之换句话说,如果被保留的对象(即弱对象)的生存期短于(或可能具有更短的)生存期,则与使用弱对象的父对象相比。 另一方面,如果两个对象都具有相同的生存期,则使用无所有权,例如,当您将闭包声明为类中某个属性的值,并且在闭包内部捕获自身时,应为该闭包标记创建一个捕获列表,将其标记为无主,因为在这种情况下,没有类就不能存在闭包。
28 — @escaping关键字是什么意思?
在Swift 3中,默认情况下,闭包被标记为@noescape,有时完成处理程序必须用@escaping进行标记,因为它们在执行了封闭函数之后已经执行了一点。
如果将闭包作为参数传递给函数,并且在函数返回后调用该闭包,则闭包正在转义。 也有人说,闭包参数转义了函数体。
29 — Swift中的泛型是什么?
Swift语言提供了“通用”功能来编写灵活且可重用的函数和类型。 泛型用于避免重复并提供抽象。 Swift标准库是使用泛型代码构建的。 Swifts的“数组”和“字典”类型属于通用集合。 在数组和字典的帮助下,将数组定义为容纳“ Int”值和“ String”值或任何其他类型。
这是一个完整的例子。
30 —什么是面向协议的编程?
这是一个非常广泛的话题,我无法恢复。 相反,我想分享一些链接,这些链接将向您介绍面向协议的编程的功能。
这是我的代码示例。
55种Swift标准库协议教给我什么
在Swift 3中引入面向协议的编程
实用的面向协议的编程
最后一点……我并不是说您应该完全使用这种语言并掩盖您的目标C知识,绝对不能,仍然是像Facebook和Uber这样的最大公司(仅举几例)都是基于目标C的,如果您很幸运,有机会为他们工作,这些知识将非常有用,但是,如果您的目标是为一个想要建立未开发项目的年轻初创公司工作,那么他们很可能会在Swift上进行工作。
我希望您对这篇文章有所帮助,请记住,这些只是某些主题的“指针”,我的目的只是为每个主题做一个简短的介绍,以及一些可用作语法目的备忘单的代码示例以及一些链接拥有非常丰富的资源,还有更多,在以后的文章中,我将分享更多…
如果您可以分享您认为是初级开发人员“必知”的Swift主题,那就太好了!
和平!