guard语句 #

一、guard语句概述 #

guard语句是Swift的一种控制流语句,用于在条件不满足时提前退出当前作用域。与if语句不同,guard语句强调"提前退出"的逻辑。

1.1 基本语法 #

swift
guard condition else {
    return
}

1.2 与if语句的区别 #

swift
func processIf(value: Int?) {
    if let unwrapped = value {
        print("值是: \(unwrapped)")
    } else {
        print("值为空")
        return
    }
}

func processGuard(value: Int?) {
    guard let unwrapped = value else {
        print("值为空")
        return
    }
    print("值是: \(unwrapped)")
}

二、guard let可选绑定 #

2.1 基本用法 #

swift
func greet(name: String?) {
    guard let unwrappedName = name else {
        print("没有名字")
        return
    }
    print("你好, \(unwrappedName)!")
}

greet(name: "张三")
greet(name: nil)

2.2 多个可选绑定 #

swift
func process(firstName: String?, lastName: String?) {
    guard let first = firstName, let last = lastName else {
        print("名字不完整")
        return
    }
    print("全名: \(first)\(last)")
}

process(firstName: "张", lastName: "三")
process(firstName: "张", lastName: nil)

2.3 附加条件 #

swift
func validate(age: Int?) {
    guard let unwrappedAge = age, unwrappedAge >= 18 else {
        print("年龄无效或未成年")
        return
    }
    print("成年人,年龄: \(unwrappedAge)")
}

validate(age: 25)
validate(age: 15)
validate(age: nil)

三、guard条件表达式 #

3.1 布尔条件 #

swift
func access(user: User) {
    guard user.isLoggedIn else {
        print("请先登录")
        return
    }
    print("欢迎访问")
}

3.2 多条件组合 #

swift
func transfer(amount: Double, balance: Double) {
    guard amount > 0, amount <= balance else {
        print("转账金额无效")
        return
    }
    print("转账成功")
}

3.3 复杂条件 #

swift
func processOrder(items: [Item], user: User) {
    guard !items.isEmpty,
          user.isLoggedIn,
          user.hasPaymentMethod else {
        print("无法处理订单")
        return
    }
    print("处理订单...")
}

四、guard与函数返回 #

4.1 返回值 #

swift
func divide(_ a: Int, by b: Int) -> Int? {
    guard b != 0 else {
        return nil
    }
    return a / b
}

if let result = divide(10, by: 2) {
    print(result)
}

4.2 抛出错误 #

swift
enum ValidationError: Error {
    case emptyInput
    case invalidFormat
}

func validate(email: String?) throws -> String {
    guard let email = email, !email.isEmpty else {
        throw ValidationError.emptyInput
    }
    
    guard email.contains("@") else {
        throw ValidationError.invalidFormat
    }
    
    return email
}

do {
    let validEmail = try validate(email: "test@example.com")
    print(validEmail)
} catch {
    print(error)
}

4.3 提前返回多个值 #

swift
func parseCoordinates(_ input: String?) -> (x: Double, y: Double)? {
    guard let input = input else { return nil }
    
    let parts = input.split(separator: ",")
    guard parts.count == 2,
          let x = Double(parts[0]),
          let y = Double(parts[1]) else {
        return nil
    }
    
    return (x, y)
}

if let coords = parseCoordinates("10.5,20.3") {
    print("x: \(coords.x), y: \(coords.y)")
}

五、guard在循环中 #

5.1 遍历时验证 #

swift
let items: [String?] = ["A", nil, "B", nil, "C"]

for item in items {
    guard let item = item else {
        continue
    }
    print(item)
}

5.2 处理集合 #

swift
func processItems(_ items: [Item]) {
    guard !items.isEmpty else {
        print("没有项目")
        return
    }
    
    for item in items {
        guard item.isValid else { continue }
        print("处理: \(item.name)")
    }
}

六、实际应用 #

6.1 API响应处理 #

swift
struct UserResponse: Decodable {
    let id: Int
    let name: String
    let email: String
}

func handleResponse(data: Data?) {
    guard let data = data else {
        print("无数据")
        return
    }
    
    guard let user = try? JSONDecoder().decode(UserResponse.self, from: data) else {
        print("解析失败")
        return
    }
    
    guard !user.name.isEmpty else {
        print("名字为空")
        return
    }
    
    print("用户: \(user.name), 邮箱: \(user.email)")
}

6.2 表单验证 #

