自定义CocoaPods集成IBDesignable时遇架构不兼容渲染错误
首次开发自定义CocoaPods组件,附带示例工程,组件运行正常。为支持代码与Storyboard两种初始化方式,引入@IBDesignable和@IBInspectable以在视图中修改属性,但出现以下错误:
file:///Users/belalmedhat/Desktop/SwipeySearch/Example/SwipeySearch/Base.lproj/Main.storyboard: error: IB Designables: Failed to render and update auto layout status for ViewController (vXZ-lx-hvc): dlopen(SwipeySearch.framework, 0x0001): tried: '/Applications/Xcode Rosetta.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Overlays/SwipeySearch.framework/SwipeySearch' (no such file), '/Applications/Xcode Rosetta.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/SwipeySearch.framework/SwipeySearch' (no such file), '/Applications/Xcode Rosetta.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRootSwipeySearch.framework' (no such file), 'SwipeySearch.framework' (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64')), '/System/Library/Frameworks/SwipeySearch.framework/SwipeySearch' (no such file)
搜索视图代码如下:
@IBDesignable public class SwipeySearchClass: UIView { @IBOutlet var contentView: UIView! @IBOutlet weak public var searchView: UIView! @IBOutlet weak public var searchButton: UIButton! @IBInspectable public var cornerRadius: CGFloat = 0 { didSet { contentView.layer.cornerRadius = cornerRadius contentView.layer.masksToBounds = cornerRadius > 0 } } @IBInspectable public var borderWidth: CGFloat = 0 { didSet { contentView.layer.borderWidth = borderWidth } } @IBInspectable public var borderColor: UIColor? { didSet { contentView.layer.borderColor = borderColor?.cgColor } } /* // Only override draw() if you perform custom drawing. // An empty implementation adversely affects performance during animation. override func draw(_ rect: CGRect) { // Drawing code } */ public override init(frame: CGRect) { super.init(frame: frame) initMe() } public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) initMe() } public override func prepareForInterfaceBuilder() { super.prepareForInterfaceBuilder() initMe() } public override func awakeFromNib() { super.awakeFromNib() initMe() } private func initMe(){ let bundle = Bundle(for: SwipeySearchClass.self) let view = UINib(nibName: "SwipeySearchView", bundle: bundle).instantiate(withOwner: self, options: nil).first as! UIView view.frame = self.bounds view.autoresizingMask = [.flexibleWidth,.flexibleHeight] addSubview(view) } public func buttonShape(type:SearchShape) { searchButton.clipsToBounds = true switch type { case .circle: searchButton.layer.cornerRadius = searchButton.frame.width/2 break case .roundedSquare(let corner): searchButton.layer.cornerRadius = corner break } } } public enum SearchShape { case circle case roundedSquare(corner:CGFloat) }
1. 修复架构不兼容问题
错误核心提示mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64'),说明Interface Builder需要arm64架构的框架,但当前编译产物不匹配:
- 打开组件工程,在Build Settings中找到
Architectures,确保包含arm64; - 示例工程同步检查
Architectures,在Excluded Architectures中,针对模拟器SDK移除不必要的架构限制,避免仅编译x86_64; - 若使用Rosetta模式运行Xcode(路径显示为Xcode Rosetta.app),右键Xcode图标→显示简介→取消勾选“使用Rosetta打开”,重启Xcode后重新编译组件和示例工程。
2. 修正IBDesignable资源加载路径
Interface Builder渲染时,组件资源的加载逻辑与运行时不同,需确保Bundle路径正确:
修改initMe()方法中的Bundle获取逻辑:
private func initMe(){ var bundle = Bundle(for: SwipeySearchClass.self) // 适配CocoaPods组件的资源Bundle路径 if let resourceBundleURL = bundle.url(forResource: "SwipeySearch", withExtension: "bundle") { bundle = Bundle(url: resourceBundleURL)! } let view = UINib(nibName: "SwipeySearchView", bundle: bundle).instantiate(withOwner: self, options: nil).first as! UIView view.frame = self.bounds view.autoresizingMask = [.flexibleWidth,.flexibleHeight] addSubview(view) }
同时在Podspec文件中添加资源打包配置,确保Xib文件被正确打包:
s.resource_bundles = { 'SwipeySearch' => ['SwipeySearch/Assets/*.xib'] }
替换路径为实际存放Xib的目录。
3. 避免重复初始化视图
当前代码中init(frame:)、init?(coder:)、prepareForInterfaceBuilder()、awakeFromNib()均调用initMe(),会导致多次添加子视图,引发渲染异常:
- 移除
prepareForInterfaceBuilder()中的initMe()调用,仅在该方法中同步IBInspectable属性; - 移除
awakeFromNib()中的initMe()调用,因为init?(coder:)已完成初始化。
修改后的初始化代码:
public override init(frame: CGRect) { super.init(frame: frame) initMe() } public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) initMe() } public override func prepareForInterfaceBuilder() { super.prepareForInterfaceBuilder() // 同步IB属性到视图,无需重复初始化 contentView.layer.cornerRadius = cornerRadius contentView.layer.masksToBounds = cornerRadius > 0 contentView.layer.borderWidth = borderWidth contentView.layer.borderColor = borderColor?.cgColor } public override func awakeFromNib() { super.awakeFromNib() // 此处可添加运行时专属逻辑,无需重复初始化 }
4. 清理缓存重新编译
- 执行
pod deintegrate && pod install清理并重新安装Pods; - 按下
Cmd+Shift+K清理构建文件夹,再按Cmd+Option+Shift+K清理Derived Data; - 重启Xcode,重新编译组件和示例工程,最后刷新Storyboard(Editor→Refresh All Views)。
内容的提问来源于stack exchange,提问作者belal medhat

