More Related Content
Similar to 既存アプリのiOS8対応 #ios8yahoo (20)
More from Yahoo!デベロッパーネットワーク (20)
既存アプリのiOS8対応 #ios8yahoo
- 5. ヤフオク!アプリについて
• iPhone版
• 2010年10月リリース(当時はiOS4.1)
• コード上でUI部品を生成している箇所多数
• iPad版
• 2013年12月リリース
• xib、storyboardは当然活用
- 17. 原因
CGRect appFrame = [[UIScreen mainScreen] applicationFrame];
/* 以下はiOS8からは端末の向きによって返却される値が変わるようになった*/
CGFloat height = appFrame.size.height;
CGFloat width = appFrame.size.width;
- 20. 端末の向きにってheight、width
に変化があるメソッド
• [[UIScreen mainScreen] applicationFrame];
• [[UIScreen mainScreen] bounds];
• [[UIApplication sharedApplication] statusBarFrame];
これらを使っている箇所は見直しましょう
- 22. 回転検知時に呼ばれる処理も変更
- (void)willRotateToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientatio
n duration:(NSTimeInterval)duration;
- (void)viewWillTransitionToSize:(CGSize)size
withTransitionCoordinator:(id
<UIViewControllerTransitionCoordinator>)coord
inator;
回転検知ではなく、サイズが変更されたと考える
- 23. 実際の対応内容
//iOS7以前の画面回転開始時の処理
- (void)willRotateToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation duration:
(NSTimeInterval)duration
{
//端末の向き取得
BOOL isLandscape =
UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
//以降width、heightを取得して回転後の座標位置変更処理を行う
}
- 24. 実際の対応内容
//iOS7以前の画面回転開始時の処理
- (void)willRotateToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation duration:
(NSTimeInterval)duration
{
//端末の向き取得
BOOL isLandscape =
UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
//以降width、heightを取得して回転後の座標位置変更処理を行う
}
!
//iOS8以降のサイズ変更時(回転時)の処理
- (void)viewWillTransitionToSize:(CGSize)size
withTransitionCoordinator:
(id<UIViewControllerTransitionCoordinator>)coordinator
{
//端末の向き取得
BOOL isLandscape = (size.height <= size.width);
//以降width、heightを取得して回転後の座標位置変更処理を行う
}
- 25. 実際の対応内容
//iOS7以前の画面回転開始時の処理
- (void)willRotateToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation duration:
(NSTimeInterval)duration
{
//端末の向き取得
BOOL isLandscape =
UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
//以降width、heightを取得して回転後の座標位置変更処理を行う
}
!
//iOS8以降のサイズ変更時(回転時)の処理
- (void)viewWillTransitionToSize:(CGSize)size
withTransitionCoordinator:
(id<UIViewControllerTransitionCoordinator>)coordinator
{
//端末の向き取得
BOOL isLandscape = (size.height <= size.width);
//以降width、heightを取得して回転後の座標位置変更処理を行う
}
- 36. デバイストークン取得処理変更
//通知タイプの設定
UIUserNotificationType types = UIUserNotificationTypeBadge |
UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
!
UIUserNotificationSettings *settings = [UIUserNotificationSettings
settingsForTypes:types categories:nil];
!
[[UIApplication sharedApplication]
registerUserNotificationSettings:settings];
!
//Push通知の利用許可をとる
[[UIApplication sharedApplication] registerForRemoteNotifications];
iOSバージョン毎に処理を分岐する必要がある
- 37. デバイストークン取得処理変更
//通知タイプの設定
UIUserNotificationType types = UIUserNotificationTypeBadge |
UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
!
UIUserNotificationSettings *settings = [UIUserNotificationSettings
settingsForTypes:types categories:nil];
!
[[UIApplication sharedApplication]
registerUserNotificationSettings:settings];
!
//Push通知の利用許可をとる
[[UIApplication sharedApplication] registerForRemoteNotifications];
- 38. デバイストークン取得処理変更
//通知タイプの設定
UIUserNotificationType types = UIUserNotificationTypeBadge |
UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
!
UIUserNotificationSettings *settings = [UIUserNotificationSettings
settingsForTypes:types categories:nil];
!
[[UIApplication sharedApplication]
registerUserNotificationSettings:settings];
!
//Push通知の利用許可をとる
[[UIApplication sharedApplication] registerForRemoteNotifications];
- 39. デバイストークン取得処理変更
//通知タイプの設定
UIUserNotificationType types = UIUserNotificationTypeBadge |
UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
!
UIUserNotificationSettings *settings = [UIUserNotificationSettings
settingsForTypes:types categories:nil];
!
[[UIApplication sharedApplication]
registerUserNotificationSettings:settings];
!
//Push通知の利用許可をとる
[[UIApplication sharedApplication] registerForRemoteNotifications];
- 40. デバイストークン取得処理変更
//通知タイプの設定
UIUserNotificationType types = UIUserNotificationTypeBadge |
UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
!
UIUserNotificationSettings *settings = [UIUserNotificationSettings
settingsForTypes:types categories:nil];
!
[[UIApplication sharedApplication]
registerUserNotificationSettings:settings];
!
//Push通知の利用許可をとる
[[UIApplication sharedApplication] registerForRemoteNotifications];
- 41. デバイストークン取得処理変更
//通知タイプの設定
UIUserNotificationType types = UIUserNotificationTypeBadge |
UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
!
UIUserNotificationSettings *settings = [UIUserNotificationSettings
settingsForTypes:types categories:nil];
!
[[UIApplication sharedApplication]
registerUserNotificationSettings:settings];
!
//Push通知の利用許可をとる
[[UIApplication sharedApplication] registerForRemoteNotifications];
iOSバージョン毎に処理を分岐する必要がある
- 42. OSバージョンで分岐させてます
+ (void)registerNotification
{
//iOS8とそれ以外で設定を変更する必要がある
if ([YJUtil isIOS8]){
[AucNotificationConfigure registerNotificationAfteriOS8];
} else {
[AucNotificationConfigure registerNotificationBeforeiOS7];
}
}
- 44. + (void)registerNotificationAfteriOS8
{
UIMutableUserNotificationAction *bidAction =
[[UIMutableUserNotificationAction alloc] init];
bidAction.identifier = XXXXXXX;
bidAction.title = @"入札する";
bidAction.activationMode = UIUserNotificationActivationModeForeground;
bidAction.destructive = NO;
bidAction.authenticationRequired = NO;
UIMutableUserNotificationCategory *inviteCategory =
[[UIMutableUserNotificationCategory alloc] init];
inviteCategory.identifier = XXXXXXX;
[inviteCategory setActions:@[bidAction]
forContext:UIUserNotificationActionContextMinimal];
//通知タイプの設定
UIUserNotificationType types = UIUserNotificationTypeBadge |
UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
NSSet *categories = [NSSet setWithObject:inviteCategory];
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types
categories:categories];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
//Push通知の利用許可をとる
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
iOS8以後の処理
- 45. + (void)registerNotificationAfteriOS8
{
UIMutableUserNotificationAction *bidAction =
[[UIMutableUserNotificationAction alloc] init];
bidAction.identifier = XXXXXXX;
bidAction.title = @"入札する";
bidAction.activationMode = UIUserNotificationActivationModeForeground;
bidAction.destructive = NO;
bidAction.authenticationRequired = NO;
UIMutableUserNotificationCategory *inviteCategory =
[[UIMutableUserNotificationCategory alloc] init];
inviteCategory.identifier = XXXXXXX;
[inviteCategory setActions:@[bidAction]
forContext:UIUserNotificationActionContextMinimal];
//通知タイプの設定
UIUserNotificationType types = UIUserNotificationTypeBadge |
UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
NSSet *categories = [NSSet setWithObject:inviteCategory];
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types
categories:categories];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
//Push通知の利用許可をとる
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
iOS8以後の処理
- 46. + (void)registerNotificationAfteriOS8
{
UIMutableUserNotificationAction *bidAction =
[[UIMutableUserNotificationAction alloc] init];
bidAction.identifier = XXXXXXX;
bidAction.title = @"入札する";
bidAction.activationMode = UIUserNotificationActivationModeForeground;
bidAction.destructive = NO;
bidAction.authenticationRequired = NO;
UIMutableUserNotificationCategory *inviteCategory =
[[UIMutableUserNotificationCategory alloc] init];
inviteCategory.identifier = XXXXXXX;
[inviteCategory setActions:@[bidAction]
forContext:UIUserNotificationActionContextMinimal];
//通知タイプの設定
UIUserNotificationType types = UIUserNotificationTypeBadge |
UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
NSSet *categories = [NSSet setWithObject:inviteCategory];
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types
categories:categories];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
//Push通知の利用許可をとる
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
iOS8以後の処理
- 48. iPadでカメラ撮影する時
UIImagePickerController * picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
!
[self presentViewController:picker animated:YES completion:nil];
- 49. iPadでカメラ撮影する時
UIImagePickerController * picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
!
[self presentViewController:picker animated:YES completion:nil];
- 50. iPadでカメラ撮影する時
UIImagePickerController * picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
!
dispatch_async(dispatch_get_main_queue(), ^ {
[self presentViewController:picker animated:YES completion:nil];
非同期で起動しないと固まってしまう
});
- 51. iPadでカメラ撮影する時
UIImagePickerController * picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
!
dispatch_async(dispatch_get_main_queue(), ^ {
[self presentViewController:picker animated:YES completion:nil];
非同期で起動しないと固まってしまう
});
- 52. iPadでカメラ撮影する時
UIImagePickerController * picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
dispatch_async(dispatch_get_main_queue(), ^ {
[self presentViewController:picker animated:YES completion:nil];
});
} else {
[self presentViewController:picker animated:YES completion:nil];
}
非同期で起動しないと固まってしまう
- 54. iPadでアルバムから写真を選択する際も同様
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc]init];
imagePickerController.delegate = self;
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
!
self.popover = [[UIPopoverController alloc] initWithContentViewController:
imagePickerController];
self.popover.delegate = self;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
dispatch_async(dispatch_get_main_queue(), ^ {
[self.popover presentPopoverFromRect:cell.frame inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
});
} else {
[self.popover presentPopoverFromRect:cell.frame inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
非同期で起動しないと固まってしまう
- 55. iPadでアルバムから写真を選択する際も同様
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc]init];
imagePickerController.delegate = self;
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
!
self.popover = [[UIPopoverController alloc] initWithContentViewController:
imagePickerController];
self.popover.delegate = self;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
dispatch_async(dispatch_get_main_queue(), ^ {
[self.popover presentPopoverFromRect:cell.frame inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
});
} else {
[self.popover presentPopoverFromRect:cell.frame inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
非同期で起動しないと固まってしまう
- 56. iPadでアルバムから写真を選択する際も同様
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc]init];
imagePickerController.delegate = self;
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
!
self.popover = [[UIPopoverController alloc] initWithContentViewController:
imagePickerController];
self.popover.delegate = self;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
dispatch_async(dispatch_get_main_queue(), ^ {
[self.popover presentPopoverFromRect:cell.frame inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
});
} else {
[self.popover presentPopoverFromRect:cell.frame inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
非同期で起動しないと固まってしまう
- 57. iPadでアルバムから写真を選択する際も同様
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc]init];
imagePickerController.delegate = self;
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
!
self.popover = [[UIPopoverController alloc] initWithContentViewController:
imagePickerController];
self.popover.delegate = self;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
dispatch_async(dispatch_get_main_queue(), ^ {
[self.popover presentPopoverFromRect:cell.frame inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
});
} else {
[self.popover presentPopoverFromRect:cell.frame inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
非同期で起動しないと固まってしまう
- 62. setFinishedSelectedImageはDepricated
UIImage *m1 = [[UIImage imageNamed:@"m1.png"]
imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
!
UIImage *m2 = [[UIImage imageNamed:@"m2.png"]
imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
!
UITabBarItem *tab = [[UITabBarItem alloc] initWithTitle:@"" image:m1
selectedImage:m2];
- 63. setFinishedSelectedImageはDepricated
UIImage *m1 = [[UIImage imageNamed:@"m1.png"]
imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
!
UIImage *m2 = [[UIImage imageNamed:@"m2.png"]
imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
!
UITabBarItem *tab = [[UITabBarItem alloc] initWithTitle:@"" image:m1
selectedImage:m2];
- 64. setFinishedSelectedImageはDepricated
UIImage *m1 = [[UIImage imageNamed:@"m1.png"]
imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
!
UIImage *m2 = [[UIImage imageNamed:@"m2.png"]
imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
!
UITabBarItem *tab = [[UITabBarItem alloc] initWithTitle:@"" image:m1
selectedImage:m2];
UIImageRenderingModeAlwaysOriginalと共に生成する
- 67. + (UIApplication *)sharedApplication
NS_EXTENSION_UNAVAILABLE_IOS("Use view
controller based solutions where
appropriate instead.");
NS_EXTENSION_UNAVAILABLE_IOS
のメソッドはExtention内では利用できない
- 68. どうするべきか
!
!
// 特定のアプリを起動する
void launchXXXXX(NSString* message)
{
NSString* url = [NSString stringWithFormat:
@"%@://XXXXX/?message=%@", kXXXXSchemes, message];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
}
!
- 69. Preprocessor Macroを使う方法
#ifndef AUC_WIDGET
!
// 特定のアプリを起動する
void launchXXXXX(NSString* message)
{
NSString* url = [NSString stringWithFormat:
@"%@://XXXXX/?message=%@", kXXXXSchemes, message];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
}
#endif
- 70. Preprocessor Macroを使う方法
#ifndef AUC_WIDGET
!
// 特定のアプリを起動する
void launchXXXXX(NSString* message)
{
NSString* url = [NSString stringWithFormat:
@"%@://XXXXX/?message=%@", kXXXXSchemes, message];
[[UIApplication sharedApplication] openURL:[NSURL
URLWithString:url]];
}
#endif
できるだけ共通部品から取り除くべきですが、
一手段として参考にしてください
- 74. Extention Todayについて
• ガイドライン上、スクロールできるUIはユーザに
とって好ましくないとの記述がある
• ヤフオク!では入札中の商品を一覧できるExtention
Todayを作成したかった
• 一覧から入札できればなお良い(でもウィジェッ
トではキーボードは利用できない)