自定义XCTApplicationLaunchMetric的XCTMetric方法未触发问题
自定义XCTMetric协议类未触发协议方法的问题解决
我想要获取XCTApplicationLaunchMetric上报的测量数据,于是封装了一个遵循XCTMetric协议的自定义类MyXCTApplicationLaunchMetric,内部调用XCTApplicationLaunchMetric的相关方法,代码如下:
class MyXCTApplicationLaunchMetric: NSObject, XCTMetric { let myLaunchMetric: XCTApplicationLaunchMetric init(waitUntilResponsive: Bool) { print(#function) myLaunchMetric = XCTApplicationLaunchMetric(waitUntilResponsive: waitUntilResponsive) } // XCTMetric conformance func willBeginMeasuring() { print(#function) myLaunchMetric.willBeginMeasuring() } // XCTMetric conformance func didStopMeasuring() { print(#function) myLaunchMetric.didStopMeasuring() } // XCTMetric conformance func reportMeasurements(from startTime: XCTPerformanceMeasurementTimestamp, to endTime: XCTPerformanceMeasurementTimestamp) throws -> [XCTPerformanceMeasurement] { let measurement = Measurement(value: 40, unit: .init(symbol: "M")) let performanceMeasurement = XCTPerformanceMeasurement(identifier: "SomeIdentifier", displayName: "SomeDisplayName", value: measurement) return [performanceMeasurement] } // NSObject conformance func copy(with zone: NSZone? = nil) -> Any { myLaunchMetric.copy(with: zone) } }
但在测试代码中使用这个自定义指标时,只有初始化方法被调用,其他XCTMetric协议方法都没触发,测试代码如下:
final class PerformanceUITests: XCTestCase { func testLaunchPerformance() throws { if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { let options = XCTMeasureOptions() options.iterationCount = 1 let launchMetric = MyXCTApplicationLaunchMetric(waitUntilResponsive: true) measure(metrics: [launchMetric], options: options) { XCUIApplication().launch() } } } }
问题原因
- XCTest框架在执行
measure(metrics:options:block:)时,会对传入的XCTMetric实例执行拷贝操作,而你的copy(with:)方法直接返回了内部封装的myLaunchMetric(原生XCTApplicationLaunchMetric实例),导致实际参与测量的是原生类实例,而非自定义类实例,自然不会触发自定义类中的协议方法。 - 自定义类的
copy(with:)方法未遵循NSCopying协议要求,没有返回当前自定义类的拷贝实例。
解决方案
1. 修正拷贝方法
修改copy(with:)方法,返回自定义类的拷贝实例,确保XCTest框架使用的是你的自定义类对象:
func copy(with zone: NSZone? = nil) -> Any { let copiedMetric = MyXCTApplicationLaunchMetric(waitUntilResponsive: myLaunchMetric.waitUntilResponsive) return copiedMetric }
2. 正确获取原生测量数据(可选)
如果你需要获取XCTApplicationLaunchMetric的原生测量数据,可以在reportMeasurements方法中调用原生metric的对应方法,再对结果进行自定义处理:
func reportMeasurements(from startTime: XCTPerformanceMeasurementTimestamp, to endTime: XCTPerformanceMeasurementTimestamp) throws -> [XCTPerformanceMeasurement] { // 获取原生指标的测量数据 let originalMeasurements = try myLaunchMetric.reportMeasurements(from: startTime, to: endTime) // 自定义处理逻辑:比如添加自定义测量数据 let customMeasurement = Measurement(value: 40, unit: .init(symbol: "M")) let customPerformanceMeasurement = XCTPerformanceMeasurement(identifier: "SomeIdentifier", displayName: "SomeDisplayName", value: customMeasurement) // 返回原生数据+自定义数据 return originalMeasurements + [customPerformanceMeasurement] }
内容的提问来源于stack exchange,提问作者fingia
相关产品推荐
相关产品推荐

