class Viperaptor::XcodeprojHelper

Provides a number of helper methods for working with xcodeproj gem

Public Class Methods

add_file_to_project_and_targets(project, targets_name, group_path, dir_path, file_group_path, file_name, file_is_resource = false) click to toggle source

Adds a provided file to a specific Project and Target @param project [Xcodeproj::Project] The target xcodeproj file @param targets_name [String] Array of targets name @param group_path [Pathname] The Xcode group path for current file @param dir_path [Pathname] The directory path for current file @param file_group_path [String] Directory path @param file_name [String] Current file name @param file_is_resource [TrueClass or FalseClass] If true then file is resource

@return [void]

# File lib/viperaptor/helpers/xcodeproj_helper.rb, line 22
def self.add_file_to_project_and_targets(project, targets_name, group_path, dir_path, file_group_path, file_name, file_is_resource = false)
  file_path = dir_path
  file_path = file_path.join(file_group_path) if file_group_path
  file_path = file_path.join(file_name) if file_name

  module_group = self.retrieve_group_or_create_if_needed(group_path, dir_path, file_group_path, project, true)
  xcode_file = module_group.new_file(File.absolute_path(file_path))

  targets_name.each do |target|
    xcode_target = obtain_target(target, project)

    if file_is_resource || self.is_bundle_resource?(file_name)
      xcode_target.add_resources([xcode_file])
    elsif self.is_compile_source?(file_name)
      xcode_target.add_file_references([xcode_file])
    end
  end
end
add_group_to_project(project, group_path, dir_path, directory_name) click to toggle source

Adds a provided directory to a specific Project @param project [Xcodeproj::Project] The target xcodeproj file @param group_path [Pathname] The Xcode group path for current directory @param dir_path [Pathname] The directory path for current directory @param directory_name [String] Current directory name

@return [void]

# File lib/viperaptor/helpers/xcodeproj_helper.rb, line 48
def self.add_group_to_project(project, group_path, dir_path, directory_name)
  self.retrieve_group_or_create_if_needed(group_path, dir_path, directory_name, project, true)
end
clear_group(project, targets_name, group_path) click to toggle source

Recursively clears children of the given group @param project [Xcodeproj::Project] The working Xcode project file @param group_path [Pathname] The full group path

@return [Void]

# File lib/viperaptor/helpers/xcodeproj_helper.rb, line 73
def self.clear_group(project, targets_name, group_path)
  module_group = self.retrieve_group_or_create_if_needed(group_path, nil, nil, project, false)
  return unless module_group

  files_path = self.files_path_from_group(module_group, project)
  return unless files_path

  files_path.each do |file_path|
    self.remove_file_by_file_path(file_path, targets_name, project)
  end

  module_group.clear
end
is_bundle_resource?(resource_name) click to toggle source

File is a resource @param resource_name [String] String of resource name

@return [TrueClass or FalseClass]

# File lib/viperaptor/helpers/xcodeproj_helper.rb, line 64
def self.is_bundle_resource?(resource_name)
  File.extname(resource_name) == '.xib' || File.extname(resource_name) == '.storyboard'
end
is_compile_source?(file_name) click to toggle source

File is a compiled source @param file_name [String] String of file name

@return [TrueClass or FalseClass]

# File lib/viperaptor/helpers/xcodeproj_helper.rb, line 56
def self.is_compile_source?(file_name)
  File.extname(file_name) == '.m' || File.extname(file_name) == '.swift' || File.extname(file_name) == '.mm'
end
module_with_group_path_already_exists(project, group_path) click to toggle source

Finds a group in a xcodeproj file with a given path @param project [Xcodeproj::Project] The working Xcode project file @param group_path [Pathname] The full group path

@return [TrueClass or FalseClass]

# File lib/viperaptor/helpers/xcodeproj_helper.rb, line 92
def self.module_with_group_path_already_exists(project, group_path)
  module_group = self.retrieve_group_or_create_if_needed(group_path, nil, nil, project, false)
  module_group.nil? ? false : true
end
obtain_project(project_name) click to toggle source

Returns a PBXProject class for a given name @param project_name [String] The name of the project file

@return [Xcodeproj::Project]

# File lib/viperaptor/helpers/xcodeproj_helper.rb, line 8
def self.obtain_project(project_name)
  Xcodeproj::Project.open(project_name)
end

Private Class Methods

build_phases_from_targets(targets_name, project) click to toggle source

Find and return target build phases @param targets_name [String] Array of targets @param project [Xcodeproj::Project] The target xcodeproj file

@return [[PBXSourcesBuildPhase]]

# File lib/viperaptor/helpers/xcodeproj_helper.rb, line 196
def self.build_phases_from_targets(targets_name, project)
  build_phases = []

  targets_name.each do |target_name|
    xcode_target = self.obtain_target(target_name, project)
    xcode_target.build_phases.each do |build_phase|
      if build_phase.isa == 'PBXSourcesBuildPhase'
        build_phases.push(build_phase)
      end
    end
  end

  build_phases
