私はここ数ヶ月アプリに取り組んでいますが、ついに自分で解決できない問題に遭遇し、インターネット上で役立つものを見つけることができません。
私は自分のアプリでいくつかの通常のUIAlertViewsを使用しています。2つのボタンがあるもの、3つのボタンがあるもの、2つのボタンとテキストフィールドがあるものがあります。ただし、すべて同じ問題があります。[someAlertViewshow]を呼び出すと; アラートビューは通常どおり表示されますが、スクリーンショットからわかるように、突然そのグラフィックスコンテキストが破損しているように見えます。
これは、iPhoneとiPadの両方のシミュレーター(5.0と5.1の両方)で発生し、iPadとiPhone4Sデバイスでも発生します。
透けて見える画像は、alertViewの背後にあるものです。
アラートは引き続き機能します。ボタンをクリックしてテキストフィールドに入力すると、デリゲートメソッドが正しく呼び出され、すべてが通常に戻ります。alertViewが再び表示されると、同じことが起こります。
アラートの背後にあるビューは、UIImageを背景として、コンテンツサイズが約4000ピクセル×1000のカスタムUIScrollViewサブクラスです。pngファイルはほとんど透明であるため、メモリサイズは約80kBであり、電話はそれをレンダリングするのに問題はありません-スクロールビューはまだ完全に応答し、遅くはありません。また、サブクラスの一部としてCADisplayLinkタイマーが接続されています。alertViewが表示される直前にこれを無効にしようとしましたが、違いがないため、それが問題であるかどうかは疑わしいです。
このアプリは、私が大学のプロジェクト用に作成したものを部分的に書き直したものであり、同じサイズとサブクラスのscrollViewの上に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であり、scrollViewsCADisplayリンクを停止する機能を追加します。
@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];
}
これが発生してもメモリの警告が表示されないので、リソースの不足が原因であるかどうかは疑わしいです。
誰かが以前にこのような問題に遭遇したことがありますか?さらに詳しい情報が必要な場合は、提供を試みることができますが、投稿できるコードには制限があります。助けていただければ幸いです。私はこれを2週間解決しようとしてきましたが、理解できません。
編集:背後にあるスクロールビューを削除すると問題が解消されるため、AlertViewではないように見えます(つまり、alertViewだけではありません)。したがって、2つの間に何らかの問題があるはずです。これは私の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