IPadのiOS8でエッジスワイプジェスチャを設定しようとしていますが、エラーが発生してバグのように見えます。
私は次のコードを持っています:
UIScreenEdgePanGestureRecognizer *edgeRecognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(handleRightEdgeSwipe:)];
edgeRecognizer.edges = UIRectEdgeRight;
[self.view addGestureRecognizer:edgeRecognizer];
次に、ジェスチャーを処理します。
-(void)handleRightEdgeSwipe:(UIGestureRecognizer*)sender
{
//slide in view code here
}
問題は、毎回右エッジスワイプを検出しないことです。そして時々それはそれを複数回検出します。
検出するかどうかに関係なく、iPadで右エッジをスワイプするとコンソールに次の情報が常に表示されます。
2014-10-07 00:04:40.386 Office Log [1531:500896] _UIApplicationHandleEventFromQueueEvent、_windowServerHitTestWindowの予期しないnilウィンドウ:;レイヤー=>
このメッセージの意味と、右エッジスワイプが一貫して検出されるように修正するにはどうすればよいですか?
これはiOSのバグだと思います。これは、iPad mini2とiOS7以降のiPadAirで、ホーム画面でも確認できます。
「LandscapeLeft」(左側のホームボタン)では、画面の外側からの「RightEdgeGesture」が機能していません。ホーム画面で自分でテストしてください。
9か月前にAppleにバグを報告しましたが、さらに発生したことに気づきました。
UIWindow initで少し遊んだのですが、実際より少し大きい場合は、ジェスチャが機能します。もちろん、これは恐ろしい修正です。
self.window = [UIWindow new];
self.window.rootViewController = [[UIViewController alloc] init];
// Real Size
CGRect frame = [UIScreen mainScreen].bounds;
// Real Size + 0.000001
self.window.frame = CGRectMake(0, 0, frame.size.width+0.000001, frame.size.height+0.000001);
[self.window makeKeyAndVisible];
同じ問題が発生しました。私の解決策はうまく機能します:あなたのxibにあなたのWindowsを非表示に設定するだけです。
なぜ機能するのかよくわかりませんが、機能します。
編集1:
私は別の解決策を見つけました。私が思うに、より理解しやすいものです。
このコードをappDelegateのwillFinishLaunchingWithOptionsに配置します。
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
CGRect bounds = [[UIScreen mainScreen] bounds];
[self.window setFrame:bounds];
[self.window setBounds:bounds];
return YES;
}
次に、didFinishLaunchingWithOptionsで:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Your codes...
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
次に、ウィンドウオブジェクトを非表示にNOに設定すると、機能するはずです。
IPadでiPhoneアプリをテストするときに問題が発生しました。シミュレーターで問題はなく、アプリをユニバーサルとしてコンパイルしてiPadで実行しても問題ありません。
unexpected nil window in _UIApplicationHandleEventFromQueueEvent, _windowServerHitTestWindow: <UIClassicWindow: 0x1276065a0; frame = (0 0; 768 1024); userInteractionEnabled = NO; gestureRecognizers = <NSArray: 0x1740557e0>; layer = <UIWindowLayer: 0x17403fd80>>
おそらくフレームが間違って報告されていますか? (フレーム=(0 0; 768 1024))
iOS 8には、Portrait Upside-Down(上部のホームボタン)またはLandscape Left(左側のホームボタン)モードでiPadの右端から正確に開始するタッチが、正しいビューでヒットテストされないというバグがあります。
修正はUIWindow
をサブクラス化して、右側を正しくヒットテストすることです。
@implementation FixedWindow
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
UIView* hit = [super hitTest:point withEvent:event];
if (!hit && point.x >= CGRectGetMaxX(self.bounds))
hit = [super hitTest:CGPointMake(point.x - 0.5, point.y) withEvent:event];
return hit;
}
@end
window
プロパティを使用して、ウィンドウをアプリケーションデリゲートにアタッチします。
@implementation AppDelegate
- (UIWindow*)window
{
if (!_window)
_window = [[IVWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
return _window;
}
@end
ポートレートモードとランドスケープライトモードでは、エッジの右タッチがエッジ上ではなく、常にエッジから0.5px以上離れていることを確認したので、この修正はそれに類似して機能するはずです。
ウィンドウフレームの拡張
firebugの修正も機能することに注意してください。つまり、ウィンドウフレームをわずかに拡張して右側を含めます。しかしながら:
application:willFinishLaunchingWithOptions:
またはapplication:didFinishLaunchingWithOptions:
でこれを行うと、ビュー階層は新しいフレームにサイズ変更されず、右のエッジタッチは階層を通過しません。iOS 7:
iOS 7にも同様のバグがあり、ヒットテストも失敗しますが、結果がゼロではなく、ジオメトリが回転しません。この修正は、iOS7と8の両方で機能するはずです。
@implementation FixedWindow
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
UIView* hit = [super hitTest:point withEvent:event];
if (!hit || hit == self)
{
CGRect bounds = self.bounds;
hit = [super hitTest:CGPointMake(MIN(MAX(point.x, CGRectGetMinX(bounds) + 0.5), CGRectGetMaxX(bounds) - 0.5),
MIN(MAX(point.y, CGRectGetMinY(bounds) + 0.5), CGRectGetMaxY(bounds) - 0.5))
withEvent:event];
}
return hit;
}
@end
考えられる修正の1つは、ステータスバーを非表示にするコードを削除するかコメントアウトすることです。髪を引っ張って解決しましたが、ルートビューでしか再現できませんでした。ステータスバーを非表示にすると、今日のウィジェット/通知センターを下にドラッグできないようです(少し努力すればできます)。
/* <- add this
- (BOOL)prefersStatusBarHidden
{
return YES;
}
add this -> */
遅くなる可能性がありますが、それでも必要な場合があります。通常、原因は、正しいサイズの起動イメージが提供されていないか、起動画面が表示されていないか、[一般]> [展開情報]でメインインターフェイスが独自のストーリーボードに設定されていないことです。
デプロイメントを8.x以上に設定し、起動画面をメインxibとして設定します。
完了!