面试的时候有问到,毕竟知道特性才能更好的驾驭这门语言,所以总结一下。暂时总结这么多,还有其他的后续再总结吧!
1.安全性和稳定性
- 例子:在 Swift 中,使用可选类型(Optionals)可以很好地处理可能为空的值。这样可以避免在运行时发生空指针异常。
// Swift 中的可选类型
var optionalName: String? = "John"
// 使用 if let 来处理可选值
if let name = optionalName {
print("Hello, \(name)")
} else {
print("Name is nil.")
}
2.简洁易读
- 例子:Swift 的闭包(Closures)语法相比 Objective-C 的块(Blocks)更加简洁和易读。
-
Swift 中的闭包
// Swift 中的闭包
let numbers = [1, 2, 3, 4, 5]
let squaredNumbers = numbers.map { $0 * $0 }
print(squaredNumbers) // Output: [1, 4, 9, 16, 25]
-
Objective-C 中的闭包(Blocks)
// Objective-C 中的闭包(Blocks)
NSArray *numbers = @[@1, @2, @3, @4, @5];
// 使用 Blocks 实现与 Swift 中的 map 类似的功能
NSArray *squaredNumbers = [numbers valueForKeyPath:@"@unionOfObjects.self"];
NSMutableArray *resultArray = [NSMutableArray arrayWithCapacity:squaredNumbers.count];
void (^squareBlock)(NSNumber *, NSUInteger, BOOL *) = ^(NSNumber *number, NSUInteger idx, BOOL *stop) {
NSInteger squaredValue = [number integerValue] * [number integerValue];
[resultArray addObject:@(squaredValue)];};
[numbers enumerateObjectsUsingBlock:squareBlock];
NSLog(@"%@", resultArray); // Output: [1, 4, 9, 16, 25]
3. 动态性能
例子:Swift 允许使用运行时反射来动态查找和操作类型信息,这提供了更多的灵活性
class Dog {
func bark() {
print("Woof!")
}
}
let className = "Dog"
if let classType = NSClassFromString(className) as? NSObject.Type {
let dog = classType.init() as? Dog
dog?.bark() // Output: "Woof!"
}
4. 互操作性 例子:Swift 可以轻松地与 Objective-C 代码进行交互,使得在现有的 Objective-C 项目中引入 Swift 变得容易。
// Swift 中与 Objective-C 交互
// Objective-C 声明
// Person.h 【举例说明,没有黏贴.m的实现】
@interface Person : NSObject
- (instancetype)initWithName:(NSString *)name;
- (NSString *)getName;
@end
// Swift 使用
let person = Person(name: "Bob")
print(person.getName()) // Output: "Bob"
5.类型推断
例子:Swift 的语法简洁,类型推断和错误检测加强,可以节省开发时间。
// Swift 中的类型推断
let age = 25 // Swift 可以自动推断 age 的类型为 Int
let greeting = "Hello, World!" // Swift 可以自动推断 greeting 的类型为 String
6.元组(Tuples)特性
例子:Swift 引入了元组(Tuples)特性,可以方便地返回多个值。
// Swift 中的元组
func getCoordinates() -> (Double, Double) {
let latitude = 40.7128
let longitude = -74.0060
return (latitude, longitude)
}
let (lat, lon) = getCoordinates()
print("Latitude: \(lat), Longitude: \(lon)") // Output: "Latitude: 40.7128, Longitude: -74.0060"
7.多重返回值(Multiple Return Values)
函数可以返回多个值,而不仅限于一个。
func getUserInfo() -> (name: String, age: Int) {
return ("John", 30)
}
let userInfo = getUserInfo()
print("Name: \(userInfo.name), Age: \(userInfo.age)") // Output: "Name: John, Age: 30"
8.泛型(Generics)
可以编写更通用、灵活的代码,适用于不同类型的数据。
// 泛型函数
func swapValues<T>(_ a: inout T, _ b: inout T) {
let temp = a
a = b
b = temp
}
var x = 10
var y = 20
swapValues(&x, &y)
print("x: \(x), y: \(y)") // Output: "x: 20, y: 10"
var str1 = "Hello"
var str2 = "World"
swapValues(&str1, &str2)
print("str1: \(str1), str2: \(str2)") // Output: "str1: World, str2: Hello"
9.扩展(Extensions)
可以在已有的类、结构体、枚举等类型中添加新的功能,无需修改原始代码。
// 扩展 String 类型
extension String {
func reversed() -> String {
return String(self.reversed())
}
}
let message = "Swift is awesome!"
let reversedMessage = message.reversed()
print(reversedMessage) // Output: "!emosewa si tfiwS"
10.协议扩展(Protocol Extensions)
可以为协议提供默认的实现,简化遵循协议的类的代码。
// 定义一个简单的协议
protocol Greeting {
func sayHello()
}
// 通过协议扩展为 sayHello 提供默认实现
extension Greeting {
func sayHello() {
print("Hello!")
}
}
// 实现 Greeting 协议的类可以选择重写 sayHello 方法
class Person: Greeting {
func sayHello() {
print("Hi!")
}
}
let person = Person()
person.sayHello() // Output: "Hi!"
11.错误处理(Error Handling)
使用 Swift 的错误处理机制可以更好地管理和处理可能发生的错误情况。
enum CustomError: Error {
case networkError
case fileNotFound
}
func processFile() throws {
// 模拟一个错误情况
throw CustomError.fileNotFound
}
do {
try processFile()
} catch CustomError.networkError {
print("Network error occurred.")
} catch CustomError.fileNotFound {
print("File not found.")
} catch {
print("Unknown error.")
}
12.可选链(Optional Chaining)
使用可选链可以在调用属性、方法或下标时检查是否存在值,避免了手动进行nil检查的繁琐过程。
class Person {
var address: Address?
}
class Address {
var street: String = "Main Street"
}
let person = Person()
// 使用可选链调用属性
if let street = person.address?.street {
print(street)
} else {
print("Address or street not available.")
}
13.函数式编程特性
Swift 支持函数式编程范式,包括高阶函数、map、filter、reduce 等,使得处理集合和序列变得更加简洁。
let numbers = [1, 2, 3, 4, 5]
// 使用 map 将数组中的每个元素进行平方
let squaredNumbers = numbers.map { $0 * $0 }
print(squaredNumbers) // Output: [1, 4, 9, 16, 25]
// 使用 reduce 计算数组中所有元素的和
let sum = numbers.reduce(0, +)
print(sum) // Output: 15
14.属性观察器(Property Observers)
可以在属性值即将被设置或已经被设置后执行自定义的代码。
class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
print("About to set totalSteps to \(newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
print("Added \(totalSteps - oldValue) steps.")
}
}
}
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 10 // Output: "About to set totalSteps to 10" and "Added 10 steps."
stepCounter.totalSteps = 20 // Output: "About to set totalSteps to 20" and "Added 10 steps."
15.Access Control(访问控制)
可以通过访问控制来限制模块中的代码访问,以增强代码的安全性和封装性。
// 示例中的一些代码访问级别
public class PublicClass {
// 可被其他模块访问
}
internal class InternalClass {
// 只能在当前模块内部访问
}
fileprivate class FilePrivateClass {
// 只能在当前文件内部访问
}
private class PrivateClass {
// 只能在当前类内部访问
}
16.Autoclosures(自动闭包)
可以推迟表达式的求值,直到需要时再进行求值,用于简化代码。
func printResult(_ getValue: @autoclosure () -> Int) {
print("Result: \(getValue())")
}
printResult(5 + 3) // Output: "Result: 8"
17. 嵌套类型(Nested Types)
在一个类或结构体中定义其他类、结构体或枚举,使得代码组织更清晰。
struct MathOperations {
enum OperationType {
case addition
case subtraction
case multiplication
case division
}
func performOperation(_ type: OperationType, _ a: Double, _ b: Double) -> Double {
switch type {
case .addition:
return a + b
case .subtraction:
return a - b
case .multiplication:
return a * b
case .division:
return a / b
}
}
}
let math = MathOperations()
let result = math.performOperation(.addition, 5, 3)
print(result) // Output: 8.0
18.类型别名(Type Aliases)
为现有的类型创建别名,增加代码的可读性。
typealias EmployeeID = Int
func getEmployeeName(employeeID: EmployeeID) -> String {
// 根据 employeeID 查询员工姓名
return "码农晨仔"
}
let id: EmployeeID = 101
let name = getEmployeeName(employeeID: id)
print(name) // Output: "John Doe"
19. 动态调用(Dynamic Dispatch)
Swift 支持动态调用方法,使得在运行时根据实际对象类型执行不同的方法。
class Animal {
func makeSound() {
print("Animal makes a sound.")
}
}
class Dog: Animal {
override func makeSound() {
print("Dog eat.")
}
}
class Cat: Animal {
override func makeSound() {
print("Cat eat.")
}
}
let dogAnimal: Animal = Dog()
let catAnimal: Animal = Cat()
dogAnimal.makeSound() // Output: "Dog eat."
catAnimal.makeSound() // Output: "Cat eat."
20. Codable 协议
Swift 引入 Codable 协议来简化模型对象的编码和解码操作。
struct Person: Codable {
var name: String
var age: Int
}
let person = Person(name: "John", age: 30)
// 编码为 JSON 数据
let encoder = JSONEncoder()
if let jsonData = try? encoder.encode(person) {
let jsonString = String(data: jsonData, encoding: .utf8)
print(jsonString!) // Output: {"name":"John","age":30}
}
// 解码 JSON 数据为对象
let jsonString = "{\"name\":\"Alice\",\"age\":25}"
let decoder = JSONDecoder()
if let jsonData = jsonString.data(using: .utf8), let decodedPerson = try? decoder.decode(Person.self, from: jsonData) {
print(decodedPerson) // Output: Person(name: "Alice", age: 25)
}
21.类型的高级操作符(Advanced Operator Overloading)
Swift 允许对运算符进行重载,并自定义类型的行为。
struct Vector2D {
var x: Double
var y: Double
}
// 重载加法运算符
func +(left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x + right.x, y: left.y + right.y)
}
let vector1 = Vector2D(x: 1.0, y: 2.0)
let vector2 = Vector2D(x: 3.0, y: 4.0)
let resultVector = vector1 + vector2
print(resultVector) // Output: Vector2D(x: 4.0, y: 6.0)
22. 自定义运算符(Custom Operators)
Swift 允许创建自定义的运算符,以适应特定的需求。
// 自定义一个名为 ∑ 的求和运算符
infix operator ∑: AdditionPrecedence
func ∑(values: [Int]) -> Int {
return values.reduce(0, +)
}
let numbers = [1, 2, 3, 4, 5]
let sum = numbers ∑
print(sum) // Output: 15
23.泛型 Where 子句(Generic Where Clauses)
在泛型代码中使用 where 子句可以增加类型约束条件,使泛型更加灵活。
func isEqual<T: Equatable>(_ a: T, _ b: T) -> Bool where T: Comparable {
return a == b
}
let result1 = isEqual(10, 10) // Output: true
let result2 = isEqual("hello", "world") // Output: false
24.模式匹配(Pattern Matching)
Swift 中的模式匹配使得代码能够更加简洁和灵活。
let value = 42
switch value {
case 0...9:
print("Single-digit number")
case 10...99:
print("Double-digit number")
case 100...999:
print("Triple-digit number")
default:
print("Larger number")
}
25. 内存访问控制(Memory Access Control)
Swift 5.5 引入了内存访问控制的改进,使得开发者可以更好地控制和优化内存使用。
// 通过 nonisolated 关键字标记异步函数,以避免隐式的任务执行
nonisolated func processData() async {
// 在这里执行异步操作
}
// 使用 actor 关键字定义一个 actor 类
actor MyActor {
var data: Int = 0
// 通过 isolated 关键字标记需要访问 actor 数据的函数
// isolated func updateData(_ value: Int) 不需要显示标记`isolated`
func updateData(_ value: Int) {
data = value
}
}
// 创建 MyActor 实例
let actorInstance = MyActor()
// 通过一个异步闭包调用 isolated 函数
Task {
await actorInstance.updateData(42)
}
-
异步函数: Swift引入了
async/await
关键字,支持异步编程。在代码中,processData()
函数被标记为async
,表示该函数是一个异步函数,可以执行异步操作,而不会阻塞当前线程。调用异步函数时,可以使用await
关键字来等待其结果。 -
非隔离函数(nonisolated):
nonisolated
关键字用于标记异步函数,表示该函数不会隐式地执行在某个任务中,而是可以直接在当前执行上下文中执行。这样做的目的是为了避免不经意地引入竞态条件和内存访问冲突。 -
Actor模型: Swift引入了
actor
关键字来支持Actor模型,用于解决并发编程中的资源竞争和数据访问问题。在代码中,MyActor
是一个定义了状态(var data
)和可以访问该状态的函数(isolated func updateData(_ value: Int)
)的Actor类。Actor内部的状态默认是线程安全的,只能通过标记为isolated
的函数来访问和修改。 -
异步闭包: 在代码中,通过
Task
来创建一个异步闭包,Task
允许我们在异步上下文中执行一组任务。在闭包中,使用await
关键字来调用actorInstance
的isolated
函数updateData(_:)
,以确保数据访问在Actor的隔离下进行,避免了多线程数据访问冲突。
26. 全局的 Actor(Global Actors)
Swift 5.5 引入了全局的 actor,使得特定的全局函数和属性可以在多线程环境下安全地访问。
// 创建一个全局 actor
@globalActor
actor MyGlobalActor {
static let shared = MyGlobalActor()
}
// 将函数标记为特定的全局 actor
@MyGlobalActor
func performTask() {
// 在这里执行任务
}
Task {
// 使用异步闭包调用函数,确保在 MyGlobalActor 中执行
await performTask()
}
27.异步序列(Async Sequences)
Swift 5.5 引入了异步序列,使得处理异步数据流变得更加简单和直观。
// 定义一个异步序列
func countUp() async -> any AsyncSequence {
let sequence = AsyncStream { continuation in
Task {
for i in 1...10 {
// 使用 yield 发送异步值
await continuation.yield(i)
}
// 使用 done 结束序列
continuation.finish()
}
}
return sequence
}
// 使用异步 for-in 循环处理异步序列
Task {
for try await number in await countUp() {
print(number)
}
}