UISwitch setThumbTintColor导致崩溃(iOS 6专用)?

18

更新:收到了苹果发送的邮件,称该漏洞/问题已经修复,下一个SDK版本将不再存在此问题。和平!

我在AppDelegate的代码中有这个内容:

- (void) customizeAppearance {
    [[UISwitch appearance] setOnTintColor:[UIColor colorWithRed:0 green:175.0/255.0 blue:176.0/255.0 alpha:1.0]];
    [[UISwitch appearance] setTintColor:[UIColor colorWithRed:255.0f/255.0f green:255.0f/255.0f blue:255.0f/255.0f alpha:1.000f]];
    [[UISwitch appearance] setThumbTintColor:[UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1.0]];
 }

我随后从 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 中调用了它。

我也使用ARC。在iOS 6中,我的应用程序一直崩溃。我启用了NSZombie并且它不断地显示:*** -[UIDeviceRGBColor release]: message sent to deallocated instance 0x9658eb0

现在我已经意识到上述问题的一个完美可重现流程。当我仅在customizeAppearance函数内注释掉setThumbTintColor代码行时,一切都正常工作。当我改用setThumbTintColor时,应用程序每次都以相同的方式崩溃。

如果UISwitch/setThumbTintColor/UIColor的问题对任何人来说已经是众所周知的,请告诉我。如果不是开关颜色,还可能是什么原因?


1
我不知道为什么会发生这种情况,但如果您可以在一个基本的示例应用程序中重现此问题,您可能需要在http://bugreport.apple.com上发布一个错误报告。 - Michael Ochs
雷达有任何更新吗?我能够稳定地复现它。 - user246672
很可能,苹果的代码包含了一个应该是强引用而不是弱引用的问题,因为当thumbTintColor设置为[UIColor redColor]时没有出现错误。 - user246672
这是我很久以前提交的雷达。如果你也遇到了这个问题,请复制它。rdar://12562867 - Bourne
非常感谢。这个链接让我找到了UISwitch Bug,否则我可能要搜索很久。 - palme
显示剩余5条评论
3个回答

19

我也在做这个教程,遇到了同样的问题。(不知道为什么你没有经历这个问题,因为我手动输入代码和解决方案代码都对我有同样的问题?)

第一个转场还好,但回退后下一个转场就失败了。

设置全局异常断点后,当生成异常时,可以看到调用栈中的thumbColorTint。我猜测对象被释放得太早了。为了解决这个问题,我在我的应用程序委托中创建了一个属性...(你不需要在应用程序委托中创建,只需在设置UISwitch外观的对象中创建,对我而言就是应用程序委托)

@interface SurfsUpAppDelegate()
@property (strong, nonatomic) UIColor *thumbTintColor;
@end

然后我这样设置

[self setThumbTintColor:[UIColor colorWithRed:0.211 green:0.550 blue:1.000 alpha:1.000]];
[[UISwitch appearance] setThumbTintColor:[self thumbTintColor]];

现在一切都按预期运行,因为对象没有被提前释放。这可能是一个缺陷,即使对象仍然需要使用它也被释放了。UISwitch在API方面似乎有一个缺陷 :(


这解决了问题。因此被接受。我还找到了另一种解决方法。将开关的父视图设置为strong也可以防止崩溃。无论如何,我还是提交了一个带有示例项目的错误报告,因为除了开关以外的任何其他UI元素都似乎不会出现这种情况,而且只有在设置thumbTintColor属性时才会发生。 - Bourne
1
我也有同样的问题。Bill和Bourne的解决方案对我都有效。然而,我还有另一个项目,其中包含一个导航控制器。堆栈中有5个视图控制器,有时视图可能会被推入/弹出。当任一场景包含开关时,以上解决方案均无效。我认为我们只能等待苹果修复这个问题。 - Wayne Liu
1
这个解决方法对我似乎没有任何影响。无论我如何设置thumbTintColor,当开关实例被dealloc时,我的应用程序都会崩溃。 - metatation
抱歉,它并不适用于所有情况。我怀疑在某些情况下它被正确释放,而在其他情况下则没有(正如Wayne所指出的)。一次性解决这个问题的方法是修复一个漏洞。NONT提出了一个很好的建议,但当它被修复后可能会失败。像这样的内存问题很难进行追溯修复。 - maninvan

3

我也遇到了苹果的UISwitch过度释放的这个问题。我有一个类似的解决方案,但我认为它更好一些,因为它不需要添加额外的属性:

UIColor *thumbTintColor =  [[UIColor alloc] initWithRed:red green:green blue:blue alpha:alpha]];

//we're calling retain even though we're in ARC,
// but the compiler doesn't know that

[thumbTintColor performSelector:NSSelectorFromString(@"retain")]; //generates warning, but OK
[[UISwitch appearance] setThumbTintColor:[self thumbTintColor]];

不利的一面是,它确实会创建一个编译警告,但这里确实存在一个错误,只是不是我们的错误!


1
目前,我按照Bill的回答进行操作:

// SomeClass.m

@interface SomeClass ()

// ...

@property (weak,   nonatomic) IBOutlet UISwitch *thumbControl;
@property (strong, nonatomic)           UIColor *thumbControlThumbTintColor;

// ...

@end

@implementation SomeClass

// ...

- (void)viewDidLoad
{
    // ...

    self.thumbControl.thumbTintColor = self.thumbControlThumbTintColor = [UIColor colorWithRed:0.2 green:0.0 blue:0.0 alpha:1.0];

    // ...
}

// ...

@end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接