Xcodeproj 添加自定义 属性 到对象
Xcodeproj add custom property to object
我想以编程方式将 onlyGenerateCoverageForSpecifiedTargets
属性 添加到 TestAction 对象。根据 documentation 这个 属性 还不被支持。所以我需要给一个对象添加一个自定义的属性。我还需要添加 CodeCoverageTargets
组。
这是我的代码:
scheme = Xcodeproj::XCScheme.new
scheme.add_build_target(app_target)
scheme.set_launch_target(app_target)
scheme.add_test_target(target)
test_action = scheme.test_action
test_action.code_coverage_enabled = true
# add onlyGenerateCoverageForSpecifiedTargets = true
scheme.test_action = test_action
scheme.save_as(xcode_proj_dir, name)
这是我从 Xcode GUI 添加 属性 时的 xml 结构。
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES"
onlyGenerateCoverageForSpecifiedTargets = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D7CE66BC1C7DE6F700FC64CC"
BuildableName = "AppName.app"
BlueprintName = "AppName"
ReferencedContainer = "container:buddyui.xcodeproj">
</BuildableReference>
</MacroExpansion>
<CodeCoverageTargets>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D7CE66BC1C7DE6F700FC64CC"
BuildableName = "AppName.app"
BlueprintName = "AppName"
ReferencedContainer = "container:buddyui.xcodeproj">
</BuildableReference>
</CodeCoverageTargets>
您可以简单地创建一个模块来添加您想要的行为(即您的方法),但我不确定这是否会解决您的实际问题
module AddOnlyGenerateCoverageForSpecifiedTargets
attr_accessor :only_generate_coverage_for_specified_targets
end
然后将模块包含在您想要的 class 中。要仅将其包含在一个对象中,请将其包含在其 singleton_class:
中
test_action.singleton_class.include AddOnlyGenerateCoverageForSpecifiedTargets
# Now you can use it
test_action.only_generate_coverage_for_specified_targets = true
我先声明:我对 Xcodeproj Gem 和 Xcode 元数据背后的逻辑一无所知。将我的代码作为进一步改进的起点。
您有几种方法可以实现您的要求:
MonkeyPatch Xcode项目。这就是我所做的,对此感到抱歉:-P
扩展 Xcode项目 classes。这将是推荐的解决方案。
直接操作XML文件或XCScheme对象,用REXML.
我的提案来了。我在 TestAction
中添加了一些方法(基于类似现有方法的代码)并创建了额外的 class CodeCoverageTargets
(基于 class MacroExpansion
) .因为我不知道 Xcode 是如何工作的,所以我选择在 XCScheme
中创建方法 add_code_coverage_targets
而不是覆盖 set_launch_target
(实例化 MacroExpansion
的地方)。
require 'xcodeproj'
class Xcodeproj::XCScheme
def add_code_coverage_targets(build_target)
code_cov_targets = CodeCoverageTargets.new(build_target)
test_action.add_code_coverage_targets(code_cov_targets)
end
class CodeCoverageTargets < XMLElementWrapper
def initialize(target_or_node = nil)
create_xml_element_with_fallback(target_or_node, 'CodeCoverageTargets') do
self.buildable_reference = BuildableReference.new(target_or_node) if target_or_node
end
end
def buildable_reference
@buildable_reference ||= BuildableReference.new @xml_element.elements['BuildableReference']
end
def buildable_reference=(ref)
@xml_element.delete_element('BuildableReference')
@xml_element.add_element(ref.xml_element)
@buildable_reference = ref
end
end
class TestAction
def only_generate_coverage_for_specified_targets?
string_to_bool(@xml_element.attributes['onlyGenerateCoverageForSpecifiedTargets'])
end
def only_generate_coverage_for_specified_targets=(flag)
@xml_element.attributes['onlyGenerateCoverageForSpecifiedTargets'] = bool_to_string(flag)
end
def code_coverage_targets
@xml_element.get_elements('CodeCoverageTargets').map do |node|
CodeCoverageTargets.new(node)
end
end
def add_code_coverage_targets(code_coverage_targets)
@xml_element.add_element(code_coverage_targets.xml_element)
end
end
end
你可以这样使用它:
xcode_proj_dir = 'Desktop/SO/66719313/DummyApp.xcodeproj'
xcode_proj = Xcodeproj::Project.open(xcode_proj_dir)
app_target = xcode_proj.targets.first
scheme = Xcodeproj::XCScheme.new
scheme.add_build_target(app_target)
scheme.set_launch_target(app_target)
#scheme.add_test_target(app_target)
scheme.add_code_coverage_targets(app_target) # new method
test_action = scheme.test_action
test_action.code_coverage_enabled = true
test_action.only_generate_coverage_for_specified_targets = true # new method
puts test_action
我想以编程方式将 onlyGenerateCoverageForSpecifiedTargets
属性 添加到 TestAction 对象。根据 documentation 这个 属性 还不被支持。所以我需要给一个对象添加一个自定义的属性。我还需要添加 CodeCoverageTargets
组。
这是我的代码:
scheme = Xcodeproj::XCScheme.new
scheme.add_build_target(app_target)
scheme.set_launch_target(app_target)
scheme.add_test_target(target)
test_action = scheme.test_action
test_action.code_coverage_enabled = true
# add onlyGenerateCoverageForSpecifiedTargets = true
scheme.test_action = test_action
scheme.save_as(xcode_proj_dir, name)
这是我从 Xcode GUI 添加 属性 时的 xml 结构。
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES"
onlyGenerateCoverageForSpecifiedTargets = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D7CE66BC1C7DE6F700FC64CC"
BuildableName = "AppName.app"
BlueprintName = "AppName"
ReferencedContainer = "container:buddyui.xcodeproj">
</BuildableReference>
</MacroExpansion>
<CodeCoverageTargets>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D7CE66BC1C7DE6F700FC64CC"
BuildableName = "AppName.app"
BlueprintName = "AppName"
ReferencedContainer = "container:buddyui.xcodeproj">
</BuildableReference>
</CodeCoverageTargets>
您可以简单地创建一个模块来添加您想要的行为(即您的方法),但我不确定这是否会解决您的实际问题
module AddOnlyGenerateCoverageForSpecifiedTargets
attr_accessor :only_generate_coverage_for_specified_targets
end
然后将模块包含在您想要的 class 中。要仅将其包含在一个对象中,请将其包含在其 singleton_class:
中test_action.singleton_class.include AddOnlyGenerateCoverageForSpecifiedTargets
# Now you can use it
test_action.only_generate_coverage_for_specified_targets = true
我先声明:我对 Xcodeproj Gem 和 Xcode 元数据背后的逻辑一无所知。将我的代码作为进一步改进的起点。
您有几种方法可以实现您的要求:
MonkeyPatch Xcode项目。这就是我所做的,对此感到抱歉:-P
扩展 Xcode项目 classes。这将是推荐的解决方案。
直接操作XML文件或XCScheme对象,用REXML.
我的提案来了。我在 TestAction
中添加了一些方法(基于类似现有方法的代码)并创建了额外的 class CodeCoverageTargets
(基于 class MacroExpansion
) .因为我不知道 Xcode 是如何工作的,所以我选择在 XCScheme
中创建方法 add_code_coverage_targets
而不是覆盖 set_launch_target
(实例化 MacroExpansion
的地方)。
require 'xcodeproj'
class Xcodeproj::XCScheme
def add_code_coverage_targets(build_target)
code_cov_targets = CodeCoverageTargets.new(build_target)
test_action.add_code_coverage_targets(code_cov_targets)
end
class CodeCoverageTargets < XMLElementWrapper
def initialize(target_or_node = nil)
create_xml_element_with_fallback(target_or_node, 'CodeCoverageTargets') do
self.buildable_reference = BuildableReference.new(target_or_node) if target_or_node
end
end
def buildable_reference
@buildable_reference ||= BuildableReference.new @xml_element.elements['BuildableReference']
end
def buildable_reference=(ref)
@xml_element.delete_element('BuildableReference')
@xml_element.add_element(ref.xml_element)
@buildable_reference = ref
end
end
class TestAction
def only_generate_coverage_for_specified_targets?
string_to_bool(@xml_element.attributes['onlyGenerateCoverageForSpecifiedTargets'])
end
def only_generate_coverage_for_specified_targets=(flag)
@xml_element.attributes['onlyGenerateCoverageForSpecifiedTargets'] = bool_to_string(flag)
end
def code_coverage_targets
@xml_element.get_elements('CodeCoverageTargets').map do |node|
CodeCoverageTargets.new(node)
end
end
def add_code_coverage_targets(code_coverage_targets)
@xml_element.add_element(code_coverage_targets.xml_element)
end
end
end
你可以这样使用它:
xcode_proj_dir = 'Desktop/SO/66719313/DummyApp.xcodeproj'
xcode_proj = Xcodeproj::Project.open(xcode_proj_dir)
app_target = xcode_proj.targets.first
scheme = Xcodeproj::XCScheme.new
scheme.add_build_target(app_target)
scheme.set_launch_target(app_target)
#scheme.add_test_target(app_target)
scheme.add_code_coverage_targets(app_target) # new method
test_action = scheme.test_action
test_action.code_coverage_enabled = true
test_action.only_generate_coverage_for_specified_targets = true # new method
puts test_action