class Xcodeproj::Project::PBXObject
def self.attribute(attribute_name, accessor_name = nil)
def self.attribute(attribute_name, accessor_name = nil) attribute_name = attribute_name.to_s name = (accessor_name || attribute_name).to_s define_method(name) { @attributes[attribute_name] } define_method("#{name}=") { |value| @attributes[attribute_name] = value } end
def self.attributes(*names)
def self.attributes(*names) names.each { |name| attribute(name) } end
def self.create_reflection(name, options)
def self.create_reflection(name, options) (reflections << AssociationReflection.new(name, options)).last end
def self.has_many(plural_attr_name, options = {}, &block)
def self.has_many(plural_attr_name, options = {}, &block) reflection = create_reflection(plural_attr_name, options) if reflection.inverse? define_method(reflection.name) do scoped = @project.objects.select_by_class(reflection.klass).select do |object| object.send(reflection.inverse.uuid_getter) == self.uuid end PBXObjectList.new(reflection.klass, @project, scoped) do |object| object.send(reflection.inverse.uuid_setter, self.uuid) end end else attribute(reflection.name, reflection.uuids_getter) define_method(reflection.name) do uuids = send(reflection.uuids_getter) if block # Evaluate the block, which was specified at the class level, in # the instance’s context. list_by_class(uuids, reflection.klass) do |object| instance_exec(object, &block) end else list_by_class(uuids, reflection.klass) end end define_method(reflection.plural_setter) do |objects| send(reflection.uuids_setter, objects.map(&:uuid)) end end end
def self.has_one(singular_attr_name, options = {})
def self.has_one(singular_attr_name, options = {}) reflection = create_reflection(singular_attr_name, options) if reflection.inverse? define_method(reflection.name) do # Loop over all objects of the class and find the one that includes # this object in the specified uuid list. @project.objects.select_by_class(reflection.klass).find do |object| object.send(reflection.inverse.uuids_getter).include?(self.uuid) end end define_method(reflection.singular_setter) do |object| # Remove this object from the uuid list of the target # that this object was associated to. if previous = send(reflection.name) previous.send(reflection.inverse.uuids_getter).delete(self.uuid) end # Now assign this object to the new object object.send(reflection.inverse.uuids_getter) << self.uuid if object end else attribute(reflection.uuid_attribute, reflection.uuid_getter) define_method(reflection.name) do @project.objects[send(reflection.uuid_getter)] end define_method(reflection.singular_setter) do |object| send(reflection.uuid_setter, object.uuid) end end end
def self.isa
def self.isa @isa ||= name.split('::').last end
def self.reflection(name)
def self.reflection(name) reflections.find { |r| r.name.to_s == name.to_s } end
def self.reflections
def self.reflections @reflections ||= [] end
def ==(other)
def ==(other) other.is_a?(PBXObject) && self.uuid == other.uuid end
def generate_uuid
def generate_uuid _uuid = CFUUIDCreate(nil) uuid = CFUUIDCreateString(nil, _uuid) CFRelease(_uuid) CFMakeCollectable(uuid) # Xcode's version is actually shorter, not worrying about collisions too much right now. uuid.gsub('-', '')[0..23] end
def initialize(project, uuid, attributes)
def initialize(project, uuid, attributes) @project, @attributes = project, attributes unless uuid # Add new objects to the main hash with a unique UUID begin; uuid = generate_uuid; end while @project.objects_hash.has_key?(uuid) @project.objects_hash[uuid] = @attributes end @uuid = uuid self.isa ||= self.class.isa end
def inspect
def inspect "#<#{isa} UUID: `#{uuid}', name: `#{name}'>" end
def list_by_class(uuids, klass, scoped = nil, &block)
def list_by_class(uuids, klass, scoped = nil, &block) unless scoped scoped = uuids.map { |uuid| @project.objects[uuid] }.select { |o| o.is_a?(klass) } end if block PBXObjectList.new(klass, @project, scoped, &block) else PBXObjectList.new(klass, @project, scoped) do |object| # Add the uuid of a newly created object to the uuids list uuids << object.uuid end end end