普通视图

发现新文章,点击刷新页面。
昨天以前首页

iOS引入Masonry库编译报错libarclite_iphonesimulator.a

2025年6月28日 16:47

背景

引入Masonry编译报错如下:

File not found: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphonesimulator.a

Linker command failed with exit code 1 (use -v to see invocation)

这是非常常见的问题,自我第一次使用Masonry库就有这个错误。但是觉得很奇怪,Masonry作为一个广泛使用的成熟库,为什么引入还会报错,这也太low了吧?

今天建立新项目,引入Masonry库,又报错,接二连三的遇到该问题让我开始正视了这个问题。

解决方案

方案1 临时方案:

xcworkspace工程中选择Pods工程,Targets下选择Masonry库,将minimum deployments最新部署版本升级至 >= 9.0即可。 image.png

方案2 推荐方案:

方案1 缺点:直接修改Pods工程中的配置并不是最佳方案,因为当你下次执行 pod updatepod install 时,这些更改可能会被覆盖。如果你确实需要对某- 使用 post_install hook:可以在你的 Podfile 中添加脚本,在安装或更新 Pods 后自动修改某些 Targets 的设置。些 Pod 进行自定义配置,推荐的做法是:

修改Podfile文件,对Masonry库的最低部署版本进行设置。

post_install do |installer|
  installer.pods_project.targets.each do |target|
    if target.name == 'Masonry'
      target.build_configurations.each do |config|
        config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0'
      end
    end
  end
end

为什么引入Masonry编译会报错

File not found: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphonesimulator.a

这个错误的核心含义是:

找不到 ARC(Automatic Reference Counting)支持库 libarclite_iphonesimulator.a

而通过将 Masonry Pod 的 Deployment Target 从 iOS 8.0 改为 iOS 11.0 后,问题解决了。

为什么会出现 libarclite_iphonesimulator.a 找不到?

  • 这个文件是 Apple 提供的一个静态库,用于模拟器环境下支持 ARC(自动内存管理)
  • 它只在某些旧版本的 iOS 部署目标下才会被链接进来(通常是 iOS 8~9)。
  • 从 iOS 9.0 起,ARC 已经成为默认行为,不再需要手动链接这个库。
  • Xcode 从某个版本开始(尤其是 Xcode 12+),已经移除了对 libarclite_iphonesimulator.a 的支持,所以如果你仍然试图链接它,就会报错。

❓ 为什么是 Masonry 导致这个问题?

Masonry 本身是 Objective-C 编写的库,并且它的 .podspec 文件里可能指定了较低的 deployment target(如 iOS 8.0)。这会导致 CocoaPods 在生成 Pod Target 时:

  • 自动添加 -fobjc-arc 标志;
  • 并尝试链接 libarclite_iphonesimulator.a 来兼容非 ARC 环境;
  • 但由于你的 Xcode 已经不包含该库,就导致了链接失败。

✅ 为什么改到 iOS 11.0 就好了?

这样会:

  • 不再要求链接 libarclite_iphonesimulator.a
  • 让编译器知道这是一个现代的、默认启用 ARC 的环境;
  • 因此不会触发这个已废弃的链接行为。

🧪 补充说明:libarclite 是什么?

  • libarclite 是 Apple 为了向后兼容,在早期 iOS 版本上支持 ARC 的“过渡性”库。
  • 当你在 iOS 5~8 上开发 Objective-C 项目时,如果项目或某些文件未启用 ARC,Xcode 会自动链接这个库来启用局部 ARC。
  • 但自从 iOS 9 之后,Apple 强制所有 App 必须使用 ARC,因此这个库就被淘汰了。

最终建议

  • 保持 Pod 的最低部署目标与主工程一致
  • 避免使用低于 iOS 10.0 的 deployment target(除非你有特殊需求);
  • 使用 post_install 统一管理 Pod 的构建设置;
  • 如果你使用 Swift 和 Objective-C 混合编程,更应统一构建配置以避免冲突。

为什么Masonry不提高最低部署版本?

既然有错误,那为什么Masonry库不把最低版本8.0升级呢? Masonry 库维持较低的 iOS 部署目标(如 iOS 8.0)主要是为了最大化兼容性,使得尽可能多的项目能够使用该库,包括那些需要支持旧版 iOS 系统的应用。然而,这种做法有时会导致与最新版本的 Xcode 或其他工具链不完全兼容的问题,就像我遇到的情况一样。

维持低部署目标的原因

  1. 广泛兼容性: 许多开发者可能仍在维护和支持需要运行在较老版本 iOS 上的应用程序。通过保持较低的最低部署目标,Masonry 可以确保这些应用可以无缝集成 Masonry 而无需升级其操作系统支持。
  2. 社区需求: 如果大部分用户仍然需要支持 iOS 8.0 或更高版本但低于最新版本的操作系统,那么提高最低部署目标可能会导致部分用户无法使用更新版本的库。
  3. 稳定性考虑: 对于一个成熟且功能稳定的库来说,频繁更改最低部署目标可能导致不必要的回归测试和潜在问题,特别是对于那些依赖于特定版本行为的应用。

