Віддалене сповіщення iOS 8


76

Як я можу отримати маркер пристрою для віддаленого сповіщення в iOS 8? Я використовував метод didRegisterForRemoteNotificationsWithDeviceTokenв AppDelegateiOS <8, і він повернув маркер пристрою. Але в iOS 8 це не так.


Це справді спрацювало ..! stackoverflow.com/questions/4086599 / ...

Відповіді:


180

Прочитайте код у UIApplication.h.

Ви будете знати, як це зробити.

Спочатку:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

додати такий код

if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
#ifdef __IPHONE_8_0
  UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert 
      | UIUserNotificationTypeBadge 
      | UIUserNotificationTypeSound) categories:nil];
  [application registerUserNotificationSettings:settings];
#endif
} else {
  UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
  [application registerForRemoteNotificationTypes:myTypes];
}

якщо ви не використовуєте як Xcode 5, так і Xcode 6 , спробуйте цей код

if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
  UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge
      |UIRemoteNotificationTypeSound
      |UIRemoteNotificationTypeAlert) categories:nil];
  [application registerUserNotificationSettings:settings];
} else {
  UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
  [application registerForRemoteNotificationTypes:myTypes];
}

(Дякую за нагадування @zeiteisen @dmur)


Друге:

Додайте цю функцію

#ifdef __IPHONE_8_0
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
    //register to receive notifications
    [application registerForRemoteNotifications];
}

- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler
{
    //handle the actions
    if ([identifier isEqualToString:@"declineAction"]){
    }
    else if ([identifier isEqualToString:@"answerAction"]){
    }
}
#endif

І ви можете отримати пристрій, взятий

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken

якщо це все ще не працює, скористайтеся цією функцією та повідомте про помилку

-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error

4
Це. Досить інфо, Apple не змогла оновити свою документацію UIUserNotificationSettingsабо UIApplicationрозповісти про те, як це потрібно для iOS 8. Натомість вона похована в їх API-розбіжностях.
Гіпербола

27
Це призведе до збоїв у версіях iOS нижче iOS 8. #ifdef - це функція COMPILER, яка обробляється під час компіляції. Вам все ще потрібна перевірка часу роботи!
Dan VanWinkle

4
Використовуйте цей макрос для перевірки iOS 8: #define isAtLeastiOS8 ([[[[UIDevice currentDevice] systemVersion] floatValue]> = 8.0). __IPHONE_8_0 - погана перевірка, оскільки ви хочете, щоб цей код продовжував працювати і в наступних версіях.
er0

2
Тим не менш, у цьому випадку #ifdef непотрібний, якщо ваша команда не використовує як Xcode 5, так і Xcode 6. Натомість вам слід зробити if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {перевірку, як це робить zeiteisen у своїй відповіді.
dmur

6
Невелике виправлення застарілого переліку UIRemoteNotificationType: NS_ENUM_DEPRECATED_IOS (3_0, 8_0, "Використовуй UIUserNotificationType для сповіщень користувачів та реєструйForRemoteNotifications для отримання віддалених повідомлень замість цього."); Отже, для iOS 8 та пізніших версій ви повинні використовувати UIUserNotificationTypeBadge, UIUserNotificationTypeSound, UIUserNotificationTypeAlert. (UIUserNotificationType для нових версій, UIRemoteNotificationType - для старих). Перерахування, визначені в <UIKit / UIApplication.h> та <UIKit / UIUserNotificationSettings.h>
KepPM

75

Спосіб реєстрації для iOS 8 та підтримка старих версій

UIApplication *application = [UIApplication sharedApplication];
if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge
                                                                                         |UIUserNotificationTypeSound
                                                                                         |UIUserNotificationTypeAlert) categories:nil];
    [application registerUserNotificationSettings:settings];
} else {
    UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
    [application registerForRemoteNotificationTypes:myTypes];
}

а в додаток делегат додайте

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    [application registerForRemoteNotifications];
}

iOS8 може отримувати мовчазні повідомлення без запиту дозволу. Телефонуйте - (void)registerForRemoteNotifications. Після цього application:didRegisterForRemoteNotificationsWithDeviceToken:буде викликано

