好的!首先,问题不在于模拟器与 iPhone 的较量。相反,这是视网膜与非视网膜的对比。使用 Retina 版本时,模拟器中也会出现相同的症状。人们立刻开始认为解决方案与扩展有关。
Apple Dev Quartz 2D 论坛上的一篇非常有用的帖子(沿着类似的“注意缩放”路线)引导我找到了解决方案。现在,我第一个承认,这个解决方案并不漂亮,但它确实适用于视网膜和非视网膜情况。
这样,这是上述的修改后的代码CAL层扩展:
//
// Checks image at a point (and at a particular scale factor) for transparency.
// Point must be with origin at lower-left.
//
BOOL ImagePointIsTransparent(CGImageRef image, CGFloat scale, CGPoint point) {
unsigned char pixel[1] = {0};
CGContextRef context = CGBitmapContextCreate(pixel, 1, 1, 8, 1,
NULL, kCGImageAlphaOnly);
CGContextSetBlendMode(context, kCGBlendModeCopy);
CGContextDrawImage(context, CGRectMake(-point.x, -point.y,
CGImageGetWidth(image)/scale, CGImageGetHeight(image)/scale), image);
CGContextRelease(context);
CGFloat alpha = pixel[0]/255.0;
return (alpha < 0.01);
}
@implementation CALayer (Extensions)
- (BOOL)containsNonTransparentPoint:(CGPoint)point scale:(CGFloat)scale {
if (CGRectContainsPoint(self.bounds, point)) {
if (!ImagePointIsTransparent((CGImageRef)self.contents, scale, point))
return YES;
}
return NO;
}
@end
简而言之,我们需要了解规模。如果我们将图像宽度和高度除以该比例,那么命中测试现在可以在视网膜和非视网膜设备上运行!
我不喜欢的是我不得不把那个可怜的选择器弄得一团糟,现在称为包含非透明点:比例:。正如问题中提到的,永远无法保证图层的内容将包含什么。就我而言,我只在有 CGImageRef 的图层上使用它,但这在更通用/可重用的情况下不会起作用。
所有这些让我想知道 CALayer 是否不是这个特定扩展的最佳位置,至少在这个新版本中是这样。也许 CGImage 加上一些图层智能,会更干净。想象一下对 CGImage 进行命中测试,但返回当时具有非透明内容的第一层的名称。仍然存在不知道哪些层中有 CGImageRefs 的问题,因此可能需要一些提示。 (留给你自己和读者作为练习!)
UPDATE:在与 Apple 的开发人员进行一些讨论后,以这种方式搞乱层实际上是不明智的。与我之前学到的相反(错误?),封装在 UIView 中的多个 UIImageView 是这里的方法。 (我总是记得知道您希望将自己的观点保持在最低限度。也许在这种情况下,这没什么大不了的。)不过,我暂时将这个答案保留在这里,但不会将其标记为正确。一旦我尝试并验证了其他技术,我将在这里分享!