Adopting Cocoa Design Patterns
ココア・デザインパターンの採用
One aid in writing well-designed, resilient apps is to use Cocoa’s established design patterns. Many of these patterns rely on classes defined in Objective-C. Because of Swift’s interoperability with Objective-C, you can take advantage of these common patterns in your Swift code. In many cases, you can use Swift language features to extend or simplify existing Cocoa patterns, making them more powerful and easier to use.
よく設計された、溌剌としたアプリを記述することでの1つの援助は、ココアのいくつかの確立したデザインパターンを使うことです。これらのパターンの多くは、Objective-Cで定義されるクラスに頼ります。スウィフトのObjective-Cとの相互運用性のため、あなたはこれらの共通のパターンをあなたのスウィフトコードにおいて活用することができます。多くの場合に、あなたは既存のココア・パターンを拡張したり、単純化するためにスウィフト言語の特徴を働かせることができます。そして、それらをより強力でより使いやすくします。
Delegation
委任
In both Swift and Objective-C, delegation is often expressed with a protocol that defines the interaction and a conforming delegate property. Just as in Objective-C, before you send a message that a delegate may not respond to, you ask the delegate whether it responds to the selector. In Swift, you can use optional chaining to invoke an optional protocol method on a possibly nil
object and unwrap the possible result using if–let
syntax. The code listing below illustrates the following process:
スウィフトとObjective-Cの両方で、委任は、相互作用を定義するプロトコルと準拠している委任プロパティでたいてい表されます。ちょうどObjective-Cでのように、あなたが委任先が応答しないかもしれないメッセージを送る前に、あなたはその委任先にそれがセレクタに応答するかどうか尋ねます。スウィフトでは、あなたはオプショナル連鎖を使用することで、オプショナルのプロトコルメソッドをもしかするとnil
であるオブジェクト上で呼び出してif–let
構文を使って可能な結果をアンラップすることができます。下記のコード出力は、次の過程を例示します:
Check that
myDelegate
is notnil
.
myDelegate
がnil
でないことを確かめる。Check that
myDelegate
implements the methodwindow:willUseFullScreenContentSize:
.
myDelegate
がメソッドwindow:willUseFullScreenContentSize:
を実装することを確かめる。If 1 and 2 hold true, invoke the method and assign the result of the method to the value named
fullScreenSize
.
1と2が当てはまるならば、そのメソッドを呼び出して、メソッドの結果をfullScreenSize
と名前をつけられる値に代入する。Print the return value of the method.
メソッドの戻り値を出力する。
class MyDelegate: NSObject, NSWindowDelegate {
func window(_ window: NSWindow, willUseFullScreenContentSize proposedSize: NSSize) -> NSSize {
return proposedSize
}
}
myWindow.delegate = MyDelegate()
if let fullScreenSize = myWindow.delegate?.window(myWindow, willUseFullScreenContentSize: mySize) {
print(NSStringFromSize(fullScreenSize))
}
Lazy Initialization
遅延初期化
A lazy property is a property whose underlying value is only initialized when the property is first accessed. Lazy properties are useful when the initial value for a property either requires complex or computationally expensive setup, or cannot be determined until after an instance’s initialization is complete.
遅延プロパティは、それの裏に潜んだ値が初期化されるのがそのプロパティが最初にアクセスされる時にして初めてというプロパティです。遅延プロパティが便利なのは、あるプロパティに対する初期値が、複雑なもしくは計算的に高くつく準備を必要とする、またはあるインスタンスの初期化が完了する後まで決定されることが出来ない、このどちらかである場合です。
In Objective-C, a property may override its synthesized getter method such that the underlying instance variable is conditionally initialized if its value is nil
:
Objective-Cでは、プロパティは、それの合成されたゲッターメソッドをオーバーライドできます、例えば、裏に潜んだインスタンス変数が、それの値がnil
かどうかで、条件付きで初期化されるように:
@property NSXMLDocument *XML;
- (NSXMLDocument *)XML {
if (_XML == nil) {
_XML = [[NSXMLDocument alloc] initWithContentsOfURL:[[Bundle mainBundle] URLForResource:@"/path/to/resource" withExtension:@"xml"] options:0 error:nil];
}
return _XML;
}
In Swift, a stored property with an initial value can be declared with the lazy
modifier to have the expression calculating the initial value only evaluated when the property is first accessed:
スウィフトでは、初期値を持つ格納プロパティがlazy
修飾子を使って宣言されると、初期値を計算する式は、そのプロパティが最初にアクセスされる時に初めて数値を求められるようになります。
lazy var XML: XMLDocument = try! XMLDocument(contentsOf: Bundle.main.url(forResource: "document", withExtension: "xml")!)
Because a lazy property is only computed when accessed for a fully-initialized instance it may access constant or variable properties in its default value initialization expression:
遅延プロパティは、完全に初期化されたインスタンスに対してアクセスされる時に初めて計算されるので、それは、定数または変数プロパティにアクセスすることがそれの省略時の値の初期化式において可能です:
var pattern: String
lazy var regex: NSRegularExpression = try! NSRegularExpression(pattern: self.pattern)
For values that require additional setup beyond initialization, you can assign the default value of the property to a self-evaluating closure that returns a fully-initialized value:
初期化を越えて更なる準備が必要な値に対して、あなたはプロパティの省略時の値を得る仕事を、完全初期化された値を返すある自己評価するクロージャに任せることができます:
lazy var currencyFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.currencySymbol = "¤"
return formatter
}()
For more information, see Lazy Stored Properties in The Swift Programming Language (Swift 4.1).
更なる情報として、遅延格納プロパティをスウィフトプログラミング言語(Swift 4.1)で見てください。
Error Handling
エラーの処理
In Cocoa, methods that produce errors take an NSError
pointer parameter as their last parameter, which populates its argument with an NSError
object if an error occurs. Swift automatically translates Objective-C methods that produce errors into methods that throw an error according to Swift’s native error handling functionality.
Cocoaでは、エラーを生成するメソッドは、それの最後のパラメーターとしてNSError
ポインターパラメーターを取ります、エラーが起こるならばその引数にNSError
オブジェクトが入ります。スウィフトは、自動的にエラーを生成するObjective-Cメソッドを、スウィフト固有のエラー処理機能に従ってエラーをスローするメソッドに翻訳します。
For example, consider the following Objective-C method from NSFileManager
:
例として、以下のNSFileManager
からのObjective-Cメソッドを考えてください:
- (BOOL)removeItemAtURL:(NSURL *)URL
error:(NSError **)error;
In Swift, it’s imported like this:
スウィフトでは、それはこのようにインポートされます:
func removeItem(at: URL) throws
Notice that the removeItem(at:)
method is imported by Swift with a Void
return type, no error
parameter, and a throws
declaration.
removeItem(at:)
メソッドがスウィフトによってVoid
の戻り型で、error
パラメーターなしで、そしてthrows
宣言でインポートされることに注意してください。
If the last non-block parameter of an Objective-C method is of type NSError **
, Swift replaces it with the throws
keyword, to indicate that the method can throw an error. If the Objective-C method’s error parameter is also its first parameter, Swift attempts to simplify the method name further, by removing the “WithError” or “AndReturnError” suffix, if present, from the first part of the selector. If another method is declared with the resulting selector, the method name is not changed.
Objective-Cメソッドの最後の非ブロックパラメーターが型NSError **
ならば、スウィフトはそれをthrows
キーワードで置き換えて、そのメソッドがエラーをスローできることを示します。Objective-Cメソッドのエラーパラメーターがまたそれの最初のパラメーターでもあるならば、スウィフトは「WithError」または「AndReturnError」接尾辞を、もしあるならば、セレクタの最初の部分から取り除くことで、メソッド名をいっそう単純化することを試みます。結果として生じるセレクタで別のメソッドが宣言されるならば、メソッド名は変更されません。
If an error producing Objective-C method returns a BOOL
value to indicate the success or failure of a method call, Swift changes the return type of the function to Void
. Similarly, if an error producing Objective-C method returns a nil
value to indicate the failure of a method call, Swift changes the return type of the function to a nonoptional type.
エラーを生成しているObjective-CメソッドがBOOL
値を返してメソッド呼び出しが成功か失敗かを指し示すならば、スウィフトは関数の戻り型をVoid
に変えます。同様に、エラーを生成しているObjective-Cメソッドがnil
値を返してメソッド呼び出しの失敗を指し示すならば、スウィフトは関数の戻り型を非オプショナル型に変えます。
Otherwise, if no convention can be inferred, the method is left intact.
それ以外では、推論されることができる慣行がないならば、メソッドは元のままにしておかれます。
Catching and Handling an Error
エラーを捕えて処理する
In Objective-C, error handling is opt-in, meaning that errors produced by calling a method are ignored unless an error pointer is provided. In Swift, calling a method that throws requires explicit error handling.
Objective-Cでは、エラー処理はオプトインです、それはメソッドを呼び出すことで生成されたエラーはエラーポインターが提供されない限りは無視されるということを意味しています。スウィフトでは、スローするメソッドを呼び出すことは明確にエラー処理することを必要とします。
Here’s an example of how to handle an error when calling a method in Objective-C:
ここにObejctive-Cにおいてメソッドを呼び出す時どのようにエラーを取り扱うかの例があります:
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *fromURL = [NSURL fileURLWithPath:@"/path/to/old"];
NSURL *toURL = [NSURL fileURLWithPath:@"/path/to/new"];
NSError *error = nil;
BOOL success = [fileManager moveItemAtURL:fromURL toURL:toURL error:&error];
if (!success) {
NSLog(@"Error: %@", error.domain);
}
And here’s the equivalent code in Swift:
そしてここにスウィフトにおける同等のコードがあります:
let fileManager = FileManager.default
let fromURL = URL(fileURLWithPath: "/path/to/old")
let toURL = URL(fileURLWithPath: "/path/to/new")
do {
try fileManager.moveItem(at: fromURL, to: toURL)
} catch let error as NSError {
print("Error: \(error.domain)")
}
Additionally, you can use catch
clauses to match on particular error codes as a convenient way to differentiate possible failure conditions:
加えて、あなたは、起こりうる失敗条件を見分ける便利な方法として、catch
節を特定のエラーコードで一致するように使うことができます。
do {
try fileManager.moveItem(at: fromURL, to: toURL)
} catch CocoaError.fileNoSuchFile {
print("Error: no such file exists")
} catch CocoaError.fileReadUnsupportedScheme {
print("Error: unsupported scheme (should be 'file://')")
}
Converting Errors to Optional Values
エラーをオプショナルの値に変換する
In Objective-C, you pass NULL
for the error parameter when you only care whether there was an error, not what specific error occurred. In Swift, you write try?
to change a throwing expression into one that returns an optional value, and then check whether the value is nil
.
Objective-Cでは、あなたはNULL
をエラーパラメータのために渡すことが、あなたが心配するのがただエラーがあったかどうかだけであり、特定のエラーに出くわしたことではない時に行えます。スウィフトでは、あなたはtry?
を書くことで、スローする式をオプショナルの値を返すものへと変えて、それからその値がnil
かどうかを調べます。
For example, the NSFileManager
instance method URL(for:in:appropriateForURL:create:)
returns a URL in the specified search path and domain, or produces an error if an appropriate URL does not exist and cannot be created. In Objective-C, the success or failure of the method can be determined by whether an NSURL
object is returned.
例えば、NSFileManager
のインスタンスメソッドURL(for:in:appropriateForURL:create:)
は指定された検索パスとドメインにおけるURLを返すか、または適切なURLが存在せず作成もできないならばエラーを生成します。Objective-Cでは、メソッドの成功や失敗は、NSURL
オブジェクトが返されるかどうかによって判断されることができます。
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *tmpURL = [fileManager URLForDirectory:NSCachesDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:YES
error:nil];
if (tmpURL != nil) {
// ...
}
You can do the same in Swift as follows:
あなたは、同じことをスウィフトにおいて以下のように行えます:
let fileManager = FileManager.default
if let tmpURL = try? fileManager.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true) {
// ...
}
Throwing an Error
エラーをスローする
If an error occurs in an Objective-C method, that error is used to populate the error pointer argument of that method:
エラーがObjective-Cメソッドにおいて起こるならば、そのエラーはそのメソッドのエラーポインター引数に入れられるために使われます。
// an error occurred
if (errorPtr) {
*errorPtr = [NSError errorWithDomain:NSURLErrorDomain
code:NSURLErrorCannotOpenFile
userInfo:nil];
}
If an error occurs in a Swift method, the error is thrown, and automatically propagated to the caller:
エラーがスウィフトメソッドにおいて起こるならば、そのエラーはスローされます、そして自動的に呼び出し側に伝達されます:
// an error occurred
throw NSError(domain: NSURLErrorDomain, code: NSURLErrorCannotOpenFile, userInfo: nil)
If Objective-C code calls a Swift method that throws an error, the error is automatically propagated to the error pointer argument of the bridged Objective-C method.
Objective-Cコードがエラーをスローするスウィフトメソッドを呼ぶならば、そのエラーは橋渡しされたObjective-Cメソッドのエラーポインタ引数に自動的に伝達されます。
For example, consider the read(from:ofType:)
method in NSDocument
. In Objective-C, this method’s last parameter is of type NSError **
. When overriding this method in a Swift subclass of NSDocument
, the method replaces its error parameter and throws instead.
例として、NSDocument
のread(from:ofType:)
メソッドを考えてください。Objective-Cでは、このメソッドの最後のパラメーターは型NSError **
です。このメソッドをNSDocument
のスウィフトのサブクラスにおいてオーバーライドする時、メソッドはそれのエラーパラメーターを置き替えて、代わりにスローをします。
class SerializedDocument: NSDocument {
static let ErrorDomain = "com.example.error.serialized-document"
var representedObject: [String: Any] = [:]
override func read(from fileWrapper: FileWrapper, ofType typeName: String) throws {
guard let data = fileWrapper.regularFileContents else {
throw NSError(domain: NSURLErrorDomain, code: NSURLErrorCannotOpenFile, userInfo: nil)
}
if case let JSON as [String: Any] = try JSONSerialization.jsonObject(with: data) {
self.representedObject = JSON
} else {
throw NSError(domain: SerializedDocument.ErrorDomain, code: -1, userInfo: nil)
}
}
}
If the method is unable to create an object with the regular file contents of the document, it throws an NSError
object. If the method is called from Swift code, the error is propagated to its calling scope. If the method is called from Objective-C code, the error instead populates the error pointer argument.
メソッドがオブジェクトを書類の標準ファイル内容で作成することができないならば、それはNSError
オブジェクトをスローします。メソッドがスウィフトコードから呼ばれるならば、エラーはそれを呼び出しているスコープに伝えられます。メソッドがObjective-Cコードから呼ばれるならば、代わりにエラーはエラーポインタ引数に入れられます。
In Objective-C, error handling is opt-in, meaning that errors produced by calling a method are ignored unless you provide an error pointer. In Swift, calling a method that throws requires explicit error handling.
Objective-Cでは、エラー処理はオプトインです、それはメソッドを呼び出すことで生成されたエラーはあなたがエラーポインターを提供しない限りは無視されるということを意味しています。スウィフトでは、スローするメソッドを呼び出すことは明確にエラー処理することを必要とします。
Handling Exceptions
例外を取り扱う
In Objective-C, exceptions are distinct from errors. Objective-C exception handling uses the @try
, @catch
, and @throw
syntax to indicate unrecoverable programmer errors. This is distinct from a common Cocoa pattern that uses a trailing NSError
parameter to indicate recoverable errors that you plan for during development.
Objective-Cにおいて、例外はエラーとは別個のものです。Objective-C例外処理は、@try
、@catch
、そして@throw
構文を使って回復不可能なプログラマエラーを指し示します。これは、後に続くNSError
パラメータを使うことで回復不可能なエラーを指し示す通常のCocoaパターンとは異なります、それはあなたが開発の間に備えるものです。
In Swift, you can recover from errors passed using Cocoa’s error pattern, as described in Error Handling. However, there’s no safe way to recover from Objective-C exceptions in Swift. To handle Objective-C exceptions, write Objective-C code that catches exceptions before they reach any Swift code.
スウィフトでは、あなたはCocoaの持つエラーパターンを使用して渡されるエラーから復旧することができます、エラーの処理において議論されるように。しかしながら、スウィフトにはObjective-C例外から回復する安全な方法はありません。Objective-C例外を取り扱うには、それら例外をそれらが何らかのスウィフトコードに届く前に捕まえるObjective-Cコードを書いてください。
For more information about Objective-C exceptions, see Exception Programming Topics.
Objective-C例外についての詳細として、Exception Programming Topicsを見てください。
Catching and Handling Custom Errors
カスタムエラーを捕まえて処理する
Objective-C frameworks can use custom error domains and enumerations to group related categories of errors.
Objective-Cフレームワークは、カスタムエラードメインと列挙を使って、エラーの関連カテゴリをグループ化します。
The example below shows a customized error type defined using the NS_ERROR_ENUM
macro in Objective-C:
下の例は、Objective-CにおいてNS_ERROR_ENUM
を使ってカスタマイズされたエラー型を示します:
extern NSErrorDomain const MyErrorDomain;
typedef NS_ERROR_ENUM(MyErrorDomain, MyError) {
specificError1 = 0,
specificError2 = 1
};
This example shows how to generate errors using that custom error type in Swift:
この例は、そのあつらえのエラー型をスウィフトにおいて使うことでエラーを生成する方法を示します:
func customThrow() throws {
throw NSError(
domain: MyErrorDomain,
code: MyError.specificError2.rawValue,
userInfo: [
NSLocalizedDescriptionKey: "A customized error from MyErrorDomain."
]
)
}
do {
try customThrow()
} catch MyError.specificError1 {
print("Caught specific error #1")
} catch let error as MyError where error.code == .specificError2 {
print("Caught specific error #2, ", error.localizedDescription)
// Prints "Caught specific error #2. A customized error from MyErrorDomain."
} let error {
fatalError("Some other error: \(error)")
}
Key-Value Observing
キー値監視
Key-value observing is a mechanism that allows objects to be notified of changes to specified properties of other objects. You can use key-value observing with a Swift class, as long as the class inherits from the NSObject
class. You can use these two steps to implement key-value observing in Swift.
キー値監視は、オブジェクトが他のオブジェクトの指定されたプロパティに対する変更を通知されるようにする仕組みです。あなたは、そのクラスがNSObject
クラスから継承する限り、スウィフトクラスでキー値監視を使うことができます。あなたは、これら2つの手順を使ってキー値監視をスウィフトにおいて実装できます。
Add the
dynamic
modifier and@objc
attribute to any property you want to observe. For more information ondynamic
, see Requiring Dynamic Dispatch.
dynamic
修飾子と@objc
属性をあなたが監視したい何らかのプロパティに加えてください。dynamic
に関数さらなる情報として、動的なディスパッチを要求するを見てください。class MyObjectToObserve: NSObject {
@objc dynamic var myDate = NSDate()
func updateDate() {
myDate = NSDate()
}
}
Create an observer for the key path and call the
observe(_:options:changeHandler)
method. For more information on key paths, see Keys and Key Paths.
キーパスに対する監視を作成してobserve(_:options:changeHandler)
メソッドを呼び出してください。新しいキーパスについてのさらなる情報として、キーとキーパスを見てください。class MyObserver: NSObject {
@objc var objectToObserve: MyObjectToObserve
var observation: NSKeyValueObservation?
init(object: MyObjectToObserve) {
objectToObserve = object
super.init()
observation = observe(\.objectToObserve.myDate) { object, change in
print("Observed a change to \(object.objectToObserve).myDate, updated to: \(object.objectToObserve.myDate)")
}
}
}
let observed = MyObjectToObserve()
let observer = MyObserver(object: observed)
observed.updateDate()
Target-Action
ターゲット-アクション
Target-action is a common Cocoa design pattern in which one object sends a message to another object when a specific event occurs. The target-action model is fundamentally similar in Swift and Objective-C. In Swift, you use the Selector
type to refer to Objective-C selectors. For an example of using target-action in Swift code, see Selectors.
ターゲット-アクションは、特定のイベントが起こる時にあるオブジェクトが別のオブジェクトにメッセージを送る場合の、一般的なココア・デザインパターンです。ターゲット-アクションの雛形は、スウィフトとObjective-Cで基本的に類似しています。スウィフトにおいて、あなたはObjective-Cセレクタに言及するためにSelector
型を使います。スウィフトコードにおいてターゲット-アクションを使う例のために、セレクタを見てください。
Singleton
シングルトン
Singletons provide a globally accessible, shared instance of an object. You can create your own singletons as a way to provide a unified access point to a resource or service that’s shared across an app, such as an audio channel to play sound effects or a network manager to make HTTP requests.
シングルトンは、全体で利用できる、共有されるひとつのインスタンスを、あるオブジェクトに提供します。あなたは、あるアプリ全体で共有されるリソースやサービス、例えばサウンドエフェクトを再生するオーディオチャンネルやHTTPリクエストを行うネットワークマネージャなどへの一本化されたアクセスポイントを提供する方法として、あなた自身のシングルトンを作成します。
In Objective-C, you can ensure that only one instance of a singleton object is created by wrapping its initialization in a call the dispatch_once
function, which executes a block once and only once for the lifetime of an app:
Objective-Cでは、あなたはあるシングルトンオブジェクトにただ1つのインスタンスが作成されることを、それの初期化を、あるブロックをあるアプリのライフタイムに対していっぺんこっきり実行するdispatch_once
関数呼び出しの中にラップする(包む)ことによって確実にできます:
+ (instancetype)sharedInstance {
static id _sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedInstance = [[self alloc] init];
});
return _sharedInstance;
}
In Swift, you can simply use a static type property, which is guaranteed to be lazily initialized only once, even when accessed across multiple threads simultaneously:
スウィフトでは、あなたは単にstatic型プロパティを使うことができます、それは、複数のスレッドから同時にアクセスされる時でさえも、ただ一度だけ遅延初期化されることを保証します:
class Singleton {
static let sharedInstance = Singleton()
}
If you need to perform additional setup beyond initialization, you can assign the result of the invocation of a closure to the global constant:
あなたが追加的な準備を初期化が済んだら実行する必要があるならば、あなたはあるクロージャの発動の結果をグローバル定数に割り当てることができます:
class Singleton {
static let sharedInstance: Singleton = {
let instance = Singleton()
// setup code
return instance
}()
}
For more information, see Type Properties in The Swift Programming Language (Swift 4.1).
更なる情報として、型プロパティをスウィフトプログラミング言語(Swift 4.1)で見てください。
Introspection
自己観察
In Objective-C, you use the isKindOfClass:
method to check whether an object is of a certain class type, and the conformsToProtocol:
method to check whether an object conforms to a specified protocol. In Swift, you accomplish this task by using the is
operator to check for a type, or the as?
operator to downcast to that type.
Objective-Cでは、あるオブジェクトが特定のクラス型かどうか調べるためにisKindOfClass:
を、そしてオブジェクトが指定されたプロトコルに準拠するかどうか調べるためにconformsToProtocol:を
使います。スウィフトでは、あなたは、ある型か調べるis
演算子、またはその型にダウンキャストするas?
演算子を使うことによってこの作業を達成します。
You can check whether an instance is of a certain subclass type by using the is
operator. The is
operator returns true
if the instance is of that subclass type, and false
if it is not.
あなたは、あるインスタンスが特定のサブクラス型であるかどうか、is
演算子を使うことによって調べることができます。is
演算子は、そのインスタンスがそのサブクラス型であるならばtrue
を、それがそうでないならばfalse
返します。
if object is UIButton {
// object is of type UIButton (オブジェクトは、型UIButtonです)
} else {
// object is not of type UIButton (オブジェクトは、型UIButtonではありません)
}
You can also try and downcast to the subclass type by using the as?
operator. The as?
operator returns an optional value that can be bound to a constant using an if
-let
statement.
あなたはまた、as?
演算子を使うことによって、そのサブクラス型へのダウンキャストを試みることができます。as?
演算子は、if
-let
文を使って定数に束縛されることができるオプショナルの値を返します。
if let button = object as? UIButton {
// object is successfully cast to type UIButton and bound to button (オブジェクトは、型UIButtonにうまくキャストされて、buttonに束縛されます)
} else {
// object could not be cast to type UIButton (オブジェクトは、型UIButtonにキャストされることができませんでした)
}
For more information, see Type Casting in The Swift Programming Language (Swift 4.1).
さらなる情報として、型キャストをスウィフトプログラミング言語(Swift 4.1)で見てください。
Checking for and casting to a protocol follows exactly the same syntax as checking for and casting to a class. Here is an example of using the as?
operator to check for protocol conformance:
あるプロトコルに対する調査とキャストは、あるクラスに対する調査とキャストと正確に同じ構文に従います。as?
演算子を使ってプロトコル準拠について調べる例がここにあります:
if let dataSource = object as? UITableViewDataSource {
// object conforms to UITableViewDataSource and is bound to dataSource (オブジェクトは、UITableViewDataSourceに準拠して、dataSourceに結束されます)
} else {
// object not conform to UITableViewDataSource (オブジェクトは、UITableViewDataSourceに準拠しません)
}
Note that after this cast, the dataSource
constant is of type UITableViewDataSource
, so you can only call methods and access properties defined on the UITableViewDataSource
protocol. You must cast it back to another type to perform other operations.
このキャストの後で、dataSource
定数は型UITableViewDataSource
である点に注意してください、なのであなたはUITableViewDataSource
プロトコル上で定義されるメソッド呼び出しとプロパティアクセスができるだけです。あなたは、他の操作を実行するために再び別の型へそれをキャストしなければなりません。
For more information, see Protocols in The Swift Programming Language (Swift 4.1).
さらなる情報として、プロトコルをスウィフトプログラミング言語(Swift 4.1)で見てください。
Serialization
シリアライズ
Serialization allows you to encode and decode objects in your app to and from architecture-independent representations, such as JSON or property lists. These representations can then be written to a file, or transmitted to another process locally or over a network.
シリアライズは、オブジェクトをあなたのアプリにおいてアーキテクチャ非依存の表現、例えばJSONやプロパティリストなどに符号化および復号化できるようにします。これらの表現は、それからファイルに書き出されたり、別のプロセスにローカルにまたはそのネットワークを超えて送られたりができます。
In Objective-C, you can use the Foundation framework classes NSJSONSerialization
and NSPropertyListSerialization
to initialize objects from a decoded JSON or property list serialization value—usually an object of type NSDictionary<NSString *, id>
.
Objective-Cでは、あなたはFoundationフレームワーククラスのNSJSONSerialization
とNSPropertyListSerialization
を使って、復号化されたJSONまたはプロパティリストのシリアライズ値 ― 通常は型NSDictionary<NSString *, id>
のオブジェクトから各オブジェクトを初期化します。
In Swift, the standard library defines a standardized approach to data encoding and decoding. You adopt this approach by making your types conform to the Encodable
or Decodable
protocols, or by conforming to Codable
as shorthand for conforming to both protocols. You can use the Foundation framework classes JSONEncoder
and PropertyListEncoder
to convert instances to JSON or property list data. Similarly, you can use the JSONDecoder
and PropertyListDecoder
classes to decode and initialize instances from JSON or property list data.
スウィフトでは、標準ライブラリが標準化された取り組みをデータのエンコーディングとデコーディングに対して定義します。あなたはこの取り組み方を、あなたの型をEncodable
またはDecodable
プロトコルに準拠するようにして、または両方のプロトコルへの準拠の簡略法としてCodable
に準拠することによって採用します。あなたは、FoundationフレームワーククラスJSONEncoder
とPropertyListEncoder
を使って、インスタンスをJSONまたはプロパティリストデータへ変換します。同様に、あなたはJSONDecoder
とPropertyListDecoder
クラスを使って、インスタンスをJSONまたはプロパティリストデータからデコードして初期化します。
For example, an app that communicates with a web server would receive JSON representations of grocery products, such as:
例えば、あるアプリでウェブサーバと通信するものは、日用製品のJSON表現を受け取るでしょう、このように:
{
"name": "Banana",
"points": 200,
"description": "A banana grown in Ecuador.",
"varieties": [
"yellow",
"green",
"brown"
]
}
Here’s how to write a Swift type that represents a grocery product and can be used with any serialization format that provides encoders and decoders:
ここにあるのは、日用製品を表して、エンコーダおよびデコーダで提供される何らかのシリアライズ形式で使用できるスウィフト型を書く方法です:
struct GroceryProduct: Codable {
let name: String
let points: Int
let description: String
let varieties: [String]
}
You can create a GroceryProduct
from a JSON representation by creating a JSONDecoder
instance and passing it the GroceryProduct.self
type along with the JSON data:
あなたはGroceryProduct
をJSON表現から作成することがJSONDecoder
インスタンスを作成してそれをGroceryProduct.self
型にそのJSONデータとともに渡すことによって可能です。
let json = """
{
"name": "Banana",
"points": 200,
"description": "A banana grown in Ecuador.",
"varieties": [
"yellow",
"green",
"brown"
]
}
""".data(using: .utf8)!
let decoder = JSONDecoder()
let banana = try decoder.decode(GroceryProduct.self, from: json)
print("\(banana.name) (\(banana.points) points): \(banana.description)")
// Prints "Banana (200 points): A banana grown in Ecuador."
For information about encoding and decoding more complex custom types, see Encoding and Decoding Custom Types. For more information about encoding and decoding JSON, see Using JSON with Custom Types.
より複雑なカスタム型のエンコードおよびデコードについての情報として、Encoding and Decoding Custom Typesを見てください。JSONのエンコードおよびデコードについてのさらなる情報として、Using JSON with Custom Typesを見てください。
Localization
現地語化
In Objective-C, you typically use the NSLocalizedString
family of macros to localize strings. These include NSLocalizedString
, NSLocalizedStringFromTable
, NSLocalizedStringFromTableInBundle
, and NSLocalizedStringWithDefaultValue
. In Swift, the functionality of these macros is made available through a single function: NSLocalizedString(_:tableName:bundle:value:comment:)
.
Objective-Cでは、あなたは一般的に文字列を現地語化するためにマクロのNSLocalizedString
ファミリーを使います。これらは、NSLocalizedString
, NSLocalizedStringFromTable
, NSLocalizedStringFromTableInBundle
, そしてNSLocalizedStringWithDefaultValue
を含みます。スウィフトでは、これらのマクロの機能性は、ただ1つの関数:NSLocalizedString(_:tableName:bundle:value:comment:)
を通して利用可能にされます。
Rather than defining separate functions that correspond to each Objective-C macro, the Swift NSLocalizedString(_:tableName:bundle:value:)
function specifies default values for the tableName
, bundle
, and value
arguments, so that they may be overridden as necessary.
それぞれのObjective-Cマクロに対応した独立した関数を定義するのではなく、スウィフトのNSLocalizedString(_:tableName:bundle:value:)
関数はtableName
、bundle
、そしてvalue
引数に省略時の値を指定します、それでそれらは必要に応じてオーバーライドされることができます。
For example, the most common form of a localized string in an app may only need a localization key and a comment:
例えば、アプリにおける最も一般的な形式の現地語化文字列は、現地語キーとコメントを必要とするだけでしょう:
let format = NSLocalizedString("Hello, %@!", comment: "Hello, {given name}!")
let name = "Mei"
let greeting = String(format: format, arguments: [name as CVarArg])
print(greeting)
// Prints "Hello, Mei!"
Or, an app may require more complex usage in order to use localization resources from a separate bundle:
または、独立したバンドルから現地語化リソースを使うために、アプリはより複雑な語法を必要とするかもしれません:
if let path = Bundle.main.path(forResource: "Localization", ofType: "strings", inDirectory: nil, forLocalization: "ja"),
let bundle = Bundle(path: path) {
let translation = NSLocalizedString("Hello", bundle: bundle, comment: "")
print(translation)
}
// Prints "こんにちは"
For more information, see Internationalization and Localization Guide.
さらなる情報として、インターナショナライゼーションとローカリゼーションのガイド(Apple訳有り)を見てください。
Autorelease Pools
オートリリースプール
Autorelease pool blocks allow objects to relinquish ownership without being deallocated immediately. Typically, you don’t need to create your own autorelease pool blocks, but there are some situations in which either you must—such as when spawning a secondary thread—or it is beneficial to do so—such as when writing a loop that creates many temporary objects.
オートリリースプール・ブロックは、オブジェクトに直ちにデアロケートされることなしに所有権を放棄させます。概して、あなたはあなた独自のオートリリース・ブロックを作成する必要はありません、しかしいくつかの状況があり、そこにおいては、あなたが必要とする—例えば副次的スレッドを生み出す時など—もしくはそうすることが利益をもたらす—例えば多くの一時的オブジェクトを作成するあるループを書く時など—のいずれかです。
In Objective-C, autorelease pool blocks are marked using @autoreleasepool
. In Swift, you can use the autoreleasepool(_:)
function to execute a closure within an autorelease pool block.
Objective-Cでは、オートリリース・ブロックは@autoreleasepool
を使って印されます。スウィフトでは、あなたはautoreleasepool(_:)
関数を使って、あるクロージャをオートリリース・ブロックの内部で実行できます。
import Foundation
autoreleasepool {
// code that creates autoreleased objects. (オートリリースされるオブジェクトを作成するコード)
}
For more information, see Advanced Memory Management Programming Guide.
さらなる情報は、Advanced Memory Management Programming Guideを見てください。
API Availability
API有効性
Some classes and methods are not available to all versions of all platforms that your app targets. To ensure that your app can accommodate any differences in functionality, you check the availability those APIs.
いくつかのクラスやメソッドは、あなたのアプリターゲットであるすべてのプラットホームのすべてのバージョンで利用可能ではありません。あなたのアプリが機能性でのどんな違いでも調整できることを確実にするために、あなたはそれらのAPIの有効性を確認します。
In Objective-C, you use the respondsToSelector:
and instancesRespondToSelector:
methods to check for the availability of a class or instance method. Without a check, the method call throws an NSInvalidArgumentException
“unrecognized selector sent to instance” exception. For example, the requestWhenInUseAuthorization
method is only available to instances of CLLocationManager
starting in iOS 8.0 and macOS 10.10:
Objective-Cでは、あなたはrespondsToSelector:
とinstancesRespondToSelector:
メソッドを使ってクラスおよびインスタンス・メソッドの有効性を確認します。確認なしでは、メソッド呼び出しはNSInvalidArgumentException
「認識不能セレクタがインスタンスに送られます」例外をスローします。例えば、requestWhenInUseAuthorization
メソッドは、CLLocationManager
のインスタンスに対してiOS 8.0およびmacOS 10.10からのみ利用可能です:
if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)]) {
// Method is available for use. (メソッドは利用に応じられます。)
} else {
// Method is not available. (メソッドは利用できません。)
}
In Swift, attempting to call a method that is not supported on all targeted platform versions causes a compile-time error.
スウィフトでは、ターゲットにされるすべてのプラットホーム上でサポートされないメソッドを呼び出す試みは、コンパイル時エラーを生じさせます。
Here’s the previous example, in Swift:
ここにスウィフトでの以前の例があります:
let locationManager = CLLocationManager()
locationManager.requestWhenInUseAuthorization()
// error: only available on iOS 8.0 or newer (エラー:iOS 8.0以降でのみ利用可能)
If the app targets a version of iOS prior to 8.0 or macOS prior to 10.10, requestWhenInUseAuthorization()
is unavailable, so the compiler reports an error.
アプリがiOSの8.0より前のまたはmacOSの10.10より前のあるバージョンをターゲットにするならば、requestWhenInUseAuthorization()
は利用可能でありません、それでコンパイラはエラーを報告します。
Swift code can use the availability of APIs as a condition at run-time. Availability checks can be used in place of a condition in a control flow statement, such as an if
, guard
, or while
statement.
スウィフトコードは、APIの有効性をひとつの条件として使うことが実行時に可能です。有効性確認は、制御の流れ文、例えばif
、guard
、またはwhile
の中のひとつの条件の代わりに使われることができます。
Taking the previous example, you can check availability in an if
statement to call requestWhenInUseAuthorization()
only if the method is available at runtime:
以前の例をとって、あなたは有効性をif
文の中で確認して、requestWhenInUseAuthorization()
をそのメソッドが実行時に有効である場合にのみ呼び出すことができます。
let locationManager = CLLocationManager()
if #available(iOS 8.0, macOS 10.10, *) {
locationManager.requestWhenInUseAuthorization()
}
Alternatively, you can check availability in a guard
statement, which exits out of scope unless the current target satisfies the specified requirements. This approach simplifies the logic of handling different platform capabilities.
あるいはまた、あなたは有効性をguard
文の中で使うことができます、それは現在のターゲットが指定された要件を満たさない限りスコープの外に退出します。この取り組みは、異なるプラットホーム適応性の取り扱い論理を単純にします。
let locationManager = CLLocationManager()
guard #available(iOS 8.0, macOS 10.10, *) else { return }
locationManager.requestWhenInUseAuthorization()
Each platform argument consists of one of platform names listed below, followed by corresponding version number. The last argument is an asterisk (*
), which is used to handle potential future platforms.
各プラットホーム引数は、以下で箇条書きにされるプラットホーム名の1つ、それに続く該当するバージョン番号から成ります。最後の引数は、ひとつのアスタリスクです(*
)、それは潜在的な将来のプラットホームを取り扱うために使われます。
Platform Names:
iOS
iOSApplicationExtension
macOS
macOSApplicationExtension
watchOS
watchOSApplicationExtension
tvOS
tvOSApplicationExtension
All of the Cocoa APIs provide availability information, so you can be confident the code you write works as expected on any of the platforms your app targets.
Cocoa APIの全ては、有効性情報を提供します、それであなたは、あなたの書くコードが予想されるようにあなたのアプリがターゲットにするどのプラットホーム上でも機能すると確信することができます。
You can denote the availability of your own APIs by annotating declarations with the @available
attribute. The @available
attribute uses the same syntax as the #available
runtime check, with the platform version requirements provided as comma-delimited arguments.
あなたは、宣言に@available
属性で注釈を付けることによって、あなたの独自APIの有効性を示すことができます。@available
属性は、コンマ区切り引数として提供されるプラットホームバージョン要件を使う、#available
実行時確認と同じ構文を使います。
For example:
例えば:
@available(iOS 8.0, macOS 10.10, *)
func useShinyNewFeature() {
// ...
}
Processing Command-Line Arguments
コマンドライン引数の処理
On macOS, you typically open an app by clicking its icon in the Dock or Launchpad, or by double-clicking its icon from the Finder. However, you can also open an app programmatically and pass command-line arguments from Terminal.
macOSでは、あなたは通常はアプリをそれのアイコンをDockまたはLaunchpadでクリックすることで、またはそれのアイコンをFinderからダブルクリックすることで開きます。しかしながら、あなたはまたアプリをプログラムに基づきそしてコマンドライン引数を渡してTerminalから開くことができます。
You can get a list of any command-line arguments that are specified at launch by accessing the CommandLine.arguments
type property.
あなたは、起動時にCommandLine.arguments
型プロパティにアクセスすることによって指定される、あらゆるコマンドライン引数のリストを得ることができます。
$ /path/to/app --argumentName value
for argument in CommandLine.arguments {
print(argument)
}
// prints "/path/to/app"
// prints "--argumentName"
// prints "value"
The first element in CommandLine.arguments
is a path to the executable. Any command-line arguments that are specified at launch begin at CommandLine.arguments[1]
.
CommandLine.arguments
の中の最初の項目は、常に実行ファイルへのパスです。起動時に指定される何らかのコマンドライン引数は、CommandLine.arguments[1]
で始まります。
Working with Cocoa Frameworks
Cocoaフレームワークを扱う
Copyright © 2018 Apple Inc. All rights reserved. Terms of Use | Privacy Policy | Updated: 2018-03-29