Примітка: зворотний виклик із маркером викликається лише в тому випадку, якщо програма успішно зареєструвалась для сповіщень користувачів за допомогою функції нижче або якщо увімкнено фонове оновлення програми.

Перевірте Налаштування для вашого додатка, якщо ввімкнено будь-який тип сповіщення. Якщо ні, то маркер пристрою ви не отримаєте.

Тепер ви можете отримувати безшумні сповіщення за допомогою

aps {
content-available: 1
}

в корисному навантаженні сповіщення

Але сповіщення, які з’являються, все ще потребують дозволу. Телефонуйте

UIUserNotificationType types = UIUserNotificationTypeSound | UIUserNotificationTypeBadge | UIUserNotificationTypeAlert;
UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
[application registerUserNotificationSettings:notificationSettings];

Цей код повинен запитувати дозволу.

Тепер ви повинні бути готові отримувати push-сповіщення


1
спасибі за OS8 can receive silent notifications without asking for permissionбіт. Це зводило мене з розуму, і це єдине місце, де я знайшов це корисне!
sbauch

@zeiteisen, у вашому першому ifтвердженні ви повинні використовувати UIUserNotificationTypeSoundзамість цього UIRemoteNotificationTypeSound, оскільки UIRemoteNotificationTypeвоно застаріло в iOS 8.
Таннер Семерад

Хтось може пояснити, чому зворотний виклик із маркером викликається лише тоді, коли увімкнено фонове оновлення програми? Я хоч його слід викликати, коли ввімкнено дозвіл на push-сповіщення ...
Gilherme.minglini

15

У моєму випадку я зробив необхідні оновлення для запиту доступу до push-сповіщень для iOS 7 та iOS 8, однак я не застосував новий зворотний виклик, коли користувач iOS 8 надає доступ. Мені потрібно було додати цей метод до делегата мого додатка.

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    [application registerForRemoteNotifications];
}

1

Якщо ви використовуєте Xamarin.iOS для створення свого мобільного додатка, ви можете використовувати цей фрагмент коду для запиту реєстрації push-сповіщень

if (UIDevice.CurrentDevice.CheckSystemVersion(8,0))
{
    UIUserNotificationType userNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound;
    UIUserNotificationSettings settings = UIUserNotificationSettings.GetSettingsForTypes(userNotificationTypes, null);
    UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
}
else
{
    UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound;
    UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes);
} 

Також вам потрібно буде замінити DidRegisterUserNotificationSettingsметод, щоб повернути маркер пристрою з сервера APNS:

public override void DidRegisterUserNotificationSettings(UIApplication application, UIUserNotificationSettings notificationSettings)
{
    application.RegisterForRemoteNotifications();
}

1

Відповідь Мадао ( https://stackoverflow.com/a/24488562/859742 ) є правильною, але ....

UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge

має бути більш "правильним"

UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert) categories:nil];

Ці прапори мають однакові значення бітової маски, і тому обидва вони працювали б, але не UIUserNotificationSettingsвимагаютьUIUserNotificationTypeUIRemoteNotificationType .

Окрім цього я би зателефонував

[application registerUserNotificationSettings:settings];

У AppDelegateметоді (залежно від наданих прав),

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings

Яка різниця?
Володимир Стажилов

1
UIUserNotificationTypeBadge та UIRemoteNotificationTypeBadge - це однакові бітові маски, але означають різні речі =)
Ilker Baltaci

0

Мені здається, що кращий спосіб зберегти зворотну сумісність, який ми можемо використати при такому підході, - це працює на мій випадок, сподіваюся, він спрацює і на вас. Також досить легко зрозуміти.

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
    {
        [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    }
    else
    {
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
         (UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert)];
    }

0
UIUserNotificationType types = UIUserNotificationTypeBadge |
    UIUserNotificationTypeSound | UIUserNotificationTypeAlert;

    UIUserNotificationSettings *mySettings =
    [UIUserNotificationSettings settingsForTypes:types categories:nil];

    [[UIApplication sharedApplication] registerUserNotificationSettings:mySettings];

    [application registerForRemoteNotifications];
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.