一、UIKit 自动布局:用代码驯服不同屏幕尺寸

在 iOS 开发中,自动布局就像是个智能管家,帮我们搞定各种屏幕尺寸的适配问题。想象一下,你设计了一个漂亮的登录界面,在 iPhone 13 上看着很完美,结果到了 iPhone SE 上按钮都挤成一团了,这多尴尬啊!

来看看用代码实现自动布局的典型场景。假设我们要做一个居中显示的圆形头像:

// UIKit 自动布局示例(技术栈:UIKit + NSLayoutConstraint)
let avatarImageView = UIImageView()
avatarImageView.image = UIImage(named: "user_avatar")
avatarImageView.contentMode = .scaleAspectFill
avatarImageView.layer.cornerRadius = 50  // 圆形效果
avatarImageView.clipsToBounds = true
view.addSubview(avatarImageView)

// 禁用自动生成的约束
avatarImageView.translatesAutoresizingMaskIntoConstraints = false

// 开始添加自定义约束
NSLayoutConstraint.activate([
    // 水平居中
    avatarImageView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
    // 垂直方向距离顶部100点
    avatarImageView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100),
    // 固定宽度100点
    avatarImageView.widthAnchor.constraint(equalToConstant: 100),
    // 固定高度100点(保持正方形)
    avatarImageView.heightAnchor.constraint(equalToConstant: 100)
])

这种方式的优点是精确控制每个视图的位置和大小,但缺点也很明显——代码量有点大。所以苹果后来推出了更简洁的 VFL(Visual Format Language),不过现在更推荐使用上面这种锚点(Anchor)的方式。

二、SwiftUI 跨平台适配:一次编写,多端运行

SwiftUI 就像是个神奇的变形金刚,写一套代码就能在 iPhone、iPad 甚至 Mac 上运行。不过这个变形金刚有时候也需要我们给它一些指导,才能在不同设备上表现得体。

来看个实际例子,我们要创建一个在 iPhone 和 iPad 上表现不同的导航界面:

// SwiftUI 跨平台适配示例(技术栈:SwiftUI)
struct ContentView: View {
    var body: some View {
        NavigationView {
            // 主视图
            SidebarView()
            
            // 默认详情视图(iPad上会并排显示)
            Text("请选择内容")
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .background(Color(.systemBackground))
        }
        // 针对不同设备的适配
        .navigationViewStyle(
            // 在iPhone上使用堆叠样式
            UIDevice.current.userInterfaceIdiom == .phone ? 
                .stack : .automatic
        )
    }
}

struct SidebarView: View {
    var body: some View {
        List {
            // 使用sizeClass判断屏幕尺寸
            if UIDevice.current.userInterfaceIdiom == .pad {
                Text("大屏幕专属功能")
                    .font(.headline)
                    .padding(.vertical, 8)
            }
            
            ForEach(1..<10) { i in
                NavigationLink("项目 \(i)") {
                    DetailView(item: i)
                }
            }
        }
        .listStyle(.sidebar)
    }
}

SwiftUI 的跨平台能力确实强大,但要注意:

  1. 某些组件在不同平台的表现可能不同
  2. 功能可用性要检查(比如Mac上可能没有某些iOS特有的传感器)
  3. 要善用 @Environment 属性来获取设备特征

三、Core Data 数据存储:本地数据库的瑞士军刀

Core Data 不是简单的数据库,更像是苹果生态中的数据管理大师。它能处理对象关系、数据版本迁移、甚至云端同步。

来看个完整的 CRUD 操作示例:

// Core Data 示例(技术栈:CoreData + SwiftUI)
struct UserListView: View {
    @Environment(\.managedObjectContext) private var viewContext
    
