xcproj 是一个用 Swift 编写的库,用于解析和使用 Xcode 项目。它受到了 CocoaPods XcodeProj 和 xcode 的启发。
✅
持续集成
💅
动机能够使用 Swift 编写命令行脚本来更新您的 Xcode 项目配置。这里有几个例子
- 添加新的
构建阶段
。 - 更新项目的
构建设置
。 - 创建新的
方案
。
❤️
从 xcproj 中受益的项目项目 | 描述 |
---|---|
XcodeGen | 从 YAML 文件中动态生成 Xcode 项目 |
xclint | 检查你的 Xcode 项目的格式 |
xctools | 实用的命令行工具 |
👨👩👧
贡献- 使用Git克隆仓库
[email protected]:xcodeswift/xcproj.git
。 - 使用
swift package generate-xcodeproj
生成 xcproj。 - 打开
xcproj.xcodeproj
。
🦋
设置使用 Swift Package Manager
在您的 Package.swift
文件中添加依赖
let package = Package(
name: "myproject",
dependencies: [
.package(url: "https://github.com/xcodeswift/xcproj.git", .upToNextMajor(from: "4.2.0")),
],
targets: [
.target(
name: "myproject",
dependencies: ["xcproj"]),
]
)
Marathon
使用编辑您的 Marathonfile
并指定依赖
https://github.com/xcodeswift/xcproj.git
CocoaPods
使用编辑您的 Podfile
并指定依赖
pod "xcproj"
Carthage
使用编辑您的 Cartfile
并指定依赖项
github "xcodeswift/xcproj"
注意:xcproj 仅适用于 macOS 和 iOS 项目。
🐒
如何使用 xcprojXcode 提供了代表 Xcode 项目并通过对项目文件内容进行解析来初始化的模型。生成的模型是可以随时修改的类。这些模型中的变更会被保存在内存中,直到通过将它们写入磁盘(通过写入 XcodeProj
或 XCWorkspace
模型)来持久化。对项目的修改通常分为三个步骤
- 读取项目或工作区,分别初始化
XcodeProj
或XCWorkspace
对象。 - 修改这些对象或其任何依赖项。
- 将其写回磁盘。
// Removing all frameworks build phases
let project = try! XcodeProj(path: "myproject.xcodeproj")
project.pbxproj.frameworksBuildPhases.removeAll()
try! project.write(path: "myproject.xcodeproj")
下面的图显示了 Xcode 项目的结构。
XcodeProj
具有以下属性
XCSharedData
包含有关项目方案的信息。XCWorkspace
定义了项目工作区的结构。PBXProj
定义了项目的结构。
在其它属性中,PBXProj
对象中最重要的一个属性是 Objects
。项目是通过以下可以分类的这些对象列表定义的
- 构建阶段对象:定义可用的构建阶段。
- 目标对象:定义您的项目目标及其之间的依赖关系。
- 配置对象:定义可用的配置以及它们与目标的关联。
- 文件对象:定义项目文件、构建文件和组。
所有对象都是 PBXObject
的子类,有一个唯一的、确定的引用。此外,它们是可哈希的,并遵循 Equatable
协议。
有关每个这些对象是做什么的更多信息,请参阅以下链接 http://www.monobjc.net/xcode-project-file-format.html
注意事项
- 对象引用用于定义对象之间的依赖关系。在未来,我们可能会更愿意使用对象引用而不是唯一标识符。
- 写入不会验证项目的结构。验证通过
xcproj
执行的更改结构是开发者的责任。 - 新的 Xcode 版本可能会引入
xcproj
不支持的新模型或属性。如果您发现任何,请不要犹豫,在仓库上 提出一个问题。
示例
MyApp.xcodeproj
读取 let project = try XcodeProj(path: "MyApp.xcodeproj")
MyApp.xcodeproj
写入 try project.write(path: "MyApp.xcodeproj")
Sources
组内添加 Home
组
在 guard var sourcesGroup = project.pbxproj.objects.groups.first(where: {$0.value.name == "Sources" || $0.value.path == "Sources"})?.value else { return }
let homeGroup = PBXGroup(children: [], sourceTree: .group, path: "Home")
let groupRef = pbxproj.objects.generateReference(homeGroup, "Home")
sourcesGroup.children.append(homeGroup, reference: groupRef)
project.pbxproj.objects.addObject(groupRef)
版本 <2.0
guard var sourcesGroup = project.pbxproj.objects.groups.first(where: {$0.value.name == "Sources" || $0.value.path == "Sources"})?.value else { return }
let homeGroup = PBXGroup(reference: project.pbxproj.generateUUID(for: PBXGroup.self), children: [], sourceTree: .group, path: "Home")
sourcesGroup.children.append(homeGroup.reference)
project.pbxproj.objects.addObject(homeGroup)
HomeGroup
内添加 HomeViewController.swift
文件
在 let homeViewController = PBXFileReference(sourceTree: .group, name: "HomeViewController.swift", path: "HomeViewController.swift")
let fileRef = pbxproj.objects.generateReference(homeViewController, "HomeViewController.swift")
homeGroup.children.append(fileRef)
project.pbxproj.objects.addObject(homeViewController, reference: fileRef)
版本 <2.0
let homeViewController = PBXFileReference(reference: project.pbxproj.generateUUID(for: PBXFileReference.self), sourceTree: .group, name: "HomeViewController.swift", path: "HomeViewController.swift")
homeGroup.children.append(homeViewController.reference)
project.pbxproj.objects.addObject(homeViewController)
HomeViewController.swift
文件添加到 MyApp
目标中
将 guard let sourcesBuildPhase = project.pbxproj
.objects.nativeTargets
.values
.first(where: {$0.name == "MyApp"})
.flatMap({ target -> PBXSourcesBuildPhase? in
return project.pbxproj.objects.sourcesBuildPhases.first(where: { target.buildPhases.contains($0.key) })?.value
}) else { return }
// PBXBuildFile is a proxy model that allows specifying some build attributes to the files
let buildFile = PBXBuildFile(fileRef: fileRef)
let buildFileRef = project.pbxproj.objects.generateReference(buildFile, "HomeViewController.swift")
project.pbxproj.objects.addObject(buildFile, reference: buildFileRef)
sourcesBuildPhase.files.append(buildFileRef)
版本 <2.0
guard let sourcesBuildPhase = project.pbxproj
.objects.nativeTargets
.values
.first(where: {$0.name == "MyApp"})
.flatMap({ target -> PBXSourcesBuildPhase? in
return project.pbxproj.objects.sourcesBuildPhases.values.first(where: { target.buildPhases.contains($0.reference) })
}) else { return }
// PBXBuildFile is a proxy model that allows specifying some build attributes to the files
let buildFile = PBXBuildFile(reference: project.pbxproj.generateUUID(for: PBXBuildFile.self), fileRef: homeViewController.reference)
project.pbxproj.objects.addObject(buildFile)
sourcesBuildPhase.files.append(buildFile.reference)
📄
文档您可以通过以下链接查看文档:链接。该文档由 Jazzy 自动生成,Jazzy 是 Realm 项目的一部分。
📚
参考内容- PathKit
- Xcode 项目文件格式
- 简要介绍 Xcode 项目格式
- pbexplorer
- pbxproj 标识符
- mob-pbxproj
- Xcodeproj
- Nanaimo
- Facebook Buck
- Swift 包管理器 - Xcodeproj
贡献者
本项目的存在归功于所有贡献者。有关贡献信息,请参考 [贡献说明]。您可以在这里看到贡献者列表:
赞助者
感谢所有赞助者!
赞助商
成为赞助商以支持本项目。您的标志将在这里展示,并链接至您的网站。 [成为赞助商]
许可协议
MIT License
Copyright (c) 2017 xcode.swift
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.