IOS应用开发:iOS使用脚本自动化复制target
安安 2017-09-27 来源 :网络 阅读 702 评论 0

摘要:本篇IOS应用开发教程将为大家讲解iOS使用脚本自动化复制target点,看完这篇文章会让你对IOS编程的知识点有更加清晰的理解和运用。

本篇IOS应用开发教程将为大家讲解iOS使用脚本自动化复制target点,看完这篇文章会让你对IOS编程的知识点有更加清晰的理解和运用。


有些项目成熟以后,就会有需求自动化配置生成一个全新的项目,不需要再让开发人员手动修改工程文件,将配置化工作直接移交给运维或者配置团队去做

其实按照普通的做法,无非就是在xcode里将目标target duplicate一下,然后修改相关的项目名称、target名称、bundleid等等,这些内容其实在xcodeproj文件中都有对应的配置信息,所以我们可以通过直接修改Xcodeproj直接文件的方式实现

首先感谢虾神 提供了详细的原理解说和工具介绍,在实现时少走了很多弯路,有兴趣的同学可以前往 虾神 的文章学习,这里我把最终实现贴出来供大家参考~~

希望进一步学习ios工程配置和脚本相关的同学建议去这里:

ruby doc

xcodeproj相关API文档

github示例

巧用脚本解决 Target 管理问题

 

 

#!/usr/bin/env ruby

require 'rubygems'

require 'xcodeproj'

require 'fileutils'

#----------------------------------- 目标项目配置内容----------------------------#

name = "newyorktoon"

displayname = "纽约通"

target_toonType = 10001

target_pushType = "hello"

target_channel = "hello"

target_mapKey = "hello"

target_schemeType = "hello"#----------------------------------- 目标项目配置内容----------------------------#

# 模板项目                   

# srcname = "tzhqtoon"                                                                      

# srcdisplayname = "后勤通"                                                 

#project

project_path = "Hello.xcodeproj"# 复制资源文件,注意:

# 1. 复制资源文件时需要排除源资源文件

# 2. 在此文件的最后面将复制出来的资源文件添加到目标target

targetdir = "TNTarget/#{name}"

srcroot = "TNTarget/#{srcname}"

# 复制资源文件夹,将源target下的图片资源文件夹复制到目标target目录if !Dir.exists?(targetdir)

  Dir.mkdir(targetdir)

end

codeDirs = [

  "#{srcroot}/Resources",

  "#{srcroot}/NetWork",

  "#{srcroot}/TabbarSetDataSource",

  "#{srcroot}/TNHQHome"

]#复制源target目录下的定制化代码目录到目标target目录

hasAllListFiles = false

codeDirs.each do |d|

  hasAllListFiles = Dir.exists?(d)#-> 此处假设所有的code file为一个整体,一有具有

  if hasAllListFiles

    FileUtils.cp_r  d, targetdir

  end

end

# 寻找模板target

proj = Xcodeproj::Project.open(project_path)

src_target = proj.targets.find { |item| item.to_s == srcname }# 创建目标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(project_path, name)

#  build_configurations

target.build_configurations.map do |item|

#设置target相关配置  item.build_settings.update(src_target.build_settings(item.name))

  # puts "-"*30 + "#{item.build_settings}" +"_"*30

  item.build_settings["PRODUCT_BUNDLE_IDENTIFIER"] = "com.abc.aa.#{name}"

  item.build_settings["PRODUCT_NAME"] =displayname

 

  targetInfoPlist = item.build_settings["INFOPLIST_FILE"]

  item.build_settings["INFOPLIST_FILE"] = targetInfoPlist.sub(srcname, name)

 

  puts "-"*30 + "#{item.build_settings['PRODUCT_BUNDLE_IDENTIFIER']}" +"_"*30

  puts "-"*30 + "#{item.build_settings['PRODUCT_NAME']}" +"_"*30

end

# build_phases

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

#复制源target引用的source和resource文件引用

phases.each do |klass|

puts "||---------------------> copy phases #{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 }

 

idx = 1

  src.files.each do |f|# 排除文件,将源target中的文件排除,不引用该文件

    if f.file_ref and f.file_ref.hierarchy_path.index(srcroot) != nil

      puts "\n................... ignore file:  #{f.file_ref}, #{f.file_ref.hierarchy_path}...................\n"

        next

    end

 

    file_ref = proj.new(Xcodeproj::Project::Object::PBXFileReference)

    if f.settings

      puts ">>file.settings:  #{idx} > file: " + f.file_ref.to_s + " settings: " + f.settings.to_s

    end

 

    idx = idx+1

    if f.file_ref

      if f.file_ref.name

        puts ">> file_ref name: #{f.file_ref.name} path: #{f.file_ref.path} source_tree: #{f.file_ref.source_tree}"

      end

      # puts ">> file path: #{f.file_ref.hierarchy_path}-- #{f.file_ref.real_path}"

      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

 

    end

 

    build_file = proj.new(Xcodeproj::Project::Object::PBXBuildFile)

    build_file.file_ref = f.file_ref# 文件属性配置,如no-arc   

 if f.settings

    build_file.settings = f.settings

  end

    dst.files << build_file

  end

end

#设置目标target文件组

projTargetGroup = proj.main_group.groups.find { |x| x.path == 'TNTarget' }

