【问题标题】:Duplicate iOS application target, rename it, add new icon and build app from command line (without using Xcode GUI)复制 iOS 应用程序目标,重命名它,添加新图标并从命令行构建应用程序(不使用 Xcode GUI)
【发布时间】:2017-08-24 18:44:10
【问题描述】:

我想将向我的 iOS 应用程序添加新目标的过程自动化,并编写一个脚本来加快整个过程。有没有办法复制 Xcode iOS 应用程序目标,然后重命名它,添加特定于该目标的新图标,更改包 ID、应用程序名称等,最后构建应用程序?我尝试使用 AppleScript 来实现这一点,但没有运气。

我现在使用的解决方法是创建一个额外的目标(使用 Xcode GUI)并在构建期间对其进行自定义(每次我想构建应用程序时)。这种方法的最大缺点是目标的配置不会保存在任何地方,并且必须为应用程序的每个构建指定目标的参数。这可能导致不可重复的构建和其他不可调试的问题。这就是为什么我正在寻找一种方法或工具来允许我从命令行脚本复制和配置新目标

【问题讨论】:

  • 目标配置的哪一部分需要自定义?您知道,当您从命令行触发 Xcode 构建时,您可以轻松覆盖所有构建设置,是吗?因此,如果这就是您所需要的,而不是创建多个目标,那么使用不同的覆盖设置多次构建单个目标的脚本怎么样?
  • @Mecki 我现在正在使用这样的解决方案。我只是想知道有没有办法在项目中添加/“保存”创建的目标,这样以后打开项目的任何人都会看到所有创建的目标。
  • 无法自动设置目标。有一个非常先进的 Ruby 库来解析和修改 Xcode 项目:github.com/CocoaPods/Xcodeproj 但是您仍然需要编写自己的 Ruby 脚本。但是,这将为您提供静态目标,并且随着时间的推移使这些目标保持同步是一个地狱。我更喜欢只有一个目标,并且在构建期间会覆盖相当多的构建设置,这样可以更好地扩展多年和十几个开发人员。

标签: ios xcode xcode8 xcodebuild xcode-command-line-tools


【解决方案1】:

您可以使用此 ruby​​ 脚本复制任何目标,但您需要先安装github.com/CocoaPods/Xcodeproj

#!/usr/bin/env ruby

require 'rubygems'
require 'xcodeproj'

puts "Project path:"
proj_path = gets
puts "New target name:"
name = gets
puts "New target bundle identifer"
bundleIdentifier = gets
puts "Witch target to clone?"
srcTargetName =  gets

name = name.chomp
bundleIdentifier = bundleIdentifier.chomp
proj_path = proj_path.chomp
srcTargetName = srcTargetName.chomp

proj = Xcodeproj::Project.open(proj_path)
src_target = proj.targets.find { |item| item.to_s == srcTargetName }
#proj_path = "/testingTest.xcodeproj"

# create target
target = proj.new_target(src_target.symbol_type, name, src_target.platform_name, src_target.deployment_target)
target.product_name = name


# create scheme
scheme = Xcodeproj::XCScheme.new
scheme.add_build_target(target)
scheme.set_launch_target(target)
scheme.save_as(proj_path, name, shared = true)

# copy build_configurations
target.build_configurations.map do |item|
  item.build_settings.update(src_target.build_settings(item.name))
end

target.build_configurations.each do |config|
  config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = bundleIdentifier
  config.build_settings['PRODUCT_NAME'] = "$(TARGET_NAME)"
end

# copy build_phases
phases = src_target.build_phases.reject { |x| x.instance_of? Xcodeproj::Project::Object::PBXShellScriptBuildPhase }.collect(&:class)

phases.each do |klass|
  src = src_target.build_phases.find { |x| x.instance_of? klass }
  dst = target.build_phases.find { |x| x.instance_of? klass }
  unless dst
    dst ||= proj.new(klass)
    target.build_phases << dst
  end
  dst.files.map { |x| x.remove_from_project }

  src.files.each do |f|
    file_ref = proj.new(Xcodeproj::Project::Object::PBXFileReference)
    file_ref.name = f.file_ref.name
    file_ref.path = f.file_ref.path
    file_ref.source_tree = f.file_ref.source_tree
    file_ref.last_known_file_type = f.file_ref.last_known_file_type
    #file_ref.fileEncoding = f.file_ref.fileEncoding
    begin
      file_ref.move(f.file_ref.parent)
    rescue
    end

    build_file = proj.new(Xcodeproj::Project::Object::PBXBuildFile)
    build_file.file_ref = f.file_ref
    dst.files << build_file
  end
end

# add files
#classes = proj.main_group.groups.find { |x| x.to_s == 'Group' }.groups.find { |x| x.name == 'Classes' }
#sources = target.build_phases.find { |x| x.instance_of? Xcodeproj::Project::Object::PBXSourcesBuildPhase }
#file_ref = classes.new_file('test.m')
#build_file = proj.new(Xcodeproj::Project::Object::PBXBuildFile)
#build_file.file_ref = file_ref
#sources.files << build_file

proj.save

【讨论】:

    猜你喜欢
    • 2012-01-21
    • 2013-09-25
    • 2012-01-21
    • 1970-01-01
    • 2013-09-25
    • 2018-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多