旋转 iPad 时自定义警报视图会导致崩溃
我在视图控制器中显示一个源自 UIAlertView 的自定义警报视图,当我旋转设备 2-3 次时,视图控制器和警报视图都会旋转。但随后应用程序崩溃了,没有任何明确的线索。我在所有异常上有一个断点,但它无法捕获它。
如果我使用标准 UIAlertView,则不会发生此崩溃。我从其他人那里找到了自定义警报视图的代码。这里有什么执行错误的地方吗?或者我怎样才能获得更多关于正在发生的事情的线索?
@implementation CustomAlertView
- (void) setBackgroundColor:(UIColor *) background
withStrokeColor:(UIColor *) stroke
{
if(fillColor != nil)
{
[fillColor release];
[borderColor release];
}
fillColor = [background retain];
borderColor = [stroke retain];
}
- (id)initWithFrame:(CGRect)frame
{
if((self = [super initWithFrame:frame]))
{
if(fillColor == nil)
{
}
}
return self;
}
- (void)layoutSubviews
{
for (UIView *sub in [self subviews])
{
if([sub class] == [UIImageView class] && sub.tag == 0)
{
// The alert background UIImageView tag is 0,
// if you are adding your own UIImageView's
// make sure your tags != 0 or this fix
// will remove your UIImageView's as well!
[sub removeFromSuperview];
break;
}
}
}
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, rect);
CGContextSetAllowsAntialiasing(context, true);
CGContextSetLineWidth(context, 0.0);
CGContextSetAlpha(context, 0.8);
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [borderColor CGColor]);
CGContextSetFillColorWithColor(context, [fillColor CGColor]);
// Draw background
CGFloat backOffset = 2;
CGRect backRect = CGRectMake(rect.origin.x + backOffset,
rect.origin.y + backOffset,
rect.size.width - backOffset*2,
rect.size.height - backOffset*2);
[self drawRoundedRect:backRect inContext:context withRadius:8];
CGContextDrawPath(context, kCGPathFillStroke);
// Clip Context
CGRect clipRect = CGRectMake(backRect.origin.x + backOffset-1,
backRect.origin.y + backOffset-1,
backRect.size.width - (backOffset-1)*2,
backRect.size.height - (backOffset-1)*2);
[self drawRoundedRect:clipRect inContext:context withRadius:8];
CGContextClip (context);
//Draw highlight
CGGradientRef glossGradient;
CGColorSpaceRef rgbColorspace;
size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 1.0, 1.0, 1.0, 0.35, 1.0, 1.0, 1.0, 0.06 };
rgbColorspace = CGColorSpaceCreateDeviceRGB();
glossGradient = CGGradientCreateWithColorComponents(rgbColorspace,
components, locations, num_locations);
CGRect ovalRect = CGRectMake(-130, -115, (rect.size.width*2),
rect.size.width/2);
CGPoint start = CGPointMake(rect.origin.x, rect.origin.y);
CGPoint end = CGPointMake(rect.origin.x, rect.size.height/5);
CGContextSetAlpha(context, 1.0);
CGContextAddEllipseInRect(context, ovalRect);
CGContextClip (context);
CGContextDrawLinearGradient(context, glossGradient, start, end, 0);
CGGradientRelease(glossGradient);
CGColorSpaceRelease(rgbColorspace);
}
- (void) drawRoundedRect:(CGRect) rrect inContext:(CGContextRef) context
withRadius:(CGFloat) radius
{
CGContextBeginPath (context);
CGFloat minx = CGRectGetMinX(rrect), midx = CGRectGetMidX(rrect),
maxx = CGRectGetMaxX(rrect);
CGFloat miny = CGRectGetMinY(rrect), midy = CGRectGetMidY(rrect),
maxy = CGRectGetMaxY(rrect);
CGContextMoveToPoint(context, minx, midy);
CGContextAddArcToPoint(context, minx, miny, midx, miny, radius);
CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius);
CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius);
CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius);
CGContextClosePath(context);
}
- (void)disableDismissForIndex:(int)index_{
canIndex = index_;
disableDismiss = TRUE;
}
- (void)dismissAlert{
[self dismissWithClickedButtonIndex:[self cancelButtonIndex] animated:YES];
}
- (void)vibrateAlert:(float)seconds{
canVirate = TRUE;
[self moveLeft];
[self performSelector:@selector (stopVibration) withObject:nil afterDelay:seconds];
}
-(void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated {
if (disableDismiss == TRUE && canIndex == buttonIndex){
}else {
[super dismissWithClickedButtonIndex:buttonIndex animated:animated];
}
}
- (void)hideAfter:(float)seconds{
[self performSelector:@selector (dismissAlert) withObject:nil afterDelay:seconds];
}
- (void)moveRight{
if (canVirate){
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.05];
self.transform = CGAffineTransformMakeTranslation(-10.0, 0.0);
[UIView commitAnimations];
[self performSelector:@selector (moveLeft) withObject:nil afterDelay:0.05];
}
}
- (void)moveLeft{
if (canVirate){
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.05];
self.transform = CGAffineTransformMakeTranslation(10.0, 0.0);
[UIView commitAnimations];
[self performSelector:@selector (moveRight) withObject:nil afterDelay:0.05];
}
}
- (void)stopVibration{
canVirate = FALSE;
self.transform = CGAffineTransformMakeTranslation(0.0, 0.0);
}
@end
I am showing a custom alert view which is derived from UIAlertView in my view controller, and when I rotate the device for like 2-3 times, both the view controller and the alert view gets rotated. But then the app crashes with no clear clues. I have a breakpoint on All Exceptions but it can't catch it.
This crash is not happening if I use a standard UIAlertView. I found the custom alertview's code from someone else. Is there something misimplemented here? Or how can I get more clues of what's happening?
@implementation CustomAlertView
- (void) setBackgroundColor:(UIColor *) background
withStrokeColor:(UIColor *) stroke
{
if(fillColor != nil)
{
[fillColor release];
[borderColor release];
}
fillColor = [background retain];
borderColor = [stroke retain];
}
- (id)initWithFrame:(CGRect)frame
{
if((self = [super initWithFrame:frame]))
{
if(fillColor == nil)
{
}
}
return self;
}
- (void)layoutSubviews
{
for (UIView *sub in [self subviews])
{
if([sub class] == [UIImageView class] && sub.tag == 0)
{
// The alert background UIImageView tag is 0,
// if you are adding your own UIImageView's
// make sure your tags != 0 or this fix
// will remove your UIImageView's as well!
[sub removeFromSuperview];
break;
}
}
}
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, rect);
CGContextSetAllowsAntialiasing(context, true);
CGContextSetLineWidth(context, 0.0);
CGContextSetAlpha(context, 0.8);
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColorWithColor(context, [borderColor CGColor]);
CGContextSetFillColorWithColor(context, [fillColor CGColor]);
// Draw background
CGFloat backOffset = 2;
CGRect backRect = CGRectMake(rect.origin.x + backOffset,
rect.origin.y + backOffset,
rect.size.width - backOffset*2,
rect.size.height - backOffset*2);
[self drawRoundedRect:backRect inContext:context withRadius:8];
CGContextDrawPath(context, kCGPathFillStroke);
// Clip Context
CGRect clipRect = CGRectMake(backRect.origin.x + backOffset-1,
backRect.origin.y + backOffset-1,
backRect.size.width - (backOffset-1)*2,
backRect.size.height - (backOffset-1)*2);
[self drawRoundedRect:clipRect inContext:context withRadius:8];
CGContextClip (context);
//Draw highlight
CGGradientRef glossGradient;
CGColorSpaceRef rgbColorspace;
size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 1.0, 1.0, 1.0, 0.35, 1.0, 1.0, 1.0, 0.06 };
rgbColorspace = CGColorSpaceCreateDeviceRGB();
glossGradient = CGGradientCreateWithColorComponents(rgbColorspace,
components, locations, num_locations);
CGRect ovalRect = CGRectMake(-130, -115, (rect.size.width*2),
rect.size.width/2);
CGPoint start = CGPointMake(rect.origin.x, rect.origin.y);
CGPoint end = CGPointMake(rect.origin.x, rect.size.height/5);
CGContextSetAlpha(context, 1.0);
CGContextAddEllipseInRect(context, ovalRect);
CGContextClip (context);
CGContextDrawLinearGradient(context, glossGradient, start, end, 0);
CGGradientRelease(glossGradient);
CGColorSpaceRelease(rgbColorspace);
}
- (void) drawRoundedRect:(CGRect) rrect inContext:(CGContextRef) context
withRadius:(CGFloat) radius
{
CGContextBeginPath (context);
CGFloat minx = CGRectGetMinX(rrect), midx = CGRectGetMidX(rrect),
maxx = CGRectGetMaxX(rrect);
CGFloat miny = CGRectGetMinY(rrect), midy = CGRectGetMidY(rrect),
maxy = CGRectGetMaxY(rrect);
CGContextMoveToPoint(context, minx, midy);
CGContextAddArcToPoint(context, minx, miny, midx, miny, radius);
CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius);
CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius);
CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius);
CGContextClosePath(context);
}
- (void)disableDismissForIndex:(int)index_{
canIndex = index_;
disableDismiss = TRUE;
}
- (void)dismissAlert{
[self dismissWithClickedButtonIndex:[self cancelButtonIndex] animated:YES];
}
- (void)vibrateAlert:(float)seconds{
canVirate = TRUE;
[self moveLeft];
[self performSelector:@selector (stopVibration) withObject:nil afterDelay:seconds];
}
-(void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated {
if (disableDismiss == TRUE && canIndex == buttonIndex){
}else {
[super dismissWithClickedButtonIndex:buttonIndex animated:animated];
}
}
- (void)hideAfter:(float)seconds{
[self performSelector:@selector (dismissAlert) withObject:nil afterDelay:seconds];
}
- (void)moveRight{
if (canVirate){
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.05];
self.transform = CGAffineTransformMakeTranslation(-10.0, 0.0);
[UIView commitAnimations];
[self performSelector:@selector (moveLeft) withObject:nil afterDelay:0.05];
}
}
- (void)moveLeft{
if (canVirate){
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.05];
self.transform = CGAffineTransformMakeTranslation(10.0, 0.0);
[UIView commitAnimations];
[self performSelector:@selector (moveRight) withObject:nil afterDelay:0.05];
}
}
- (void)stopVibration{
canVirate = FALSE;
self.transform = CGAffineTransformMakeTranslation(0.0, 0.0);
}
@end
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,现在我找到了。在layoutViews方法中,用
((UIImageView*)sub).image = nil;替换
[sub removeFromSuperview];
行为我解决了这个问题。但我仍然不确定确切的原因。OK now I found it. In layoutViews method, replacing
[sub removeFromSuperview];
line with((UIImageView*)sub).image = nil;
fixed the problem for me. Still I'm not sure about the exact reason though.