记录App切后台时AppIcon变成默认雪花icon问题

2025年6月28日 12:46

xcode做新项目时,设置了app图标。发现点击app进入前台时,App Icon是正常的,但是回到桌面时App Icon又变成了默认的雪花图标。

之前也遇到过,但是不求甚解,在此列出解决方案。

问题1: AppIcon的设置

随便设置了个图片为app图标,编译报错xxx/Assets.xcassets: The stickers icon set or app icon set named "AppIcon" did not have any applicable content. 同时appIcon可视化窗口显示黄色⚠️图标。

Xcode 提示你在 Assets.xcassets 中名为 "AppIcon" 的 App 图标集合里没有提供任何有效的图片资源。

iOS 应用要求必须有完整的 AppIcon 集合,并且要包含适用于各种设备和分辨率的图标尺寸。如果没有正确设置这些图标,App 就无法通过 App Store 审核,甚至可能在某些模拟器或真机上运行异常。

我使用了makeappicon.com/ 生成appIcon图标。 网站生成的结果包含AppIcon.appiconset,直接把AppIcon.appiconset替换原项目中Assets中的appIcon即可。 image.png 结果如下 image.png

问题2: 切后台appIcon变成默认雪花icon

现在成功设置appIcon后,切后台时发现appIcon变成了默认的雪花icon。

原因是系统缓存了旧图标,iOS 系统有时会缓存应用的图标缩略图,尤其是多任务界面中的预览图。即使你更新了图标,也可能不会立即刷新。

解决办法: 卸载重装

现在能正常显示了

image.png

UINavigationController 导航控制器

2025年6月27日 00:12

之前有一次设置了self.window.rootViewController = newViewController。但是没有把newViewController放入UINavigationController导航栈,结果一直跳转不了页面。浪费了很多时间。

UINavigationController导航控制器

UINavigationController,它用来管理视图控制器的层次结构,并提供导航栏(NavigationBar)来帮助用户在不同的视图控制器之间进行导航。通过这种方式,可以方便地实现页面之间的前进和后退操作。

使用UINavigationController

创建 UINavigationController

通常情况下,你会将一个视图控制器设置为根视图控制器(root view controller),然后把这个视图控制器传给 UINavigationController 的初始化方法。


       let viewController = ViewController()
        
        // 将它嵌入到导航控制器中
        let navController = UINavigationController(rootViewController: viewController)
        
        // 创建一个 UIWindow 实例,指定其 windowScene,并将导航控制器设置为其根视图控制器
        self.window = UIWindow(windowScene: windowScene)
        self.window?.rootViewController = navController
        self.window?.makeKeyAndVisible()

推送新视图控制器 页面导航

要从当前视图控制器导航到另一个视图控制器,你可以使用 pushViewController(_:animated:) 方法。

let nextViewController = NextViewController()
navigationController?.pushViewController(nextViewController, animated: true)

返回上一个视图控制器: 可以通过 popViewController(animated:) 方法返回到前一个视图控制器,或者使用 popToRootViewControllerAnimated(_:) 返回到根视图控制器。

Tab Bar Controller与Navigation Controller的2种组合方式

每个Tab包含一个Navigation Controller

这是最常见的方式,每个标签页都有自己的 UINavigationController 作为其根视图控制器。这样,每个标签都可以独立地处理自己的导航流程。

  • 创建多个 UINavigationController 实例,每个实例都包含一个不同的根视图控制器。
  • 将这些 UINavigationController 实例添加到 UITabBarController 的 viewControllers 属性中。
let tabBarController = UITabBarController()

let firstNavController = UINavigationController(rootViewController: FirstViewController())
let secondNavController = UINavigationController(rootViewController: SecondViewController())

tabBarController.viewControllers = [firstNavController, secondNavController]

单一Navigation Controller用于所有Tabs

这种方式不太常见,因为每个标签页共享同一个导航栈可能会导致用户体验不佳。不过,在某些特定场景下,这种模式也可能是合适的。

  • 在这种情况下,你首先需要创建一个 UINavigationController,然后将 UITabBarController 设置为其根视图控制器,或反之亦然,取决于具体需求。
        // 创建两个简单的View Controllers作为Tab的内容
        let vc1 = UIViewController()
        vc1.view.backgroundColor = .white
        vc1.tabBarItem.title = "首页"
        
        let vc2 = UIViewController()
        vc2.view.backgroundColor = .lightGray
        vc2.tabBarItem.title = "设置"
        
        // 创建Tab Bar Controller并添加View Controllers
        let tabBarController = UITabBarController()
        tabBarController.viewControllers = [vc1, vc2]
        
        // 创建Navigation Controller并将Tab Bar Controller设为其root view controller
        let navController = UINavigationController(rootViewController: tabBarController)
        
        // 设置window的rootViewController为Navigation Controller
        window?.rootViewController = navController
        window?.makeKeyAndVisible()
❌
❌