我已经在一个应用程序上工作了几个月,但最终遇到了一个我自己无法解决的问题,并且在互联网上找不到任何可以帮助的东西。
我在我的应用程序中使用了几个普通的 UIAlertViews。有些有 2 个按钮,有些有 3 个按钮,还有一些有 2 个按钮和一个文本字段。但是,所有人都有相同的问题。当你调用 [someAlertView show]; 警报视图显示正常,但突然它的图形上下文似乎已损坏,如您从屏幕截图中看到的那样。
这在 iPhone 和 iPad 模拟器(5.0 和 5.1)上都会发生,在 iPad 和 iPhone4S 设备上也会发生。
显示的图像是发生在 alertView 后面的任何内容。
警报仍然有效,我可以单击按钮,在文本字段中输入,然后当它关闭时,委托方法被正确调用,一切恢复正常。当 alertView 再次出现时,同样的事情发生了。
警报背后的视图是一个自定义 UIScrollView 子类,其内容大小约为 4000 x 1000 像素,以 UIImage 作为背景。png 文件大部分是透明的,因此内存大小只有 80kB 左右,手机在渲染它时没有问题 - 滚动视图仍然完全响应且不慢。作为子类的一部分,它还附加了一个 CADisplayLink 计时器。我曾尝试在显示 alertView 之前禁用它,但这没有任何区别,所以我怀疑这是问题所在。
这个应用程序是我为一个大学项目制作的一个应用程序的部分重写,它可以在相同大小和子类的滚动视图的顶部显示 UIAlertViews 而不会出现问题。这个应用程序和那个应用程序之间的区别在于,在我的旧应用程序中,我将 UIAlertView 子类化以添加额外的东西,例如pickerView,但是我决定我不喜欢它的外观,所以将所有内容都从警报中移出只是坚持使用标准的 UIAlertView。
截图中的 alertView 是这样调用的:
- (IBAction)loadSimulation:(id)sender {
importAlert = [[UIAlertView alloc] initWithTitle:@"Load Simulation" message:@"Enter Filename:" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Load", nil];
[importAlert setAlertViewStyle:UIAlertViewStylePlainTextInput];
[importAlert showPausingSimulation:self.simulationView]; //Calling [importAlert show]; makes no difference.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
[self hideOrganiser]; //Not an issue as the problem occurs on iPad as well.
}
}
这是分类的 AlertView 以添加停止 scrollViews CADisplay 链接的能力。
@interface UIAlertView(pauseDisplayLink)
- (void)showPausingSimulation:(UILogicSimulatorView*)simulationView;
@end
@implementation UIAlertView(pauseDisplayLink)
- (void)showPausingSimulation:(UILogicSimulatorView *)simulationView {
[simulationView stopRunning];
[simulationView removeDisplayLink]; //displayLink needs to be removed from the run loop, otherwise it will keep going in the background and get corrupted.
[self show];
}
发生这种情况时,我没有收到任何内存警告,所以我怀疑这是由于缺乏资源。
有没有人遇到过这样的问题?如果您需要更多信息,我可以尝试提供,但我可以发布的代码有限。任何帮助将不胜感激,我已经尝试解决这个问题两周但无法解决。
编辑:看起来它根本不是 AlertView(或者更确切地说它不仅仅是 alertView),因为当我删除它后面的滚动视图时问题就消失了,所以两者之间一定存在一些问题。这是我的 UIScrollView 子类的代码:.h 文件:#import #import
@class ECSimulatorController;
@interface UILogicSimulatorView : UIScrollView {
CADisplayLink *displayLink;
NSInteger _updateRate;
ECSimulatorController* _hostName;
}
@property (nonatomic) NSInteger updateRate;
@property (nonatomic, strong) ECSimulatorController* hostName;
- (void) removeDisplayLink;
- (void) reAddDisplayLink;
- (void) displayUpdated:(CADisplayLink*)timer;
- (void) startRunning;
- (void) stopRunning;
- (void) refreshRate:(NSInteger)rate;
- (void) setHost:(id)host;
- (void)setMinimumNumberOfTouches:(NSInteger)touches;
- (void)setMaximumNumberOfTouches:(NSInteger)touches;
@end
.m 文件:
#import "UILogicSimulatorView.h"
#import "ECSimulatorController.h"
#import <QuartzCore/QuartzCore.h>
@implementation UILogicSimulatorView
@synthesize updateRate = _updateRate;
@synthesize hostName = _hostName;
- (void)reAddDisplayLink {
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; //allows the display link to be re-added to the run loop after having been removed.
}
- (void)removeDisplayLink {
[displayLink removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; //allows the display link to be removed from the Run loop without deleting it. Removing it is essential to prevent corruption between the games and the simulator as both use CADisplay link, and only one can be in the run loop at a given moment.
}
- (void)startRunning {
[self refreshRate:self.updateRate];
[displayLink setPaused:NO];
}
- (void)refreshRate:(NSInteger)rate {
if (rate > 59) {
rate = 59; //prevent the rate from being set too an undefined value.
}
NSInteger frameInterval = 60 - rate; //rate is the number of frames to skip. There are 60FPS, so this converts to frame interval.
[displayLink setFrameInterval:frameInterval];
}
- (void)stopRunning {
[displayLink setPaused:YES];
}
- (void)displayUpdated:(CADisplayLink*)timer {
//call the function that the snakeController host needs to update
[self.hostName updateStates];
}
- (void)setHost:(ECSimulatorController*)host;
{
self.hostName = host; //Host allows the CADisplay link to call a selector in the object which created this one.
}
- (id)initWithFrame:(CGRect)frame
{
//Locates the UIScrollView's gesture recogniser
if(self = [super initWithFrame:frame])
{
[self setMinimumNumberOfTouches:2];
displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayUpdated:)]; //CADisplayLink will update the logic gate states.
self.updateRate = 1;
[displayLink setPaused:YES];
}
return self;
}
- (void)setMinimumNumberOfTouches:(NSInteger)touches{
for (UIGestureRecognizer *gestureRecognizer in [self gestureRecognizers])
{
if([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]])
{
//Changes the minimum number of touches to 'touches'. This allows the UIPanGestureRecogniser in the object which created this one to work with one finger.
[(UIPanGestureRecognizer*)gestureRecognizer setMinimumNumberOfTouches:touches];
}
}
}
- (void)setMaximumNumberOfTouches:(NSInteger)touches{
for (UIGestureRecognizer *gestureRecognizer in [self gestureRecognizers])
{
if([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]])
{
//Changes the maximum number of touches to 'touches'. This allows the UIPanGestureRecogniser in the object which created this one to work with one finger.
[(UIPanGestureRecognizer*)gestureRecognizer setMaximumNumberOfTouches:touches];
}
}
}
@end