LoginSignup
1
1

More than 3 years have passed since last update.

iOSでのNullabilityの歴史(社内勉強会用)

Last updated at Posted at 2017-08-09
1 / 10

目次

  • 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

1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1