目次
- Objective-C での null の扱い
- Objective-C の nullable, nonnull
- Swift の Optional
- Swift3 での仕様変更
Objective-C
id nullObject = nil;
NSString *nullString = nullObject;
NSInteger length = nullString.length; // 0
NSString *uppercase = [nullString uppercaseString]; // null
- オブジェクトはid型
-
Type *
と宣言 - (ダウンキャストしても警告でない)
- nullオブジェクトはなにもせずnullを返す
Objective-C の nullable, nonnull
ObjC.h
@interface ObjC : NSObject
@property NSString *string; // Warning: Pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)
@property (nullable) NSString *nullableString;
@property (nonnull) NSString *nonnullString;
@end
ObjC.m
@implementation ObjC
- (instancetype)init
{
if (self = [super init]) {
self.string = nil;
self.nullableString = nil;
self.nonnullString = nil; // Warning: Null passed to a callee that requires a non-null argument
}
return self;
}
@end
- warning
Swift の Optional
var string: String = "abc"
var optionalString: String? = string
var implicitlyUnwrappedOptionalString: String! = optionalString
optionalString?.uppercaseString // Optional("ABC")
optionalString!.uppercaseString // "ABC"
implicitlyUnwrappedOptionalString?.uppercaseString // Optional("ABC")
implicitlyUnwrappedOptionalString!.uppercaseString // "ABC"
implicitlyUnwrappedOptionalString.uppercaseString // "ABC"
- obj?.member で Optional Chaining
- obj! で Forced Unwrapping
- Implicitly Unwrapped Optional
var string: String = nil // Compile error: Nil cannot initialize specified type 'String'
var optionalString: String? = nil
var implicitlyUnwrappedOptionalString: String! = nil
optionalString?.uppercaseString // nil
optionalString!.uppercaseString // Runtime error
implicitlyUnwrappedOptionalString?.uppercaseString // nil
implicitlyUnwrappedOptionalString.uppercaseString // Runtime error
Objective-C -> Swift
Objective-C
@interface ObjC : NSObject
@property NSString *string;
@property (nullable) NSString *nullableString;
@property (nonnull) NSString *nonnullString;
@end
Swift
var objc = ObjC()
objc.string.uppercaseString // Implicitly Unwrapped Optional
objc.nullableString?.uppercaseString
objc.nonnullString.uppercaseString
Implicitly Unwrapped Optional (IUO)
class MyObject {
var string: String
init() {
// Compile error: Return from initializer without initializing all stored properties
}
}
- プロパティは、宣言時かInitializerで初期化しなければらならない
- Optional型だけは、自動的にnilで初期化される
ので、
- 例えば、システム側にインスタンス化された直後に必ず設定するプロパティは、Optional型にせざるを得ない
- という時に、String! と宣言しておけば、参照時の Unwrap が不要となる
class MyObject {
var optionalString: String?
var string: String!
func test() {
self.optionalString!.uppercaseString
self.string.uppercaseString
}
}
IUO, Swift3で仕様変更
swift2
var notFoundImage: UIImage? = UIImage(named: "notFound.png")
var notFoundSize: CGSize? = notFoundImage?.size // nil
var beFoundImage: UIImage! = UIImage(named: "beFound.png")
var beFoundSize: CGSize = beFoundImage.size // (544.0, 184.0)
var beFoundImage2 = beFoundImage // UIImage! 型
var beFoundSize2 = beFoundImage2.size // (544.0, 184.0)
Swift2ではIUOは型なので、型推論も問題なしだったが、
Swift3で 「宣言時の属性」に変更された
Swift3
var beFoundImage2 = beFoundImage // UIImage?型
var beFoundSize2 = beFoundImage2.size // Compile error: Value of optional type 'UIImage?' not unwrapped; did you mean to use '!' or '?'?
(参考) Kotlin
lateinit
class MyObject{
private var string: String // Compile error: Property must be initialized or be abstract
private lateinit var lateinitString: String // OK
}
thanks