アプリの作成にSwiftを使用していますが、アラートを表示する必要があります。アプリはiOS 7およびiOS 8互換である必要があります。 UIAlertView
はUIAlertController
に置き換えられているので、システムバージョンを確認せずにUIAlertController
が利用可能かどうかを確認するにはどうすればよいですか? Appleは、APIの可用性を判断するためにデバイスのシステムバージョンを確認しないことを推奨していると聞いています。
これは私がiOS 8で使用しているものですが、これはiOS 7で「dyld: Symbol not found: _OBJC_CLASS_$_UIAlertAction
」でクラッシュします:
let alert = UIAlertController(title: "Error", message: message, preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
alert.addAction(cancelAction)
presentViewController(alert, animated: true, completion: nil)
IOS 8のUIAlertViewを使用すると、次の警告が表示されます:Warning: Attempt to dismiss from view controller <_UIAlertShimPresentingViewController: 0x7bf72d60> while a presentation or dismiss is in progress!
検出パターンはObjective-Cスタイルと同じです。
現在アクティブなランタイムにこのクラスをインスタンス化する機能があるかどうかを検出する必要があります
if objc_getClass("UIAlertController") != nil {
println("UIAlertController can be instantiated")
//make and use a UIAlertController
}
else {
println("UIAlertController can NOT be instantiated")
//make and use a UIAlertView
}
OSのバージョンに基づいてこれを試そうとしないでください。能力を検出する必要がありますNOT OS。
編集
この回答の元の検出器NSClassFromString("UIAlertController")
は-O
最適化で失敗するため、リリースビルドで機能する現在のバージョンに変更されました
編集2
NSClassFromString
はXcode 6.3/Swift 1.2のすべての最適化で機能しています
非Swiftコードの場合、純粋なobjective-Cがこれを行います
if ([UIAlertController class])
{
// use UIAlertController
UIAlertController *alert= [UIAlertController
alertControllerWithTitle:@"Enter Folder Name"
message:@"Keep it short and sweet"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action){
//Do Some action here
UITextField *textField = alert.textFields[0];
NSLog(@"text was %@", textField.text);
}];
UIAlertAction* cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
NSLog(@"cancel btn");
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:ok];
[alert addAction:cancel];
[alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.placeholder = @"folder name";
textField.keyboardType = UIKeyboardTypeDefault;
}];
[self presentViewController:alert animated:YES completion:nil];
}
else
{
// use UIAlertView
UIAlertView* dialog = [[UIAlertView alloc] initWithTitle:@"Enter Folder Name"
message:@"Keep it short and sweet"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"OK", nil];
dialog.alertViewStyle = UIAlertViewStylePlainTextInput;
dialog.tag = 400;
[dialog show];
}
私は両方の状況を書き続けなければならないことに悩まされていたので、iOS 7でも動作する互換性のあるUIAlertControllerを書いたので、GitHubに投げました。 UIAlertControllerのボタンとアクションを追加する(はるかに優れた)メソッドを複製するために最善を尽くしました。 Objective-CとSwiftの両方で動作します。 Googleで検索するときにこの質問を見つけ、他の人に役立つ可能性があると考えたため、これを投稿しています。
このコードを使用して問題を解決できます:-
var device : UIDevice = UIDevice.currentDevice()!;
var systemVersion = device.systemVersion;
var iosVerion : Float = systemVersion.bridgeToObjectiveC().floatValue;
if(iosVerion < 8.0) {
let alert = UIAlertView()
alert.title = "Noop"
alert.message = "Nothing to verify"
alert.addButtonWithTitle("Click")
alert.show()
}else{
var alert : UIAlertController = UIAlertController(title: "Noop", message: "Nothing to verify", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Click", style:.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
uIKitは必須ではなくオプションとしてマークする必要がありました。
Courtsey:- iOS 7およびiOS 8で動作可能なアラート
Swift 2.0
if #available(iOS 8.0, *) {
} else {
}
これが共有コードであり、コードがiOS 8拡張機能(UIAlertViewとUIActionSheetが制限されたAPI)およびUIAlertControllerが存在しないiOS 7で使用できる可能性がある場合は、以下を参照してください- JVAlertController
これは、iOS 7とiOS 8の両方の拡張機能でSDKコードを安全に使用できるようにするために、iOS 7に対するUIAlertControllerのAPI互換のバックポートです。
カテゴリを使用してそれを解決できます(ただし、Swiftに変換する必要があります)。
@implementation UIView( AlertCompatibility )
+( void )showSimpleAlertWithTitle:( NSString * )title
message:( NSString * )message
cancelButtonTitle:( NSString * )cancelButtonTitle
{
if( [[UIDevice currentDevice] isSystemVersionLowerThan: @"8"] )
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: title
message: message
delegate: nil
cancelButtonTitle: cancelButtonTitle
otherButtonTitles: nil];
[alert show];
}
else
{
// nil titles break alert interface on iOS 8.0, so we'll be using empty strings
UIAlertController *alert = [UIAlertController alertControllerWithTitle: title == nil ? @"": title
message: message
preferredStyle: UIAlertControllerStyleAlert];
UIAlertAction *defaultAction = [UIAlertAction actionWithTitle: cancelButtonTitle
style: UIAlertActionStyleDefault
handler: nil];
[alert addAction: defaultAction];
UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
[rootViewController presentViewController: alert animated: YES completion: nil];
}
}
@end
@implementation UIDevice( SystemVersion )
-( BOOL )isSystemVersionLowerThan:( NSString * )versionToCompareWith
{
if( versionToCompareWith.length == 0 )
return NO;
NSString *deviceSystemVersion = [self systemVersion];
NSArray *systemVersionComponents = [deviceSystemVersion componentsSeparatedByString: @"."];
uint16_t deviceMajor = 0;
uint16_t deviceMinor = 0;
uint16_t deviceBugfix = 0;
NSUInteger nDeviceComponents = systemVersionComponents.count;
if( nDeviceComponents > 0 )
deviceMajor = [( NSString * )systemVersionComponents[0] intValue];
if( nDeviceComponents > 1 )
deviceMinor = [( NSString * )systemVersionComponents[1] intValue];
if( nDeviceComponents > 2 )
deviceBugfix = [( NSString * )systemVersionComponents[2] intValue];
NSArray *versionToCompareWithComponents = [versionToCompareWith componentsSeparatedByString: @"."];
uint16_t versionToCompareWithMajor = 0;
uint16_t versionToCompareWithMinor = 0;
uint16_t versionToCompareWithBugfix = 0;
NSUInteger nVersionToCompareWithComponents = versionToCompareWithComponents.count;
if( nVersionToCompareWithComponents > 0 )
versionToCompareWithMajor = [( NSString * )versionToCompareWithComponents[0] intValue];
if( nVersionToCompareWithComponents > 1 )
versionToCompareWithMinor = [( NSString * )versionToCompareWithComponents[1] intValue];
if( nVersionToCompareWithComponents > 2 )
versionToCompareWithBugfix = [( NSString * )versionToCompareWithComponents[2] intValue];
return ( deviceMajor < versionToCompareWithMajor )
|| (( deviceMajor == versionToCompareWithMajor ) && ( deviceMinor < versionToCompareWithMinor ))
|| (( deviceMajor == versionToCompareWithMajor ) && ( deviceMinor == versionToCompareWithMinor ) && ( deviceBugfix < versionToCompareWithBugfix ));
}
@end
それからちょうど電話
[UIView showSimpleAlertWithTitle: @"Error" message: message cancelButtonTitle: @"OK"];
ただし、システムバージョンを確認したくない場合は、
BOOL lowerThaniOS8 = NSClassFromString( @"UIAlertController" ) == nil;
カテゴリUIView(AlertCompatibility)内
上記のようにiOS 7- UIAlertViewとiOS 8+ UIAlertControllerの両方を使用し、UIAlertControllerブロックがUIAlertViewのデリゲート(MyControllerなど)alertView:didDismissWithButtonIndexメソッドを呼び出して結果の処理を続行する場合は、次の方法の例を示します。それ:
if ([UIAlertController class]) {
MyController * __weak mySelf = self;
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:alertTitle
message:alertMessage
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction
actionWithTitle:alertCancel
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action)
{
[mySelf alertView:nil didDismissWithButtonIndex:0];
}
];
...
これは、ブロックのselfをキャプチャするためのAppleの推奨事項を使用します: self
もちろん、このメソッドは、コントローラーにUIAlertViewが1つしかないため、nilをデリゲートメソッドに値として渡すことを前提としています。それ以外の場合は、alertView:didDismissWithButtonIndexに渡すために「偽の」UIAlertViewをインスタンス化(およびタグ付け)する必要があります。
ここでUIAlertView
と IAlertContoller の2つの方法を確認します。
チェック1:iOSバージョンチェック IAlertController クラス。
if #available(iOS 8.0, *) {
// UIALertController
let alert = UIAlertController(title: "Alert", message: "Alert after 8.0", preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
alert.addAction(cancelAction)
presentViewController(alert, animated: true, completion: nil)
} else {
// UIALertView
UIAlertView(title: "Alert", message: "Alert below iOS V 8.0", delegate: nil, cancelButtonTitle: "OK").show()
}
チェック2:チェックUIAlertController
nilその後、iOSバージョン8.0以下。
if objc_getClass("UIAlertController") != nil {
// UIALertController
let alert = UIAlertController(title: "Alert", message: "Alert after 8.0", preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
alert.addAction(cancelAction)
presentViewController(alert, animated: true, completion: nil)
}
else {
// UIALertView
UIAlertView(title: "Alert", message: "Alert below iOS V 8.0", delegate: nil, cancelButtonTitle: "OK").show()
}
IOS 7との互換性が必要な場合は、UIAlertController
を使用しないでください。そのような単純な。
UIAlertView
は置き換えられていませんが、引き続き完全に機能し、近い将来、完全に機能し続けます。
これが私のドラッグアンドドロップSwiftソリューションです。
//Alerts change in iOS8, this method is to cover iOS7 devices
func CozAlert(title: String, message: String, action: String, sender: UIViewController){
if respondsToSelector("UIAlertController"){
var alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: action, style: UIAlertActionStyle.Default, handler:nil))
sender.presentViewController(alert, animated: true, completion: nil)
}
else {
var alert = UIAlertView(title: title, message: message, delegate: sender, cancelButtonTitle:action)
alert.show()
}
}
このような呼び出し:
CozAlert("reportTitle", message: "reportText", action: "reportButton", sender: self)
これは最も基本的なアラート専用であり、高度なものには追加のコードが必要になる場合があることに注意してください。