end
configure_file_ref_path(file_ref) click to toggle source

Get configure file full path @param file_ref [PBXFileReference] Build file

@return [String]

# File lib/viperaptor/helpers/xcodeproj_helper.rb, line 231
def self.configure_file_ref_path(file_ref)
  build_file_ref_path = file_ref.hierarchy_path.to_s
  build_file_ref_path[0] = ''

  build_file_ref_path
end
files_path_from_group(module_group, _project) click to toggle source

Get all files path from group path @param module_group [PBXGroup] The module group @param project [Xcodeproj::Project] The target xcodeproj file

@return [[String]]

# File lib/viperaptor/helpers/xcodeproj_helper.rb, line 243
def self.files_path_from_group(module_group, _project)
  files_path = []

  module_group.recursive_children.each do |file_ref|
    if file_ref.isa == 'PBXFileReference'
      file_ref_path = configure_file_ref_path(file_ref)
      files_path.push(file_ref_path)
    end
  end

  files_path
end
obtain_target(target_name, project) click to toggle source

Returns an AbstractTarget class for a given name @param target_name [String] The name of the target @param project [Xcodeproj::Project] The target xcodeproj file

@return [Xcodeproj::AbstractTarget]

# File lib/viperaptor/helpers/xcodeproj_helper.rb, line 138
def self.obtain_target(target_name, project)
  project.targets.each do |target|
    return target if target.name == target_name
  end

  error_description = "Cannot find a target with name #{target_name} in Xcode project".red
  raise StandardError, error_description
end
path_names_from_path(path) click to toggle source

Splits the provided Xcode path to an array of separate paths @param path The full group or file path

@return [[String]]

# File lib/viperaptor/helpers/xcodeproj_helper.rb, line 151
def self.path_names_from_path(path)
  path.to_s.split('/')
end
remove_file_by_file_path(file_path, targets_name, project) click to toggle source

Remove build file from target build phase @param file_path [String] The path of the file @param targets_name [String] Array of targets @param project [Xcodeproj::Project] The target xcodeproj file

@return [Void]

# File lib/viperaptor/helpers/xcodeproj_helper.rb, line 161
def self.remove_file_by_file_path(file_path, targets_name, project)
  file_names = path_names_from_path(file_path)

  build_phases = nil

  if self.is_compile_source?(file_names.last)
    build_phases = self.build_phases_from_targets(targets_name, project)
  elsif self.is_bundle_resource?(file_names.last)
    build_phases = self.resources_build_phase_from_targets(targets_name, project)
  end

  self.remove_file_from_build_phases(file_path, build_phases)
end
remove_file_from_build_phases(file_path, build_phases) click to toggle source
# File lib/viperaptor/helpers/xcodeproj_helper.rb, line 175
def self.remove_file_from_build_phases(file_path, build_phases)
  return if build_phases.nil?

  build_phases.each do |build_phase|
    build_phase.files.each do |build_file|
      next if build_file.nil? || build_file.file_ref.nil?

      build_file_path = self.configure_file_ref_path(build_file.file_ref)

      if build_file_path == file_path
        build_phase.remove_build_file(build_file)
      end
    end
  end
end
resources_build_phase_from_targets(targets_name, project) click to toggle source

Find and return target resources build phase @param targets_name [String] Array of targets @param project [Xcodeproj::Project] The target xcodeproj file

@return [[PBXResourcesBuildPhase]]

# File lib/viperaptor/helpers/xcodeproj_helper.rb, line 216
def self.resources_build_phase_from_targets(targets_name, project)
  resource_build_phase = []

  targets_name.each do |target_name|
    xcode_target = self.obtain_target(target_name, project)
    resource_build_phase.push(xcode_target.resources_build_phase)
  end

  resource_build_phase
end
retrieve_group_or_create_if_needed(group_path, dir_path, file_group_path, project, create_group_if_not_exists) click to toggle source

Finds or creates a group in a xcodeproj file with a given path @param group_path [Pathname] The Xcode group path for module @param dir_path [Pathname] The directory path for module @param file_group_path [String] Directory path @param project [Xcodeproj::Project] The working Xcode project file @param create_group_if_not_exists [TrueClass or FalseClass] If true nonexistent group will be created

@return [PBXGroup]

# File lib/viperaptor/helpers/xcodeproj_helper.rb, line 107
def self.retrieve_group_or_create_if_needed(group_path, dir_path, file_group_path, project, create_group_if_not_exists)
  group_names = path_names_from_path(group_path)
  group_components_count = group_names.count
  group_names += path_names_from_path(file_group_path) if file_group_path

  final_group = project

  group_names.each_with_index do |group_name, index|
    next_group = final_group[group_name]

    unless next_group
      return nil unless create_group_if_not_exists

      if group_path != dir_path && index == group_components_count-1
        next_group = final_group.new_group(group_name, dir_path, :project)
      else
        next_group = final_group.new_group(group_name, group_name)
      end
    end

    final_group = next_group
  end

  final_group
end