This class is used to gather localized files into one entry.
last_known_file_type
children
source_tree
path
name
uses_tabs
indent_width
tab_width
wraps_lines
comments
display_name
files
groups
recursive_children_groups
version_groups
new_file
new_file_reference
set_file_refenrece_name_if_needed
new_framework
new_xcdatamodeld
new_group
new_static_library
new_bundle
new_xcdatamodel_group
[]
remove_children_recursively
find_subpath
<<
sort_by_type!
isa
initialize
initialize_defaults
uuid
project
remove_from_project
to_s
referrers
add_referrer
remove_referrer
remove_reference
==
<=>
inspect
last_known_file_type #=> String
String
The file type guessed by Xcode.
405 attribute :last_known_file_type, String
children #=> ObjectList<PBXGroup, PBXFileReference>
ObjectList
The objects contained by the group.
15 has_many :children, [PBXGroup, PBXFileReference, PBXReferenceProxy]
source_tree #=> String
String
The source tree to which this group is relative.
21 attribute :source_tree, String, '<group>'
path #=> String
String
The path to a folder in the file system.
28 attribute :path, String
name #=> String
String
The name of the group.
34 attribute :name, String
uses_tabs #=> String
String
Whether Xcode should use tabs for text alignment.
`1`
41 attribute :uses_tabs, String
indent_width #=> String
String
The width of the indent.
`2`
48 attribute :indent_width, String
tab_width #=> String
String
The width of the tabs.
`2`
55 attribute :tab_width, String
wraps_lines #=> String
String
Whether Xcode should wrap lines.
`1`
62 attribute :wraps_lines, String
comments #=> String
String
Comments associated with this group.
68 attribute :comments, String
display_name #=> String
String
The name of the group taking into account the path or other factors if needed.
79 def display_name
80 if name
81 name
82 elsif path
83 File.basename(path)
84 elsif self.equal?(project.main_group)
85 'Main Group'
86 end
87 end
files #=> Array<PBXFileReference>
Array
The files references in the group children.
92 def files
93 children.select { |obj| obj.class == PBXFileReference }
94 end
groups #=> Array<PBXGroup>
Array
The groups in the group children.
98 def groups
99 children.select { |obj| obj.class == PBXGroup }
100 end
recursive_children_groups #=> Array<PBXGroup,PBXFileReference,PBXReferenceProxy>
Array
The recursive children of the group.
105 def recursive_children_groups
106 result = []
107 groups.each do |child|
108 result << child
109 result.concat(child.recursive_children_groups)
110 end
111 result
112 end
version_groups #=> Array<XCVersionGroup>
Array
The version groups in the group children.
117 def version_groups
118 children.select { |obj| obj.class == XCVersionGroup }
119 end
new_file(path, sub_group_path = nil) #=> PBXFileReference
#to_s
path
The file system path of the file.
String
sub_group_path
An optional subgroup path indicating the groups separated by
a /
.
PBXFileReference
The new file reference.
140 def new_file(path, sub_group_path = nil)
141 extname = File.extname(path)
142 case
143 when extname == '.framework' then new_framework(path, sub_group_path)
144 when extname == '.xcdatamodeld' then new_xcdatamodeld(path, sub_group_path)
145 else new_file_reference(path, sub_group_path)
146 end
147 end
new_file_reference(path, sub_group_path = nil) #=> PBXFileReference
@see
#new_file
PBXFileReference
The new file reference.
158 def new_file_reference(path, sub_group_path = nil)
159 ref = project.new(PBXFileReference)
160 ref.path = path.to_s
161 ref.update_last_known_file_type
162
163 parent_group = find_subpath(sub_group_path, true)
164 parent_group.children << ref
165 set_file_refenrece_name_if_needed(ref, parent_group)
166 ref
167 end
set_file_refenrece_name_if_needed(ref, parent_group) #=> void
PBXFileReference
XCVersionGroup
ref
The reference which needs the name optionally set.
void
176 def set_file_refenrece_name_if_needed(ref, parent_group)
177 same_path_of_group = (parent_group.path == Pathname(ref.path).dirname.to_s)
178 same_path_project = (Pathname(ref.path).dirname.to_s == '.' && parent_group.path.nil?)
179 unless same_path_of_group || same_path_project
180 ref.name = Pathname(ref.path).basename.to_s
181 end
182 end
new_framework(path, sub_group_path = nil) #=> PBXFileReference
@see
#new_file
PBXFileReference
The new file reference.
192 def new_framework(path, sub_group_path = nil)
193 ref = new_file_reference(path, sub_group_path = nil)
194 ref.include_in_index = nil
195 ref
196 end
new_xcdatamodeld(path, sub_group_path = nil) #=> XCVersionGroup
@see
#new_file
XCVersionGroup
The new reference.
210 def new_xcdatamodeld(path, sub_group_path = nil)
211 path = Pathname.new(path)
212 ref = project.new(XCVersionGroup)
213 ref.path = path.to_s
214 ref.source_tree = '<group>'
215 ref.version_group_type = 'wrapper.xcdatamodel'
216
217 last_child_ref = nil
218 if path.exist?
219 path.children.each do |child_path|
220 if File.extname(child_path) == '.xcdatamodel'
221 child_ref = ref.new_file_reference(child_path)
222 child_ref.source_tree = '<group>'
223 last_child_ref = child_ref
224 end
225 end
226 ref.current_version = last_child_ref
227 end
228
229 parent_group = find_subpath(sub_group_path, true)
230 parent_group.children << ref
231 set_file_refenrece_name_if_needed(ref, parent_group)
232 ref
233 end
new_group(name, sub_group_path = nil) #=> PBXGroup
#to_s
name
The name of the new group.
String
sub_group_path
@see new_file
PBXGroup
The new group.
247 def new_group(name, sub_group_path = nil)
248 group = project.new(PBXGroup)
249 group.name = name
250
251 target = find_subpath(sub_group_path, true)
252 target.children << group
253 group
254 end
new_static_library(product_name, sub_group_path = nil) #=> PBXFileReference
#to_s
product_name
The name of the new static library.
String
sub_group_path
@see new_file
PBXFileReference
The new file reference.
268 def new_static_library(product_name, sub_group_path = nil)
269 file = new_file("lib#{product_name}.a", sub_group_path)
270 file.include_in_index = '0'
271 file.source_tree = 'BUILT_PRODUCTS_DIR'
272 file.explicit_file_type = file.last_known_file_type
273 file.last_known_file_type = nil
274 file
275 end
new_bundle(product_name) #=> PBXFileReference
#to_s
product_name
The name of the bundle.
PBXFileReference
The new file reference.
284 def new_bundle(product_name)
285 file = new_file("#{product_name}.bundle")
286 file.explicit_file_type = 'wrapper.cfbundle'
287 file.include_in_index = '0'
288 file.source_tree = 'BUILT_PRODUCTS_DIR'
289 file.last_known_file_type = nil
290 file
291 end
new_xcdatamodel_group(xcdatamodel_path) #=> XCVersionGroup
XCVersionGroup
The new group.
297 def new_xcdatamodel_group(xcdatamodel_path)
298 g = @project.new(XCVersionGroup)
299 g.path = xcdatamodel_path
300 g.version_group_type = 'wrapper.xcdatamodel'
301 file = g.new_file(xcdatamodel_path.sub(/xcdatamodeld$/, 'xcdatamodel'))
302 g.current_version = file
303 g
304 end
[](path) #=> undefined
311 def [](path)
312 find_subpath(path, false)
313 end
remove_children_recursively #=> undefined
317 def remove_children_recursively
318 groups.each do |g|
319 g.remove_children_recursively
320 g.remove_from_project
321 end
322 files.each { |f| f.remove_from_project }
323 end
find_subpath(path, should_create = false) #=> PBXGroup, Nil
String
path
A string with the names of the groups separated by a '/
'.
Boolean
should_create
Whether the path should be created.
PBXGroup
The group if found.
Nil
If the path could not be found and should create is false.
g = main_group['Frameworks']
g.name #=> 'Frameworks'
345 def find_subpath(path, should_create = false)
346 return self unless path
347 path = path.split('/') unless path.is_a?(Array)
348 child_name = path.shift
349 child = children.find{ |c| c.display_name == child_name }
350 if child.nil?
351 if should_create
352 child = new_group(child_name)
353 else
354 return nil
355 end
356 end
357 if path.empty?
358 child
359 else
360 child.find_subpath(path, should_create)
361 end
362 end
<<(child) #=> ObjectList<AbstractObject>
ObjectList
The children list.
368 def <<(child)
369 children << child
370 end
sort_by_type! #=> void
void
382 def sort_by_type!
383 children.sort! do |x, y|
384 if x.is_a?(PBXGroup) && y.is_a?(PBXFileReference)
385 -1
386 elsif x.is_a?(PBXFileReference) && y.is_a?(PBXGroup)
387 1
388 else
389 x.display_name <=> y.display_name
390 end
391 end
392 end
isa #=> String
String
The ISA of the class.
isa #=> String
String
The object's class name.
42 def self.isa
43 @isa ||= name.split('::').last
44 end
initialize(project, uuid) #=> AbstractObject
Project
project
The project that will host the object.
String
uuid
The UUID of the new object.
AbstractObject
A new instance of AbstractObject
64 def initialize(project, uuid)
65 @project, @uuid = project, uuid
66 @isa = self.class.isa
67 @referrers = []
68 raise "[Xcodeproj] Attempt to initialize an abstract class." unless @isa.match(/^(PBX|XC)/)
69 end
initialize_defaults #=> void
void
81 def initialize_defaults
82 simple_attributes.each { |a| a.set_default(self) }
83 end
uuid #=> String
String
The object universally unique identifier.
project #=> Project
Project
The project that owns the object.
remove_from_project #=> void
void
101 def remove_from_project
102 @project.objects_by_uuid.delete(uuid)
103 @referrers.each { |referrer| referrer.remove_reference(self) }
104 raise "[Xcodeproj] BUG: #{self} should have no referrers instead the following objects are still referencing it #{referrers}" unless referrers.count == 0
105 end
to_s #=> String
String
A name for the object.
124 def display_name
125 declared_name = name if self.respond_to?(:name)
126 if declared_name && !declared_name.empty?
127 declared_name
128 else
129 isa.gsub(/^(PBX|XC)/, '')
130 end
131 end
referrers #=> Array<ObjectList>
Array
The list of the objects that have a reference to this object.
add_referrer(referrer) #=> void
void
143 def add_referrer(referrer)
144 @referrers << referrer
145 @project.objects_by_uuid[uuid] = self
146 end
remove_referrer(referrer) #=> void
void
156 def remove_referrer(referrer)
157 @referrers.delete(referrer)
158 if @referrers.count == 0
159 @project.objects_by_uuid.delete(uuid)
160 end
161 end
remove_reference(object) #=> void
void
169 def remove_reference(object)
170 to_one_attributes.each do |attrb|
171 value = attrb.get_value(self)
172 attrb.set_value(self, nil) if value.equal?(object)
173 end
174
175 to_many_attributes.each do |attrb|
176 list = attrb.get_value(self)
177 list.delete(object)
178 end
179
180 references_by_keys_attributes.each do |attrb|
181 list = attrb.get_value(self)
182 list.each { |dictionary| dictionary.remove_reference(object) }
183 end
184 end
configure_with_plist(objects_by_uuid_plist) #=> void
void
202 def configure_with_plist(objects_by_uuid_plist)
203 object_plist = objects_by_uuid_plist[uuid].dup
204
205 raise "[Xcodeproj] Attempt to initialize `#{isa}` from plist with different isa `#{object_plist}`" unless object_plist['isa'] == isa
206 object_plist.delete('isa')
207
208 simple_attributes.each do |attrb|
209 attrb.set_value(self, object_plist[attrb.plist_name])
210 object_plist.delete(attrb.plist_name)
211 end
212
213 to_one_attributes.each do |attrb|
214 ref_uuid = object_plist[attrb.plist_name]
215 if ref_uuid
216 ref = object_with_uuid(ref_uuid, objects_by_uuid_plist, attrb)
217 attrb.set_value(self, ref) if ref
218 end
219 object_plist.delete(attrb.plist_name)
220 end
221
222 to_many_attributes.each do |attrb|
223 ref_uuids = object_plist[attrb.plist_name] || []
224 list = attrb.get_value(self)
225 ref_uuids.each do |uuid|
226 ref = object_with_uuid(uuid, objects_by_uuid_plist, attrb)
227 list << ref if ref
228 end
229 object_plist.delete(attrb.plist_name)
230 end
231
232 references_by_keys_attributes.each do |attrb|
233 hashes = object_plist[attrb.plist_name] || {}
234 list = attrb.get_value(self)
235 hashes.each do |hash|
236 dictionary = ObjectDictionary.new(attrb, self)
237 hash.each do |key, uuid|
238 ref = object_with_uuid(uuid, objects_by_uuid_plist, attrb)
239 dictionary[key] = ref if ref
240 end
241 list << dictionary
242 end
243 object_plist.delete(attrb.plist_name)
244 end
245
246 unless object_plist.empty?
247 raise "[!] Xcodeproj doesn't know about the following attributes " \
248 "#{object_plist.inspect} for the '#{isa}' isa.\n" \
249 "Please file an issue: https://github.com/CocoaPods/Xcodeproj/issues/new"
250 end
251 end
object_with_uuid(uuid, objects_by_uuid_plist, attribute) #=> AbstractObject, Nil
String
uuid
The UUID of the object that should be initialized.
Hash{String=>String}
objects_by_uuid_plist
The hash contained by objects
key of the plist containing
the information about the object that should be initialized.
AbstractObjectAttribute
attribute
The attribute that requested the object. It is used only for exceptions.
AbstractObject
The initialized object.
Nil
If the UUID could not be found in the objects hash. In this case a warning is printed to STDERR.
274 def object_with_uuid(uuid, objects_by_uuid_plist, attribute)
275 unless object = project.objects_by_uuid[uuid] || project.new_from_plist(uuid, objects_by_uuid_plist)
276 UI.warn "`#{inspect}` attempted to initialize an object with " \
277 "an unknown UUID. `#{uuid}` for attribute: `#{attribute.name}`."\
278 " This can be the result of a merge and the unknown UUID is " \
279 "being discarded."
280 end
281 object
282 rescue NameError
283 attributes = objects_by_uuid_plist[uuid]
284 raise "`#{isa}` attempted to initialize an object with unknown ISA "\
285 "`#{attributes['isa']}` from attributes: `#{attributes}`\n" \
286 "Please file an issue: https://github.com/CocoaPods/Xcodeproj/issues/new"
287 end
to_hash #=> Hash
Hash
A hash representation of the project.
299 def to_hash
300 plist = {}
301 plist['isa'] = isa
302
303 simple_attributes.each do |attrb|
304 value = attrb.get_value(self)
305 plist[attrb.plist_name] = value if value
306 end
307
308 to_one_attributes.each do |attrb|
309 obj = attrb.get_value(self)
310 plist[attrb.plist_name] = obj.uuid if obj
311 end
312
313 to_many_attributes.each do |attrb|
314 list = attrb.get_value(self)
315 plist[attrb.plist_name] = list.uuids
316 end
317
318 references_by_keys_attributes.each do |attrb|
319 list = attrb.get_value(self)
320 plist[attrb.plist_name] = list.map { |dictionary| dictionary.to_hash }
321 end
322
323 plist
324 end
to_tree_hash #=> Hash
Hash
A hash representation of the project different from the plist one.
339 def to_tree_hash
340 hash = {}
341 hash['displayName'] = display_name
342 hash['isa'] = isa
343
344 simple_attributes.each do |attrb|
345 value = attrb.get_value(self)
346 hash[attrb.plist_name] = value if value
347 end
348
349 to_one_attributes.each do |attrb|
350 obj = attrb.get_value(self)
351 hash[attrb.plist_name] = obj.to_tree_hash if obj
352 end
353
354 to_many_attributes.each do |attrb|
355 list = attrb.get_value(self)
356 hash[attrb.plist_name] = list.map { |obj| obj.to_tree_hash }
357 end
358
359 references_by_keys_attributes.each do |attrb|
360 list = attrb.get_value(self)
361 hash[attrb.plist_name] = list.map { |dictionary| dictionary.to_tree_hash }
362 end
363
364 hash
365 end
pretty_print #=> Hash{String => Hash}
Hash{String => Hash}
A hash suitable to display the object to the user.
370 def pretty_print
371 if to_many_attributes.count == 1
372 children = to_many_attributes.first.get_value(self)
373 {display_name => children.map(&:pretty_print)}
374 else
375 display_name
376 end
377 end
==(other) #=> undefined
385 def ==(other)
386 other.is_a?(AbstractObject) && self.to_hash == other.to_hash
387 end
<=>(other) #=> undefined
389 def <=>(other)
390 self.uuid <=> other.uuid
391 end
inspect #=> undefined
393 def inspect
394 name_part = " name=#{self.name}" if respond_to?(:name)
395 "<#{self.class}#{name_part} UUID=#{uuid}>"
396 end