Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ios_push_local_notification
Search
WorldDownTown
February 23, 2014
Programming
0
130
ios_push_local_notification
iOS, Objective-C, Push Notification, Local Notification
WorldDownTown
February 23, 2014
Tweet
Share
More Decks by WorldDownTown
See All by WorldDownTown
WWDC動画鑑賞会📹🍱を支える技術 / WWDC Video Lunch
worlddowntown
0
280
Live Renderingとの上手い付き合い方
worlddowntown
1
530
In-App Purchase / Subscription with StoreKit
worlddowntown
3
3k
20150225_iqon.pdf
worlddowntown
0
83
iqon_ios_growth_hack
worlddowntown
3
4.3k
Other Decks in Programming
See All in Programming
ててべんす独演会〜Flowの全てを語ります〜
tbsten
1
220
Railsだからできる 例外業務に禍根を残さない 設定設計パターン
ei_ei_eiichi
0
360
GraphQL×Railsアプリのデータベース負荷分散 - 月間3,000万人利用サービスを無停止で
koxya
1
1.2k
あなたの知らない「動画広告」の世界 - iOSDC Japan 2025
ukitaka
0
410
2分台で1500examples完走!爆速CIを支える環境構築術 - Kaigi on Rails 2025
falcon8823
3
3.3k
大規模アプリのDIフレームワーク刷新戦略 ~過去最大規模の並行開発を止めずにアプリ全体に導入するまで~
mot_techtalk
0
390
iOS 17で追加されたSubscriptionStoreView を利用して5分でサブスク実装チャレンジ
natmark
0
630
Domain-centric? Why Hexagonal, Onion, and Clean Architecture Are Answers to the Wrong Question
olivergierke
1
330
Goで実践するドメイン駆動開発 AIと歩み始めた新規プロダクト開発の現在地
imkaoru
4
710
CSC509 Lecture 02
javiergs
PRO
0
410
私達はmodernize packageに夢を見るか feat. go/analysis, go/ast / Go Conference 2025
kaorumuta
2
500
Go Conference 2025: Goで体感するMultipath TCP ― Go 1.24 時代の MPTCP Listener を理解する
takehaya
7
1.6k
Featured
See All Featured
How to train your dragon (web standard)
notwaldorf
96
6.3k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
45
2.5k
Balancing Empowerment & Direction
lara
4
680
KATA
mclloyd
32
15k
Imperfection Machines: The Place of Print at Facebook
scottboms
269
13k
Building an army of robots
kneath
306
46k
For a Future-Friendly Web
brad_frost
180
9.9k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
33
2.5k
Thoughts on Productivity
jonyablonski
70
4.9k
Done Done
chrislema
185
16k
Principles of Awesome APIs and How to Build Them.
keavy
127
17k
Transcript
1VTI-PDBM /PUJpDBUJPO ͱͦͷपล 2014/2/23 ঙ࢘ ܒี
ࣗݾհ • ঙ࢘ ܒี • twitter/github: WorldDownTown • iOSྺ1 iQONͷiOSΤϯδχΞ
J20/
J20/ ϑΝογϣϯࡶࢽΛݟΔΑ͏ʹτϨϯυ͕Θ͔ͬͯɺ ݟ͍ͯΔͷ͕௨ൢͰ͖ΔແྉͷϑΝογϣϯ ίʔσΟωʔτΞϓϦ AppStoreͷ2012ϕετΞϓϦʹબग़ʂ
࣍ • Push / Local Notification ͱʁ • Push Notification
• Local Notification • Push / Local Notificationൺֱ • iOS7ͷػೳ • ·ͱΊ
Push / Local Notification ͬͯ·͔͢ʁ
Push / Local Notification ͱʁ
Push / Local Notification ͱʁ ϩʔΧϧ௨͓Αͼϓογϡ௨͕ղܾ͢Δ ϑΥΞάϥϯυͰɺʹͭͷΞϓϦέʔγϣϯ͔͠ΞΫςΟϒʹͳΕ·ͤΜɻ ଟ͘ͷΞϓϦέʔγϣϯɺ࣌ؒϕʔε·ͨ૬ޓଓ͞ΕͨڥͰಈ࡞͍ͯ͠Δͨ ΊɺΞϓϦέʔγϣϯ͕ϑΥΞάϥϯυʹͳ͍ͱ͖ʹɺϢʔβ͕ؔ৺Λ͍࣋ͬͯΔ Πϕϯτ͕ൃੜ͢ΔՄೳੑ͕͋Γ·͢ɻ
ϩʔΧϧ௨͓Αͼϓογϡ௨ʹΑΓɺΞϓϦέʔγϣϯɺ͜ΕΒͷΠϕϯτ͕ ൃੜͨ͜͠ͱΛϢʔβʹ௨Ͱ͖ΔΑ͏ʹͳΓ·͢ɻ ʰ-PDBM͓Αͼ1VTI/PUJpDBUJPOϓϩάϥϛϯάΨΠυʱ
Push / Local Notification ͱʁ ϩʔΧϧ௨͓Αͼϓογϡ௨͕ղܾ͢Δ ϑΥΞάϥϯυͰɺʹͭͷΞϓϦέʔγϣϯ͔͠ΞΫςΟϒʹͳΕ·ͤΜɻ ଟ͘ͷΞϓϦέʔγϣϯɺ࣌ؒϕʔε·ͨ૬ޓଓ͞ΕͨڥͰಈ࡞͍ͯ͠Δͨ ΊɺΞϓϦέʔγϣϯ͕ϑΥΞάϥϯυʹͳ͍ͱ͖ʹɺϢʔβ͕ؔ৺Λ͍࣋ͬͯΔ Πϕϯτ͕ൃੜ͢ΔՄೳੑ͕͋Γ·͢ɻ
ϩʔΧϧ௨͓Αͼϓογϡ௨ʹΑΓɺΞϓϦέʔγϣϯɺ͜ΕΒͷΠϕϯτ͕ ൃੜͨ͜͠ͱΛϢʔβʹ௨Ͱ͖ΔΑ͏ʹͳΓ·͢ɻ ʰ-PDBM͓Αͼ1VTI/PUJpDBUJPOϓϩάϥϛϯάΨΠυʱ ར༻্ʹͭͳ͕Δ
Push / Local Notification ͱʁ • ܯࠂόφʔ͕දࣔ͞ΕΔ • ΞϓϦέʔγϣϯΞΠίϯʹόοδ͕ͭ͘ •
αϯυ͕໐Δ Ϣʔβʔʹͱͬͯ Push NotificationLocal Notification ಉ͡ʹݟ͑Δ
Push / Local Notification ͱʁ • ࣮ํ๏ͷҧ͍ • ϝϦοτ/σϝϦοτͷҧ͍ ΞϓϦέʔγϣϯʹͱͬͯ
Push NotificationͱLocal Notification ҧ͏ʹݟ͑Δ
࣍ • Push / Local Notification ͱʁ • Push Notification
• Local Notification • Push / Local Notificationൺֱ • iOS7ͷػೳ • ·ͱΊ
1VTI/PUJpDBUJPO
1VTI/PUJpDBUJPO • iPhone OS 3.0ʙ • αʔό͔ΒiOS௨ΛૹΔ • αʔό͔Βҙͷϝοηʔδ/λΠϛϯά Ͱૹ৴Մೳ
1VTI/PUJpDBUJPOͷΈ 1. Apple Push Notification Service (APNs) ͱ͍͏ήʔτΣΠʹσόΠε Λొ
2. σόΠε͕APNs͔ΒdeviceTokenΛड͚औΔ 3. ΞϓϦ͕σόΠε͔ΒdeviceTokenΛड͚औΔ 4. deviceTokenΛϓϩόΠμ(ΞϓϦ ӡӦऀͷαʔό)ʹొ͢Δ
1VTI/PUJpDBUJPOͷΈ 1. ϓϩόΠμdeviceTokenͱpayloadΛؚΉ௨ύοέʔδΛ࡞ ϦϞʔτ௨ͷσʔλҰํʹྲྀΕΔ 2. ϓϩόΠμͦͷ௨ΛAPNsʹૹ৴ 3. APNs͕ͦͷ௨ΛσόΠεʹ৴ʢϓογϡʣ
1VTI/PUJpDBUJPOΛૹΔ ४උ • ϓϩόΠμͷڥߏங • σόΠετʔΫϯઃఆॲཧ࣮
ϓϩόΠμͷڥߏங লུ
ϓϩόΠμͷڥߏங ໘ͳڥઃఆΛ͠ͳ͍͍ͯ͘Α͏ʹͳ͖ͬͯ·ͨ͠
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // APNsにデバイス登録 UIRemoteNotificationType notificationType
= UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert; [[UIApplication sharedApplication] registerForRemoteNotificationTypes:notificationType]; ! return YES; } - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { NSString *deviceTokenString = deviceToken.description; NSCharacterSet *characterSet = [NSCharacterSet characterSetWithCharactersInString:@"<>"]; deviceTokenString = [deviceTokenString stringByTrimmingCharactersInSet:characterSet]; deviceTokenString = [deviceTokenString stringByReplacingOccurrencesOfString:@" " withString:@""]; ! // deviceTokenStringをサーバに送信 } σόΠετʔΫϯ ઃఆॲཧ࣮ UIApplicationDelegateͷԼهͷϝιουΛ࣮
͜ΕͰ४උྃ ϓϩόΠμ͔Β 1VTIૹ৴Մೳ
Ԡ༻ • payloadͷΧελϜϓϩύςΟ • σόΠετʔΫϯઃఆλΠϛϯά
QBZMPBEͷΧελϚΠζ { "aps":{ "alert":"hello", "badge":1, "sound":"default" } } γϯϓϧͳQBZMPBE
QBZMPBEͷΧελϚΠζ { "aps":{ "alert":{ "body":"hello", "action-loc-key":"ゲームを再開", "launch-image":"push.png" }, "badge":1, "sound":"default"
} } BMFSUͷࢠϓϩύςΟͰΧελϚΠζͰ͖Δ
QBZMPBEͷΧελϚΠζ BMFSUͷࢠϓϩύςΟ Ωʔ ͷܕ આ໌ CPEZ จࣈྻ 1VTI௨࣌ͷϝοηʔδ BDUJPOMPDLFZ จࣈྻ
1VTIىಈϘλϯͷϝοηʔδ MPDLFZ จࣈྻ 1VTI௨࣌ͷϩʔΧϥΠζϝοηʔδ -PDBMJ[BCMFTUSJOHTϑΝΠϧͷΩʔΛ༩͑Δ MPDBSHT จࣈྻͷྻ MPDLFZͷॻࣜࢦఆࢠͷΘΓʹ දࣔ͢Δมจࣈྻ MBVODIJNBHF จࣈྻ 1VTI͔Βͷىಈ࣌ʹදࣔ͞ΕΔը૾ͷϑΝΠϧ໊ ࢦఆ͠ͳ͚Ε%FGBVMUQOH
QBZMPBEͷΧελϚΠζ BDUJPOMPDLFZ
QBZMPBEͷΧελϚΠζ { "aps":{ "alert":"hello", "badge":1, "sound":"default" }, "key":"value" } ΞϓϦέʔγϣϯʹLFZWBMVFΛ͢͜ͱ͕Ͱ͖Δ
Push௨ىಈͷϩάΛམͱͨ͠Γ! ىಈ࣌ͷViewControllerΛࢦఆͨ͠ΓͰ͖Δ
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSMutableDictionary *payload = [launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]
mutableCopy]; payload[@"type"] = @"not_running"; if (payload) { // アプリの未起動時にプッシュ通知を受け取り、ユーザーがアクションボタンをタップしたとき // payload[@"key"] -> value [self startWithPayload:payload]; } return YES; } - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { NSMutableDictionary *payload = userInfo.mutableCopy; if (application.applicationState == UIApplicationStateActive) { // フォアグラウンドでプッシュ通知を受け取ったとき payload[@"type"] = @"active"; } else { // アプリがサスペンド中にプッシュ通知を受け取り、ユーザーがアクションボタンをタップしたとき payload[@"type"] = @"background"; } // payload[@"key"] -> value [self startWithPayload:payload]; } UIApplicationDelegateͷԼهͷϝιουΛ࣮ QBZMPBEͷΧελϚΠζ
σόΠετʔΫϯઃఆͷ λΠϛϯά - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // APNsにデバイス登録
UIRemoteNotificationType notificationType = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert; [[UIApplication sharedApplication] registerForRemoteNotificationTypes:notificationType]; ! return YES; } Α͘ݟΔαϯϓϧ
σόΠετʔΫϯઃఆͷ λΠϛϯά ·ͩͲΜͳΞϓϦ͔Α͘Θ͔Βͳ͍ͷʹɺ! ॳճىಈͷλΠϛϯάͰϓογϡͷڐՄ! Λฉ͍ͯ͠·͏ͱڐՄͯ͠Β͑ͳ͍…
σόΠετʔΫϯઃఆͷ λΠϛϯά νϡʔτϦΞϧʹ͋ΔΑ͏ʹ! application:didFinishLaunchingWithOptions: Ͱ! registerForRemoteNotificationTypesΛίʔϧͤͣɺ! ϓογϡ௨Λड͚औΔϝϦοτड़ͨ͏͑Ͱ! ॳΊͯregisterForRemoteNotificationTypes:Λίʔϧ͢Δ iQONͰPUSHઃఆ্͕!
࣍ • Push / Local Notification ͱʁ • Push Notification
• Local Notification • Push / Local Notificationൺֱ • iOS7ͷػೳ • ·ͱΊ
-PDBM/PUJpDBUJPO • iOS 4.0ʙ • ໘ͳϓϩόΠμઃఆ͕ෆཁ • λΠϚʔ܁Γฦ͠Ͱ௨ΛදࣔͰ͖Δ • ΞϓϦ͕OSʹରͯ͠௨ͷεέδϡʔϧ
ςΩετΛઃఆ͢Δ
௨ઃఆ UILocalNotification *notification = [UILocalNotification new]; notification.alertBody = @"UILocalNotificationのテスト"; //
アラートメッセージ notification.fireDate = [[NSDate date] dateByAddingTimeInterval:(60 * 3)]; // 3分後に通知 notification.applicationIconBadgeNumber = 1; // アプリアイコンのバッジ数 notification.timeZone = [NSTimeZone localTimeZone]; // タイムゾーン notification.alertAction = @"起動して!"; // 起動ボタンのテキスト notification.hasAction = NO; // YESならアラートからアプリを起動しない notification.soundName = UILocalNotificationDefaultSoundName; // 通知音 notification.alertLaunchImage = @"push.png"; // 起動時の画像指定しなければDefault.png notification.userInfo = @{@"id":@1234}; // カスタムプロパティ [[UIApplication sharedApplication] scheduleLocalNotification:notification]; // 通知の予約 Push NotificationʹൺͨΒྦ͕ग़Δ΄Ͳ؆୯! Push Notificationͱಉ͡Α͏ͳࡉ͔͍Φϓγϣϯ͋Δ
௨Ωϟϯηϧ NSArray *notifications = [UIApplication sharedApplication].scheduledLocalNotifications; for (UILocalNotification *notification in
notifications) { if ([notification.userInfo[@"id"] integerValue] == 1234) { [[UIApplication sharedApplication] cancelLocalNotification:notification]; } } ΧϨϯμʔΞϓϦͰεέδϡʔϧΛআ࣌͠ͳͲɺ! ௨ΛΩϟϯηϧ͢Δ͜ͱ͕Ͱ͖Δ [[UIApplication sharedApplication] cancelAllLocalNotifications]; શͯͷ௨ΛΩϟϯηϧ ಛఆͷ௨ΛΩϟϯηϧ͢ΔʹuserInfoͷใ͔ΒΩϟϯηϧ͢Δ௨Λಛఆ͢Δ
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { UILocalNotification *notification = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
if (notification) { // アプリの未起動時に通知を受け取り、ユーザーがアクションボタンをタップしたとき // notification.userInfo[@"key"] -> value [self startWithNotification:notification]; } return YES; } - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { if (application.applicationState == UIApplicationStateActive) { // フォアグラウンドで通知を受け取ったとき } else { // アプリがサスペンド中に通知を受け取り、ユーザーがアクションボタンをタップしたとき } // notification.userInfo[@"key"] -> value [self startWithNotification:notification]; } UIApplicationDelegateͷԼهͷϝιουΛ࣮ (Push Notificationͱ΄΅ಉ͡) ىಈ࣌ͷ੍ޚ
-PDBM/PUJpDBUJPOԠ༻ྫ Sleipnir͕νϡʔτϦΞϧͱͯ͠Local Notification! Λར༻͍ͯ͠Δ
-PDBM/PUJpDBUJPOԠ༻ྫ ࣮Λ૾ͯ͠Έͨ • AppDelegateͷapplicationWillResignActive:Ͱ௨ͷઃఆ • notification.soundName = nil; • νϡʔτϦΞϧͱ͍ͯ͑ͨ͠ػೳΛطʹͬͨ͜ͱ͕
͋Δ߹ɺ௨ΛΩϟϯηϧ
࣍ • Push / Local Notification ͱʁ • Push Notification
• Local Notification • Push / Local Notificationൺֱ • iOS7ͷػೳ • ·ͱΊ
1VTI-PDBM/PUJpDBUJPOൺ ֱ 1VTI/PUJpDBUJPO -PDBM/PUJpDBUJPO ઃఆڥߏங ϓϩόΠμڥ 1SPWJTJPOJOHͷઃఆ͕ ඞཁ ωΠςΟϒͷίʔυ ͷΈ
௨λΠϛϯά ϓϩόΠμଆ͔Β ҙʹมߋՄೳ εέδϡʔϦϯά͕Մೳͩ ͕ɺ ௨Λઃఆ͢ΔͷΞϓϦى ಈத ௨ςΩετ ϓϩόΠμଆ͔Β ҙʹมߋՄೳ ΞϓϦ෦Ͱઃఆ มߋ͢ΔʹΞϓϦͷόʔδ ϣϯΞοϓ͕ඞཁ
࣍ • Push / Local Notification ͱʁ • Push Notification
• Local Notification • Push / Local Notificationൺֱ • iOS7ͷػೳ • ·ͱΊ
#BDLHSPVOE'FUDI
J04·Ͱͷ͓͞Β͍ • ΞϓϦ͕όοΫάϥϯυʹͳͬͨࡍͷॲཧ Իָ࠶ੜɺҐஔใऔಘɺVoIPͷΈՄೳ • ͦΕҎ֎UIApplicationͷ beginBackgroundTaskWithExpirationHandler: Ͱ όοΫάϥϯυʹߦ͔ͬͯΒ10͚ؒͩॲཧ ͕Մೳͩͬͨɻ10ޙʹαεϖϯυ͢Δ
#BDLHSPVOE'FUDI • iOS7ͰBackground ModeʹՃ͞Εͨ • 10ͷ੍ݶͳ͘ͳͬͨ • OS͕࠷దͱஅͨ͠λΠϛϯάͰόοΫάϥ ϯυॲཧΛߦ͏ •
ݺͼग़͠λΠϛϯάϢʔβʔͷΞϓϦͷར༻ ঢ়گΛΈֶͯश͢Δ
3FNPUF/PUJpDBUJPOT • iOS7ͰBackground ModeʹՃ͞Εͨ • Push NotificationΛΩʔʹόοΫάϥϯυͰॲ ཧΛ࣮ߦ͢Δ͜ͱ͕Ͱ͖Δ
3FNPUFOPUJpDBUJPOT ઃఆํ๏ XcodeͷCapabilitiesઃఆͰBackgroundMode > Remote notificationsʹνΣοΫ
UIApplicationDelegateͷԼهͷϝιουΛ࣮ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { //
コンテンツのダウンロード処理など ! if (success) { if (hasData) { // データ取得成功 completionHandler(UIBackgroundFetchResultNewData); } else { // データなし completionHandler(UIBackgroundFetchResultNoData); } } else { // データ取得失敗 completionHandler(UIBackgroundFetchResultFailed); } } 3FNPUFOPUJpDBUJPOT ઃఆํ๏
{ "aps":{ "alert":"hello", "badge":1, "sound":"default", "content-available":1 } } ϓϩόΠμ͕ૹ৴͢ΔQBZMPBEʹzDPOUFOUBWBJMBCMFzΛՃ͢Δͱ 3FNPUFOPUJpDBUJPOT
QBZMPBE - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler ͕࣮ߦ͞ΕΔ
{ "aps":{ "content-available":1 } } 4JMFOU1VTI QBZMPBEͷϝοηʔδΛࢦఆͤͣʹzDPOUFOUBWBJMBCMFz͚ͩࢦఆ͢Δͱɺ ௨͕දࣔ͞Εͣʹɺॲཧ͚࣮ͩߦ͞ΕΔ 4JMFOU1VTI
ҙ • όοΫάϯυͰΞϓϦ͕ىಈͯ͠ ͍ͳ͍ͱॲཧݺͼग़͞Εͳ͍ • iOSͷઃఆͰΞϓϦ͝ͱʹόοΫάϥ ϯυॲཧͷڐՄΛऔΓফ͢͜ͱ͕ Ͱ͖Δ ඞਢػೳͱͯ͠ఏڙ͢Δͷةݥ
࣍ • Push / Local Notification ͱʁ • Push Notification
• Local Notification • Push / Local Notificationൺֱ • iOS7ͷػೳ • ·ͱΊ
·ͱΊ 1VTI/PUJpDBUJPO • ॳճͷઃఆڥߏங͕໘ • ͦΕͰϢʔβʔ࠶ར༻ΛߴΊΔʹ ඞਢػೳ
·ͱΊ -PDBM/PUJpDBUJPO • ઃఆ͕؆୯ • ΧϨϯμʔToDoΞϓϦͳͲϢʔβʔͱ ͷίϛϡχέʔγϣϯ͕ແ͍ΞϓϦʹ ͍ͯΔ
·ͱΊ #BDLHSPVOE'FUDI • େ͖ͳσʔλΛಡΈࠐΉΑ͏ͳΞϓϦ PushͱΈ߹ΘͤΔͱ͍͍͔ • όοΫάϥϯυͰ͔͠ಈ͔ͳ͍ͷͰɺ ඞਢػೳͱ࣮ͯ͢͠Δͷةݥ
8"/5&% https://www.wantedly.com/projects/5530 iOS(ʹݶΒͣ) ΤϯδχΞืूதʂ