swift
struct FormData {
    var username: String?
    var email: String?
    var password: String?
    var confirmPassword: String?
}

func validateForm(_ data: FormData) -> Bool {
    guard let username = data.username, !username.isEmpty else {
        print("用户名不能为空")
        return false
    }
    
    guard username.count >= 3 else {
        print("用户名至少3个字符")
        return false
    }
    
    guard let email = data.email, email.contains("@") else {
        print("邮箱格式不正确")
        return false
    }
    
    guard let password = data.password, password.count >= 8 else {
        print("密码至少8个字符")
        return false
    }
    
    guard let confirmPassword = data.confirmPassword,
          password == confirmPassword else {
        print("两次密码不一致")
        return false
    }
    
    return true
}

6.3 权限检查 #

swift
struct User {
    var id: Int
    var name: String
    var role: Role
    var isActive: Bool
}

enum Role {
    case admin
    case editor
    case viewer
}

func canEdit(user: User?, resource: Resource?) -> Bool {
    guard let user = user else {
        print("用户未登录")
        return false
    }
    
    guard user.isActive else {
        print("用户已禁用")
        return false
    }
    
    guard let resource = resource else {
        print("资源不存在")
        return false
    }
    
    guard user.role == .admin || user.role == .editor else {
        print("权限不足")
        return false
    }
    
    return true
}

6.4 网络请求 #

swift
func fetchUser(id: Int, completion: @escaping (Result<User, Error>) -> Void) {
    guard id > 0 else {
        completion(.failure(NSError(domain: "InvalidID", code: -1)))
        return
    }
    
    guard isConnected() else {
        completion(.failure(NSError(domain: "NoConnection", code: -2)))
        return
    }
    
    guard let url = URL(string: "https://api.example.com/users/\(id)") else {
        completion(.failure(NSError(domain: "InvalidURL", code: -3)))
        return
    }
    
    URLSession.shared.dataTask(with: url) { data, response, error in
        guard let data = data, error == nil else {
            completion(.failure(error!))
            return
        }
        
        guard let user = try? JSONDecoder().decode(User.self, from: data) else {
            completion(.failure(NSError(domain: "DecodeError", code: -4)))
            return
        }
        
        completion(.success(user))
    }.resume()
}

七、guard vs if let #

7.1 可读性对比 #

swift
func processIfLet(value: Int?) {
    if let unwrapped = value {
        if unwrapped > 0 {
            if unwrapped < 100 {
                print("有效值: \(unwrapped)")
            } else {
                print("值太大")
            }
        } else {
            print("值太小")
        }
    } else {
        print("值为空")
    }
}

func processGuard(value: Int?) {
    guard let unwrapped = value else {
        print("值为空")
        return
    }
    
    guard unwrapped > 0 else {
        print("值太小")
        return
    }
    
    guard unwrapped < 100 else {
        print("值太大")
        return
    }
    
    print("有效值: \(unwrapped)")
}

7.2 变量作用域 #

swift
func ifLetScope(value: Int?) {
    if let unwrapped = value {
        print(unwrapped)
    }
}

func guardScope(value: Int?) {
    guard let unwrapped = value else {
        return
    }
    print(unwrapped)
}

八、最佳实践 #

8.1 提前返回 #

swift
func process(data: [String: Any]?) -> User? {
    guard let data = data else { return nil }
    guard let id = data["id"] as? Int else { return nil }
    guard let name = data["name"] as? String else { return nil }
    
    return User(id: id, name: name)
}

8.2 链式guard #

swift
func validate(input: String?) -> Bool {
    guard let input = input,
          !input.isEmpty,
          input.count >= 3,
          input.count <= 20 else {
        return false
    }
    return true
}

8.3 有意义的错误信息 #

swift
func process(user: User?) throws {
    guard let user = user else {
        throw ProcessingError.userNotFound
    }
    
    guard user.isActive else {
        throw ProcessingError.userInactive
    }
    
    guard user.hasPermission else {
        throw ProcessingError.permissionDenied
    }
    
    print("处理用户: \(user.name)")
}

九、总结 #

本章学习了Swift的guard语句:

  • guard let:可选绑定并提前退出
  • guard条件:条件验证并提前退出
  • 作用域优势:解包后的值在外部可用
  • 代码可读性:减少嵌套层次

最佳实践:

  • 使用guard提前处理错误情况
  • 避免深层嵌套
  • guard后变量在外部可用
  • 提供有意义的错误信息

下一章,我们将学习集合类型!

最后更新:2026-03-26