1.Swift和Objective-C的联系
- Swift与Objective-C共用同一套运行时环境
我们编写程序,让程序运行起来,被机器执行的代码并非全部是由我们自己来编写的。需要同时运行很多预先写好的支持性的代码,才能让我们自己的代码运行起来。- Swift跟Objective-C编译出的程序代码运行在同一套运行环境上面。Swift的类型可以桥接到Objective-C的类型,反之亦然。Swift编写的代码可以调用Objective-C编写的代码,反之也一样。
Objective-C之前积累下来的大量类库,实现不用改写Swift就可以直接调用。- 同一个工程,可以同时使用Swift和Objective-C
Objective-C在一端,Swift在另一端,两端经中间文件进行桥接。桥接文件包含Objective-C的头文件,编译时自动转成Swift可以识别的形式。Swift就可以使用Objective-C的类和它的函数。
在Swift的类中,加上@objc(类名)
的字样,Objective-C也可以使用Swift编写的类。但Swift跟C++的相互调用,需要Objective-C来封装。- Swift骨子里大多与Objective-C一样
Objective-C出现过的绝大多数概念,比如引用记数、ARC、属性、协议、接口、初始化、扩展类、命名参数、匿名函数等,在Swift中继续有效(可能只是换了个术语)。- Swift大多数概念与Objective-C一样,也有些概念在Objective-C找不到对应,比如泛型。Swift中将那种操作写一次就可以作用多个类型的语法叫做Generics(泛型)。
2.Swift比Objective-C有什么优势?
- Swift 容易阅读
不再需要行尾的分号,以及if/else
语句中围绕条件表达式的括弧。另外就是方法的调用不再互相嵌套成中括号[[[ ]]]
。Swift 中的方法和函数的调用使用行业内标准的在一对括弧
内使用逗号分隔的参数列表。这样做的结果就是一种带有简化了句法和语法的更加干净有表现力的语言。- Swift 更易于维护
Swift 丢掉了对应两个文件的要求。 Xcode编译器可以自动计算出以来并执行增量构建。如此,将头文件 同实现文件相分离。把 Objective-C 头文件(.h)
和实现文件(.m)
合并成了一个代码文件(.swift)
- Swift 更加安全
Swift代码中的可选类型使得一个nil可选值的可能性变得非常的明确, 这意味它能在你写下一段糟糕的代码时会生成一个编译器错误. 这就建立了一种短程反馈的循环,可以让程序员带着目标去写代码. 问题在代码被写就时就可以被修复, 这大大节省了你要在修复有关来自 Objective-C 指针逻辑的bug时需要耗费的时间和金钱.- Swift 代码更少
Swift 减少了重复性语句和字符串操作所需要的代码量。在 Objective-C 中, 使用文本字符串将两块信息组合起来的操作非常繁琐。Swift 采用当代编程语言的特性,比如使用“+”
操作符将两个字符串加到一起。
Swift中的类型系统减少了代码语句的复杂性--作为编译器可以理解的类型。比如,Objective-C要求程序员记住特殊字符标记(%s,%d,%@)
并且提供了一个用逗号分隔的变量来代替每个标记。Swift支持字符串插入,这就消除了需要记住的标记和允许程序员直接插入变量到面向用户的字符串中- Swift 速度更快
删除遗留下来的C语言约定大大提升了引擎盖之下Swift的性能, 进行计算密集型任务的性能上,Swift已经逼近C++的表现, 将近是OC运行速度的1.4倍.- 总结: 使用 Swift,程序员只要维护原来一半量的代码文件,手动的代码同步工作为零,标点输入出错的概率也远远低于以前 -- 这样就能腾出更多的时间写高质量的代码。通过使用可选类型 —— 一种针对返回或不返回值的编译时安全机制,而返回值是同步操作、网络失效时无效的用户输入以及数据验证错误发生时普遍会遇到的问题。ARC 在 Swift 中对过程式 C 风格的代码,还有苹果公司 Cocoa 框架使用的面向对象代码都进行了统一。
3.Swift的内存管理是怎样的?
- Swift 使用自动引用计数(Automatic Reference Counting, ARC)来简化内存管理, 这种内存管理方式相比GC而言,对程序员的要求较高, 并且ARC比GC更容易引起编程错误,但却比GC快。尤其在性能很重要的场合。
4.Swift支持面向过程编程吗?
- 它采用了 Objective-C 的命名参数以及动态对象模型,可以无缝对接到现有的 Cocoa 框架,并且可以兼容 Objective-C 代码,支持面向过程编程和面向对象编程。
5.举例说明Swift里面有哪些是 Objective-C中没有的?
- Swift引入了在Objective-C中没有的一些高级数据类型,例如tuples(元组),可以使你创建和传递一组数值。
- Swift还引入了可选项类型(Optionals),用于处理变量值不存在的情况。可选项的意思有两种:一是变量是存在的,例如等于X,二是变量值根本不存在。Optionals类似于Objective-C中指向nil的指针,但是适用于所有的数据类型,而非仅仅局限于类,Optionals 相比于Objective-C中nil指针更加安全和简明,并且也是Swift诸多最强大功能的核心。
6.Swift 是一门安全语言吗?
- Swift是一门类型安全的语言,Optionals就是代表。Swift能帮助你在类型安全的环境下工作,如果你的代码中需要使用String类型,Swift的安全机制能阻止你错误的将Int值传递过来,这使你在开发阶段就能及时发现并修正问题。
7.为什么要在变量类型后面加个问号?
- 用来标记这个变量的值是可选的,一般用“!”和“?”定义可选变量的区别:用“!”定的可选变量必须保证转换能够成功,否则报错,但定义的变量可以直接使用,不会封装在option里;而用“?”号定的可选变量即使转换不成功本身也不会出错,变量值为nil,如果转换成功,要使用该变量进行计算时变量名后需要加“!”
8.什么是泛型,它们又解决了什么问题?
- 泛型是用来使代码能安全工作。在Swift中,泛型可以在函数数据类型和普通数据类型中使用,例如类、结构体或枚举。
- 泛型解决了代码复用的问题。有一种常见的情况,你有一个方法,需要一个类型的参数,你为了适应另一种类型的参数还得重新再写一遍这个方法。
比如,在下面的代码中,第二个方法是第一个方法的“克隆体”:
这段代码能达到了目的,但是编译的时候并不安全。它允许一个字符串和一个整型数据进行比较:
9. Swift 中定义常量和 Objective-C 中定义常量有什么区别?
一般人会觉得没有差别,因为写出来好像也确实没差别。
OC是这样定义常量的: const int number = 0;
Swift 是这样定义常量的:let number = 0
首先第一个区别,OC中用const
来表示常量,而 Swift 中用let
来判断是不是常量。
上面的区别更进一步说,OC中const
表明的常量类型和数值是在 compilation time 时确定的;而 Swift 中let
只是表明常量(只能赋值一次),其类型和值既可以是静态的,也可以是一个动态的计算方法,它们在 runtime 时确定的。
10. Swift 中 struct 和 class 什么区别?举个应用中的实例
struct 是值类型,class 是引用类型。
看过WWDC的人都知道,struct
是苹果推荐的,原因在于它在小数据模型传递和拷贝时比class
要更安全,在多线程和网络请求时尤其好用。
我们来看一个简单的例子:
class A {
var val = 1
}
var a = A()
var b = a
b.val = 2
此时 a 的 val 也被改成了 2,因为 a 和 b 都是引用类型,本质上它们指向同一内存。
解决这个问题的方法就是使用 struct:
struct A {
var val = 1
}
var a = A()
var b = a
b.val = 2
此时 A 是struct,值类型,b 和 a 是不同的东西,改变 b 对于 a 没有影响。
小结:
- class是引用类型,struct则是值类型
- class允许一个类继承另一个类的特征
- 类型转换允许在运行时检查和解释一个类实例的类型
11. Swift 到底是面向对象还是函数式的编程语言?
Swift 既是面向对象的,又是函数式的编程语言。
说 Swift 是 Object-oriented(面向对象),是因为 Swift 支持类的封装、继承、和多态,从这点上来看与 Java 这类纯面向对象的语言几乎毫无差别。说 Swift 是函数式编程语言,是因为 Swift 支持 map, reduce, filter, flatmap 这类去除中间状态、数学函数式的方法,更加强调运算结果而不是中间过程。
12.不通过继承,代码复用(共享)的方式有哪些
- 为 class/struct/enum 添加extension
- protocol + extension
13.集合(Set) 独有的方法有哪些?
集合(Set)用来存储相同类型并且没有确定顺序的值。
集合(Set)类型取交集、并集、差集、补集这些数学中常用集合方法是独有的
14. map、filter、reduce 的用法
WHAT Map,Filter,Reduce是什么?
map:
对数组中的每一个元素执行函数操作,并返回一个新的数组。filter:
筛选数组中满足传入函数的元素,并返回新数组。reduce:
传入一个初值,再传入一个函数,初值和数组中每一个元素都会被传入函数计算结果,最终返回一个值。
WHY 为什么要使用Map,Filter,Reduce?
- 方便:代码量极少,节省时间
- 简洁:符合Swift语言风格,当你使用map,filter,reduct的代码质量会更好。但也需要在合适的场景中使用它们,不要指望用它们来解决任何问题。没有放之四海而皆准的真理。
- 效率:数据比较大的时候,高阶函数会比传统实现更快,因为它可以并行执行(如运行在多核上),除非真的需要更高定制版本的map,reduce和filter,否则可以一直使用它们以获得更快的执行速度。
HOW 怎么使用?
- 例(map):将示例数组,每个数字都加10,获得一个新的数组。
//采用闭包的方式
var result = numberArray.map({($0) + 10})
print(result)
- 例(FlatMap):找出数组中大于2的数
filteredArray = numberArray.filter({$0 > 2})
print(filteredArray)
- 例(reduce):计算数组中所有数字的和,积
sum = numberArray.reduce(0, combine: {$0 + $1})
print(sum)
15.if let/guard let 使用场景
- guard语句来要求条件必须为真时,以执行guard语句后的代码。
- guard守护有值,和if let相反 ,逻辑代码少降低分支的层次, 通常判断后有值就直接做逻辑处理
- if let 使用它解决Optional对象解包时产生空对象的处理
16.defer常用与需要配对出现的代码,比如文件的打开与关闭,加锁与解锁
- defer常用与需要配对出现的代码,比如文件的打开与关闭,加锁与解锁.
- 对应OC中是黑魔法之一
__attribute__(cleanup(...))
。
17.String 与 NSString 的关系与区别
- String是结构体,NSString是类,这是它们的根本区别。
- Swift 中,结构体struct是值类型,String是结构体,所以也是值类型;
- 类class是引用类型,NSString是类,所以也是引用类型.
18.throws 和 rethrows 的用法与区别
- 1、throw异常,这表示这个函数可能会抛出异常。不管作为參数的闭包是否抛出异常
- 2、rethrow异常,这表示这个函数本身不会抛出异常,但假设作为參数的闭包抛出了异常。那么它会把异常继续抛上去。比如
func map<T>(@noescape transform: (Generator.Element) throws -> T) rethrows -> [T]
19.try、try?、和 try!是什么意思?
- try 出现异常处理异常
- try? 不处理异常,返回一个可选值类型,出现异常返回nil
- try! 不让异常继续传播,一旦出现异常程序停止,类似NSAssert()
20. 什么时候使用 final
- final关键字在大多数的编程语言中都存在,表示不允许对其修饰的内容进行继承或者重新操作。Swift中,final关键字可以在class、func和var前修饰。所以,当确定这个类、函数是最终实现(类不被继承,属性方法不被override)时候使用final保证代码安全。
- 具体情况如下:
(1)类或者方法的功能确实已经完备了
这种通常是一些辅助性质的工具类或者方法,特别那种只包含类方法而没有实例方法的类。比如MD5加密类这种,算法都十分固定,我们基本不会再继承和重写。
(2)避免子类继承和修改造成危险
有些方法如果被子类继承重写会造成破坏性的后果,导致无法正常工作,则需要将其标为final加以保护。
(3)为了让父类中某些代码一定会执行
父类的方法如果想要其中一些关键代码在继承重写后仍必须执行(比如状态配置、认证等)。我们可以把父类的方法定义成final,同时将内部可以继承的部分剥离出来,供子类继承重写。
下面通过一段代码演示:
class Parent {
final func method1() {
//权限验证(必须执行)
//.....
method2()
//下面是日志记录(必须执行)
//..........
}
func method2(){
//父类的实现
//......
}
}
class Child : Parent {
//只能重写父类的method2方法,不能重写method1方法
override func method2() {
//子类的实现
//......
}
}
21.open 、 public 、fileprivate 、 private 的区别
- (1) private 只允许在当前类中调用,不包括 Extension
private 现在变为了真正的私有访问控制
用 private 修饰的方法不可以被代码域之外的地方访问- (2) fileprivate 其修饰的属性或者方法只能在当前的 Swift 源文件里可以访问。 即在同一个文件中,所有的 fileprivate 方法属性都是可以访问到的。
- (3) public 修饰的属性或者方法可以在其他作用域被访问
但不能在重载 override 中被访问 ,也不能在继承方法中的 Extension 中被访问.- (4) open 修饰的属性或者方法可以在其他作用域被访问 ,修饰的属性或者方法可以在其他作用域被继承或重载 override
从高到低排序如下:open > public > fileprivate > private
22.dynamic framework 和 static framework 的区别是什么
- 动态库文件名后缀:.dylib和.framework; 静态库文件名后缀:.a和.framework
- 静态库:链接时,静态库会被完整地复制到可执行文件中,被多次使用就有多份冗余拷贝
- 系统动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存
23. Swift 中定义常量和 Objective-C 中定义常量有什么区别?
- 一般人会觉得没有差别,因为写出来好像也确实没差别。
- OC是这样定义常量的:
const int number = 0
- Swift 是这样定义常量的:
let number = 0
- 首先第一个区别,OC中用 const 来表示常量,而 Swift 中用 let 来判断是不是常量。
上面的区别更进一步说,OC中 const 表明的常量类型和数值是在编译时(compilation time)
确定的;而 Swift 中let
只是表明常量(只能赋值一次),其类型和值既可以是静态的,也可以是一个动态的计算方法,它们在runtime
时确定的。
本文转载于其它网站,仅供学习使用!