targetGroup =  projTargetGroup.new_group(name, name)# resource

resourceGroup = targetGroup.new_group("Resources", "./Resources")

supportingGroup=resourceGroup.new_group("Supporting Files")

# 添加资源文件引用,注意和代码文件引用方式不同target.add_resources(

  [

    resourceGroup.new_reference("areaCode.plist"),

    resourceGroup.new_reference("login_toon_bg@2x.png"),

    resourceGroup.new_reference("login_toon_bg@3x.png"),

    resourceGroup.new_reference("tab_item_home_highlight@2x.png"),

    resourceGroup.new_reference("tab_item_home_highlight@3x.png"),

    resourceGroup.new_reference("tab_item_home_normal@2x.png"),

    resourceGroup.new_reference("tab_item_home_normal@3x.png"),

    resourceGroup.new_reference("Toon_logo@2x.png"),

    resourceGroup.new_reference("Toon_logo@3x.png"),

    resourceGroup.new_reference("toon_serviceProtocol.html"),

    resourceGroup.new_reference("user_protocol.html"),

    resourceGroup.new_reference("NewFunction.html"),

 

    supportingGroup.new_reference("Supporting Files/configuration.plist"),

    supportingGroup.new_reference("Supporting Files/Info.plist"),

    supportingGroup.new_reference("Supporting Files/Images.xcassets"),

    supportingGroup.new_reference("Supporting Files/InfoPlist.strings"),

    supportingGroup.new_reference("Supporting Files/Localizable.strings")

  ])

 

  if hasAllListFiles# 添加代码文件组

code1 = targetGroup.new_group("NetWork", "./NetWork")

code2 = targetGroup.new_group("TabbarSetDataSource", "./TabbarSetDataSource")

code3 = targetGroup.new_group("TNHQHome", "./TNHQHome")

# 添加代码文件引用    target.add_file_references(

      [

        code1.new_reference("NetworkRequestURL.h"),

        code1.new_reference("NetworkRequestURL.m"),

 

        code2.new_reference("TNTabSettingDataSource.h"),

        code2.new_reference("TNTabSettingDataSource.m"),

 

        code3.new_reference("TNHomeViewController.m")

        ])

  end

 

  # 修改文件通用内容

  infoplistfile = "#{targetdir}/Resources/Supporting Files/Info.plist"

  files = [

    "#{targetdir}/Resources/areaCode.plist",

    "#{targetdir}/Resources/toon_serviceProtocol.html",

    "#{targetdir}/Resources/user_protocol.html",

    "#{targetdir}/Resources/NewFunction.html",

    infoplistfile,

    "#{targetdir}/Resources/Supporting Files/InfoPlist.strings",

    "#{targetdir}/Resources/Supporting Files/Localizable.strings"

 

  ]

  if hasAllListFiles

     files << "#{targetdir}/TabbarSetDataSource/TNTabSettingDataSource.m"

  end

files.each do |f1|

  File.open(f1) do |fr|

      buffer = fr.read.gsub(srcdisplayname, displayname)

      buffer= buffer.gsub("项目名", displayname)

      buffer= buffer.gsub("大同", displayname)

       File.open(f1, "w") { |fw| fw.write(buffer) }

  end

end

# 修改info.plist

  File.open(infoplistfile) do |fr|

    if hasAllListFiles

      puts "*************************** 1"

      buffer = fr.read.gsub("<string>10024</string>", "<string>#{target_pushType}</string>")

      buffer= buffer.gsub("<integer>124</integer>", "<integer>#{target_toonType}</integer>")

      buffer= buffer.gsub("<string>1241002</string>", "<string>#{target_channel}</string>")

      buffer= buffer.gsub("<string>8058bda8c0ad5a7cfb8742cfbac4ecb8</string>", "<string>#{target_mapKey}</string>")

      buffer= buffer.gsub("<string>toon124</string>", "<string>#{target_schemeType}</string>")

    else

      puts "*************************** 2"

      buffer = fr.read.gsub("<string>10016</string>", "<string>#{target_pushType}</string>")

      buffer= buffer.gsub("<integer>116</integer>", "<integer>#{target_toonType}</integer>")

      buffer= buffer.gsub("<string>10035</string>", "<string>#{target_channel}</string>")

      buffer= buffer.gsub("<string>e851d7df83d59f143bff1ad5a3a8e554</string>", "<string>#{target_mapKey}</string>")

      buffer= buffer.gsub("<string>toon116</string>", "<string>#{target_schemeType}</string>")

    end

    puts "*************************** updating InfoPlist"

 

    File.open(infoplistfile, "w") { |fw| fw.write(buffer) }

 

  end

proj.save

# 修改Podfile

puts ">> prepare loading pods ..."

podTarget = "target '#{name}' do shared_pods  end"

File.open("Podfile") do |file|

  if file.read().index(podTarget) ==nil

    File.open(infoplistfile, "w") { |fw| fw.puts podTarget }

    puts ">> add pod item"

  else

    puts ">> pod has been added"

  end

 

end

# file.close

# 更新pod依赖exec 'pod install'


本文由职坐标整理并发布,希望对同学们学习IOS的知识有所帮助。了解更多详情请关注职坐标IOS频道!


本文由 @安安 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved