Swiftの勉強方法まとめてみました。初学者の方はまずこちらを御覧ください。
クロージャーがわからないと、completionHandlerも理解できません。
クロージャーについて、理解がおぼつかない方は、まずこちらを御覧ください。
通常関数は、引数を定義して利用します。
引数がnilだったりしたら当然使えません。
どうしてクロージャーが必要かというと、グーグルマップをイメージしてください。
住所を入れないと、そもそも地図は表示できない。
住所を入力して、初めてその場所が表示されます。
住所が入力されたときに、初めて、関数内のクロージャーが実行されて、MAPを表示するイメージです。
ですから、住所が入力されるまで(引数が渡されるまで)は、その関数のクロージャー部分は、実行されなません。
大変便利ですね。
WEBなどでよく利用されるものです。
イベントドリブンといいます。何かのトリガーで関数が動く。
Swiftも同じような仕組みを備えています。それがクロージャーであり、completionHandlerというわけです。
説明してもわかりにくいので、実際のジオコーディングのコードから説明します。
//テキストフィールドに入力された住所 nilチェックをしています。
if let addressWord = address.text {
//CLGeocoderのインスタンスを生成
let geocoder = CLGeocoder()
//geocodeAddressStringは住所を入れる、その住所でもってhttp通信で帰ってきた値を利用して地図を描画
//ここでcompletionHandlerを利用 引数にplacemarks, errorを渡しているがそんな物は無い。appleMAPのAPIが返してくれて初めて存在する
geocoder.geocodeAddressString(addressWord, completionHandler: { (placemarks, error) in
//もしplacemarksがAppleMAP返却されたら配列locationsに詰め込もう!
if let locations = placemarks {
//locations配列の初めのものが目的の住所の座標値
if let firstlocation = locations.first {
if let location = firstlocation.location {
//目的地の座標値をtargetCordinateに入れよう
let targetCordinate = location.coordinate
//チェックのためにコンソールに出力
print(targetCordinate)
ここで大切なのは、下記部分です。{ }の中の (placemarks, error) がクロージャーにわたす引数です。 in の後がクロージャーの処理です。
geocoder.geocodeAddressString(addressWord, completionHandler: { (placemarks, error) in
//もしplacemarksがAppleMAP返却されたら配列locationsに詰め込もう!
if let locations = placemarks {
ユーザーが目的地を入力したら、その場所を返却する関数です。
当然ですが、ユーザーがどんな位置情報を入力するか?は実行されたときでないとわかりません。addressWord はわからないわけです。でもコードは書いておかないと当然動きません。
で、クロージャーの登場です。クロージャーは、引数が準備されたときに、実行されます。ですから、このような位置情報を返却する、ジオコーディングなどは大変利用価値が高いですし、最近のアプリは、iOS内部で完結するものは殆どありません、WEBと接続する必要があります。ですから、クロージャーは、必須です。
placemarksはアップルマップに問い合わせをしたときに、目的の座標値等のデータが返却されます。アップルのPAIから値が返却されます。
その座標値を取り出して、マーカーを表示するわけです。
placemarksは、引数として利用されていますが、アップルマップから値が返却されないと当然値はアリません。値があるときに、実行されますので、クロージャーは大変重宝する仕組みです。
UserNotificationとは、アプリのアイコンの右上につくバッジを管理する仕組みです。
なにかのアプリの情報の更新があると、その数などを、Userに教えてくれます。
しかしそれを表示するには、ユーザーの許可が必要です。そのアラートメッセージを表示させます。
そこでusreが了解したときに初めて通知(バッジ-数字のマーク)を表示できます。ちなみにアラートメッセージは以下のようなものです。
//5秒後にpush通知
//通知許可
UNUserNotificationCenter.current().getNotificationSettings{
//ここでもクロージャーを利用 settingsが返却されるのを待つ 無いときはクロージャーは実行されない。
(settings) in
//もしUserが .autorized(許可しているなら)
if(settings.authorizationStatus == .authorized){
self.push()
}else{
UNUserNotificationCenter.current().requestAuthorization(options: [.sound, .badge, .alert], completionHandler:{
//ここがクロージャー (granted, error) が引数 in 以下が実装部
//ここでユーザーが許可するかどうか尋ねています。trueは一つ以上OK,falseはすべて拒否が帰ります。
(granted, error) in
//もしerrorがあるなら
if let error = error{
//errorをデバッグエリアに出力しなさい
print(error)
}else{
//もしgrantedがあるなら(Userが許可したら=値が返却されたら)
if(granted){
//配列に追加しなさい
self.push()
}
}
})
}
}
例えて言うなら
UNUserNotificationCenterは郵便局
Notification は送られる手紙
ローカル通知やリモート通知でも同じ要領で利用されます。
func requestAuthorization(options: UNAuthorizationOptions = [],
completionHandler: @escaping (Bool, Error?) -> Void)
ここでのポイントは下記部分です。
completionHandler:{
//ここがクロージャー (granted, error) が引数 in 以下が実装部
//ここでユーザーが許可するかどうか尋ねています。trueは一つ以上OK,falseはすべて拒否が帰ります。
(granted, error) in
//もしerrorがあるなら
if let error = error{
//errorをデバッグエリアに出力しなさい
print(error)
//もしgrantedがあるなら(Userが許可したら=値が返却されたら)
if(granted){
//配列に追加しなさい
self.push()
}
ここでは同じように、(granted, error)がcompletionHandlerの引数として渡されています。
上記アラート画面でuserがOKボタンを押したときに初めて、granted以下が実行されます。
例えば、”写真へのアクセスを許可しますか?”などのアラートです。
ユーザーは認可を許可または拒否することができ、システムはユーザーの応答を保管して、このメソッドへの後続の呼び出しでユーザーに再度プロンプトを出さないようにします。
ユーザーがだめというと、falseが帰り、利用できなくなります。
このようなときにもcompletionHandlerが利用されます。
だって、まだユーザーがどんな返事をするか、事前にはわからないですよね。
基本completionHandlerはクロージャーなので、値(引数)が入ってきたときに実行されます。
とても便利ですね。
では、また!