我在杭州折腾Xcode那点事:从跨平台到原生踩坑记
从Android转Flutter快两年了,最近要接iOS端SDK,领导让我顺手把iOS环境搭一下。记录踩坑过程,给跨平台转原生的兄弟避避坑。
环境搭建
Mac mini M2,系统Ventura。App Store装Xcode,15个G。装完先去Settings → Locations把Command Line Tools选上,否则终端里xcodebuild用不了,flutter doctor检测的就是这个。
建项目与SwiftUI
File → New → Project,选iOS App,语言Swift,界面SwiftUI。SwiftUI声明式UI跟Flutter思路很像,上手几乎没障碍。但@State和Flutter的setState生命周期完全不同。与UIKit混编时,UIViewRepresentable桥接层要小心内存泄漏。我栽在一个Coordinator没释放导致SDK回调重复触发的问题上,查了半天发现是闭包强引用了self。
证书签名
这是跨平台转iOS的第一道鬼门关。勾了“Automatically manage signing”,模拟器正常,真机报Failed to register bundle identifier。得先去Apple Developer后台建App ID,Bundle Identifier与Xcode完全一致,大小写都不能错。
流程:Keychain Access → Certificate Assistant → Request a Certificate,生成CSR上传后台,下载.cer双击安装。Provisioning Profile自动生成,但用了Push Notification等能力需手动配置Capabilities,Xcode同步不过来就重启——祖传bug。
资源文件处理
Build Phases里“Copy Bundle Resources”把模型文件拖进去,编译时复制到.app包。路径带空格或中文,Bundle.main.url(forResource:)可能返回nil且不报错,静默失败。我App直接崩溃在try!解包上。资源文件命名别用中文和空格,跨平台过来的人根本不知道。
真机调试
M2跑模拟器飞快。真机调试坑:iOS 17以上,首次连接要打开手机设置里的“Developer Mode”,否则报Failed to prepare device for development。我换了三根线,结果是没开开发者模式,错误信息误导性极强。
Swift最佳实践
// 别这样写,闭包强引用self导致内存泄漏
class SDKManager {
var callback: (() -> Void)?
func setup() {
callback = {
self.doSomething() // 强引用
}
}
}
// 用weak self
callback = { [weak self] in
self?.doSomething()
}
SwiftUI刷新跟Flutter有本质区别:Flutter整棵树diff,SwiftUI依赖追踪,只有@State或@Observable标记的属性变化才触发body重算。别把大对象塞进@State,用@StateObject或@Observable宏(Xcode 15以上支持)。
上架审核
截图别用模拟器截的,苹果对状态栏和刘海屏敏感;隐私清单(Privacy Manifest)2024年5月起强制,用了哪些API要声明,尤其UserDefaults,不声明直接拒;HTTP接口要在Info.plist加NSAllowsArbitraryLoads,但上架苹果会问理由,生产环境最好全上HTTPS。
总结
Xcode比Android Studio工程配置复杂度高一个量级。Android一个build.gradle解决的事,iOS要证书、Profile、Capabilities、Entitlements、Info.plist配合。但跑通后Apple工具链集成度高,Instruments比Android Profiler顺手。SwiftUI写感跟Flutter很像,一周能上手写业务。
对还在犹豫的Flutter开发者,建议:至少把证书签名和真机调试完整走一遍。不为别的,就为出问题时知道去哪改,而不是对着Code Signing Error干瞪眼。尤其端侧大模型火,Llama转CoreML跑在iPhone上已不新鲜,懂点Xcode的资源配置和模型加载,做端云协同架构设计时会有更完整的技术视角。

评论 0