Class: Viperaptor::XcodeprojHelper

Inherits:
Object
  • Object
show all
Defined in:
lib/viperaptor/helpers/xcodeproj_helper.rb

Overview

Provides a number of helper methods for working with xcodeproj gem

Class Method Summary collapse

Class Method Details

.add_file_to_project_and_targets(project, targets_name, group_path, dir_path, file_group_path, file_name, file_is_resource = false) ⇒ void

This method returns an undefined value.

Adds a provided file to a specific Project and Target

Parameters:

  • project (Xcodeproj::Project)

    The target xcodeproj file

  • targets_name (String)

    Array of targets name

  • group_path (Pathname)

    The Xcode group path for current file

  • dir_path (Pathname)

    The directory path for current file

  • file_group_path (String)

    Directory path

  • file_name (String)

    Current file name

  • file_is_resource (TrueClass or FalseClass) (defaults to: false)

    If true then file is resource



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 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) ⇒ void

This method returns an undefined value.

Adds a provided directory to a specific Project

Parameters:

  • project (Xcodeproj::Project)

    The target xcodeproj file

  • group_path (Pathname)

    The Xcode group path for current directory

  • dir_path (Pathname)

    The directory path for current directory

  • directory_name (String)

    Current directory name



48
49
50
# 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

.build_phases_from_targets(targets_name, project) ⇒ [PBXSourcesBuildPhase]

Find and return target build phases

Parameters:

  • targets_name (String)

    Array of targets

  • project (Xcodeproj::Project)

    The target xcodeproj file

Returns:

  • ([PBXSourcesBuildPhase])


196
197
198
199
200
201
202
203
204
205
206
207
208
209
# 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

.clear_group(project, targets_name, group_path) ⇒ Void

Recursively clears children of the given group

Parameters:

  • project (Xcodeproj::Project)

    The working Xcode project file

  • group_path (Pathname)

    The full group path

Returns:

  • (Void)


73
74
75
76
77
78
79
80
81
82
83
84
85
# 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

.configure_file_ref_path(file_ref) ⇒ String

Get configure file full path

Parameters:

  • file_ref (PBXFileReference)

    Build file

Returns:



231
232
233
234
235
236
# 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) ⇒ [String]

Get all files path from group path

Parameters:

  • module_group (PBXGroup)

    The module group

  • project (Xcodeproj::Project)

    The target xcodeproj file

Returns:



243
244
245
246
247
248
249
250
251
252
253
254
# 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

.is_bundle_resource?(resource_name) ⇒ TrueClass or FalseClass

File is a resource

Parameters:

  • resource_name (String)

    String of resource name

Returns:

  • (TrueClass or FalseClass)


64
65
66
# 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) ⇒ TrueClass or FalseClass

File is a compiled source

Parameters:

  • file_name (String)

    String of file name

Returns:

  • (TrueClass or FalseClass)


56
57
58
# 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) ⇒ TrueClass or FalseClass

Finds a group in a xcodeproj file with a given path

Parameters:

  • project (Xcodeproj::Project)

    The working Xcode project file

  • group_path (Pathname)

    The full group path

Returns:

  • (TrueClass or FalseClass)


92
93
94
95
# 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) ⇒ Xcodeproj::Project

Returns a PBXProject class for a given name

Parameters:

  • project_name (String)

    The name of the project file

Returns:

  • (Xcodeproj::Project)


8
9
10
# File 'lib/viperaptor/helpers/xcodeproj_helper.rb', line 8

def self.obtain_project(project_name)
  Xcodeproj::Project.open(project_name)
end

.obtain_target(target_name, project) ⇒ Xcodeproj::AbstractTarget

Returns an AbstractTarget class for a given name

Parameters:

  • target_name (String)

    The name of the target

  • project (Xcodeproj::Project)

    The target xcodeproj file

Returns:

  • (Xcodeproj::AbstractTarget)

Raises:

  • (StandardError)


138
139
140
141
142
143
144
145
# 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) ⇒ [String]

Splits the provided Xcode path to an array of separate paths

Parameters:

  • path

    The full group or file path

Returns:



151
152
153
# 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) ⇒ Void

Remove build file from target build phase

Parameters:

  • file_path (String)

    The path of the file

  • targets_name (String)

    Array of targets

  • project (Xcodeproj::Project)

    The target xcodeproj file

Returns:

  • (Void)


161
162
163
164
165
166
167
168
169
170
171
172
173
# 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) ⇒ Object



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# 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) ⇒ [PBXResourcesBuildPhase]

Find and return target resources build phase

Parameters:

  • targets_name (String)

    Array of targets

  • project (Xcodeproj::Project)

    The target xcodeproj file

Returns:

  • ([PBXResourcesBuildPhase])


216
217
218
219
220
221
222
223
224
225
# 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) ⇒ PBXGroup

Finds or creates a group in a xcodeproj file with a given path

Parameters:

  • group_path (Pathname)

    The Xcode group path for module

  • dir_path (Pathname)

    The directory path for module

  • file_group_path (String)

    Directory path

  • project (Xcodeproj::Project)

    The working Xcode project file

  • create_group_if_not_exists (TrueClass or FalseClass)

    If true nonexistent group will be created

Returns:

  • (PBXGroup)


107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# 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