    // 获取所有用户数据
    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \User.name, ascending: true)],
        animation: .default)
    private var users: FetchedResults<User>
    
    var body: some View {
        List {
            ForEach(users) { user in
                Text(user.name ?? "未知用户")
            }
            .onDelete(perform: deleteUsers)
        }
        .toolbar {
            Button(action: addUser) {
                Label("添加用户", systemImage: "plus")
            }
        }
    }
    
    // 添加新用户
    private func addUser() {
        withAnimation {
            let newUser = User(context: viewContext)
            newUser.id = UUID()
            newUser.name = "用户\(Int.random(in: 1000...9999))"
            newUser.joinDate = Date()
            
            do {
                try viewContext.save()
            } catch {
                let nsError = error as NSError
                fatalError("保存错误:\(nsError), \(nsError.userInfo)")
            }
        }
    }
    
    // 删除用户
    private func deleteUsers(offsets: IndexSet) {
        withAnimation {
            offsets.map { users[$0] }.forEach(viewContext.delete)
            
            do {
                try viewContext.save()
            } catch {
                let nsError = error as NSError
                fatalError("删除错误:\(nsError), \(nsError.userInfo)")
            }
        }
    }
}

Core Data 的强大之处在于:

  • 自动处理对象关系
  • 支持数据版本迁移
  • 与 SwiftUI 深度集成
  • 可搭配 iCloud 实现云端同步

但也要注意:

  1. 多线程操作要使用正确的 context
  2. 大数据量时要考虑批处理
  3. 复杂查询可能需要创建合适的索引

四、实战经验与技巧分享

在实际项目中,我们经常会遇到一些特殊场景。比如在 UIKit 和 SwiftUI 混编时怎么处理布局?Core Data 如何优化性能?

UIKit 与 SwiftUI 混编技巧

// UIKit 中使用 SwiftUI 视图(技术栈:UIKit + SwiftUI)
func embedSwiftUIView() {
    let hostingController = UIHostingController(rootView: SwiftUIView())
    addChild(hostingController)
    view.addSubview(hostingController.view)
    
    hostingController.view.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        hostingController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        hostingController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
        hostingController.view.topAnchor.constraint(equalTo: view.topAnchor),
        hostingController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor)
    ])
    
    hostingController.didMove(toParent: self)
}

// SwiftUI 中使用 UIKit 视图(技术栈:SwiftUI + UIKit)
struct UIKitRepresentedView: UIViewRepresentable {
    func makeUIView(context: Context) -> some UIView {
        let label = UILabel()
        label.text = "来自UIKit的问候"
        label.textAlignment = .center
        return label
    }
    
    func updateUIView(_ uiView: UIViewType, context: Context) {
        // 更新视图
    }
}

Core Data 性能优化

对于大数据集,我们应该:

  1. 使用批处理获取数据
  2. 考虑使用 NSFetchedResultsController
  3. 合理设置 fetchLimit 和 fetchBatchSize
// 批量获取优化示例
let fetchRequest: NSFetchRequest<User> = User.fetchRequest()
fetchRequest.fetchLimit = 20  // 每次只获取20条
fetchRequest.fetchBatchSize = 10  // 预取10条
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "joinDate", ascending: false)]

do {
    let users = try context.fetch(fetchRequest)
    // 处理数据...
} catch {
    print("获取失败: \(error)")
}

五、技术选型与总结

在实际项目中如何选择这些技术?

  1. UIKit 自动布局

    • 适合需要精确控制布局的场景
    • 适合维护已有项目
    • 适合需要支持旧版iOS的项目
  2. SwiftUI

    • 适合新项目开发
    • 需要支持多苹果平台的场景
    • 追求开发效率的项目
  3. Core Data

    • 需要复杂数据关系的场景
    • 需要iCloud同步功能
    • 苹果生态专属应用

最终建议

  • 新项目优先考虑 SwiftUI + Core Data 组合
  • 复杂界面可以考虑 SwiftUI 与 UIKit 混编
  • 性能关键部分仍可能需要 UIKit 的精细控制
  • 数据存储根据团队熟悉程度,也可以考虑 Realm 等第三方方案

记住,没有完美的技术,只有适合特定场景的技术组合。在实际开发中,要根据项目需求、团队熟悉度和时间预算做出合理选择。