Objective-C实现iOS通信通知:图标显示为附件而非通知图标求助
iOS通信通知图标显示异常的Objective-C解决方案需求
我正在尝试使用Objective-C实现iOS通信通知功能,但无论采用何种写法,通知图标始终以附件形式呈现,而非作为通知图标正常显示。有趣的是,使用Swift实现相同逻辑时无此问题。经排查,核心差异在于Objective-C中没有Swift的content.updating(from: intent)对应的等效方法。由于onesignal-expo-plugin基于Objective-C开发,急需Objective-C下的解决方案。
现有Objective-C代码
#import <OneSignalFramework/OneSignalFramework.h> #import <Intents/Intents.h> #import <UserNotifications/UserNotifications.h> #import "NotificationService.h" @interface NotificationService () @property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver); @property (nonatomic, strong) UNNotificationRequest *receivedRequest; @property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent; @end @implementation NotificationService - (INSendMessageIntent *)genMessageIntentFromRequest:(UNNotificationRequest *)request { NSDictionary *custom = request.content.userInfo[@"custom"]; if (![custom isKindOfClass:[NSDictionary class]]) { return nil; } NSDictionary *a = custom[@"a"]; if (![a isKindOfClass:[NSDictionary class]]) { return nil; } NSString *name = a[@"name"]; NSString *urlString = a[@"url"]; if (!name || !urlString) { return nil; } NSURL *url = [NSURL URLWithString:urlString]; if (!url) { return nil; } INPersonHandle *handle = [[INPersonHandle alloc] initWithValue:nil type:INPersonHandleTypeUnknown]; INImage *avatar = [INImage imageWithURL:url]; INPerson *sender = [[INPerson alloc] initWithPersonHandle:handle nameComponents:nil displayName:name image:avatar contactIdentifier:nil customIdentifier:nil]; if (@available(iOSApplicationExtension 14.0, *)) { return [[INSendMessageIntent alloc] initWithRecipients:nil outgoingMessageType:INOutgoingMessageTypeOutgoingMessageText content:nil speakableGroupName:nil conversationIdentifier:nil serviceName:nil sender:sender attachments:nil]; } else { // Fallback on earlier versions return nil; } } - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler { self.receivedRequest = request; self.contentHandler = contentHandler; self.bestAttemptContent = [request.content mutableCopy]; NSDictionary *userInfo = request.content.userInfo; NSLog(@"Payload: %@", userInfo); if (@available(iOSApplicationExtension 15.0, *)) { INSendMessageIntent *intent = [self genMessageIntentFromRequest:request]; if (intent) { INInteraction *interaction = [[INInteraction alloc] initWithIntent:intent response:nil]; interaction.direction = INInteractionDirectionIncoming; [interaction donateInteractionWithCompletion:^(NSError * _Nullable error) { if (error == nil) { if (self.bestAttemptContent) { self.bestAttemptContent.title = intent.sender.displayName; self.bestAttemptContent.subtitle = self.bestAttemptContent.title; self.bestAttemptContent.body = self.bestAttemptContent.body; NSString *urlString = userInfo[@"custom"][@"a"][@"url"]; NSURL *imageURL = [NSURL URLWithString:urlString]; [self downloadImageFromURL:imageURL completion:^(UNNotificationAttachment *attachment) { if (attachment) { self.bestAttemptContent.attachments = @[attachment]; } [self forwardRequestToExtension]; }]; } else { [self forwardRequestToExtension]; } } else { [self forwardRequestToExtension]; } }]; } else { [self forwardRequestToExtension]; } } else { [self forwardRequestToExtension]; } } - (void)downloadImageFromURL:(NSURL *)url completion:(void (^)(UNNotificationAttachment *))completion { NSURLSessionDataTask *downloadTask = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (data && !error) { NSString *tempDirectory = NSTemporaryDirectory(); NSString *imagePath = [tempDirectory stringByAppendingPathComponent:@"image.jpg"]; [data writeToFile:imagePath atomically:YES]; NSURL *imageURL = [NSURL fileURLWithPath:imagePath]; UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:@"media" URL:imageURL options:nil error:nil]; completion(attachment); } else { completion(nil); } }]; [downloadTask resume]; } - (void)forwardRequestToExtension { if (self.receivedRequest && self.bestAttemptContent) { [OneSignal didReceiveNotificationExtensionRequest:self.receivedRequest withMutableNotificationContent:self.bestAttemptContent withContentHandler:self.contentHandler]; } } - (void)serviceExtensionTimeWillExpire { if (self.contentHandler && self.bestAttemptContent) { [OneSignal serviceExtensionTimeWillExpireRequest:self.receivedRequest withMutableNotificationContent:self.bestAttemptContent]; self.contentHandler(self.bestAttemptContent); } } @end
对比用的Swift代码
import UserNotifications import Intents import OneSignalExtension class NotificationService: UNNotificationServiceExtension { private var contentHandler: ((UNNotificationContent) -> Void)? private var receivedRequest: UNNotificationRequest? private var bestAttemptContent: UNMutableNotificationContent? private func genMessageIntent(from request: UNNotificationRequest) -> INSendMessageIntent? { guard let custom = request.content.userInfo["custom"] as? [String: Any], let a = custom["a"] as? [String: Any], let name = a["name"] as? String, // Name that will appear let urlString = a["url"] as? String, // Photo that will appear let url = URL(string: urlString) else { return nil } let handle = INPersonHandle(value: nil, type: .unknown) let avatar = INImage(url: url) let sender = INPerson(personHandle: handle, nameComponents: nil, displayName: name, image: avatar, contactIdentifier: nil, customIdentifier: nil) if #available(iOSApplicationExtension 14.0, *) { return INSendMessageIntent( recipients: nil, outgoingMessageType: .outgoingMessageText, content: nil, speakableGroupName: nil, conversationIdentifier: nil, serviceName: nil, sender: sender, attachments: nil ) } else { // Fallback on earlier versions return nil } } override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { self.receivedRequest = request self.contentHandler = contentHandler self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) let userInfo = request.content.userInfo print("Payload:", userInfo) if #available(iOSApplicationExtension 15.0, *) { guard let intent = genMessageIntent(from: request) else { forwardRequestToExtension() return } let interaction = INInteraction(intent: intent, response: nil) interaction.direction = .incoming interaction.donate { [weak self] error in guard let self = self, error == nil else { return } do { let content = try request.content.updating(from: intent) self.bestAttemptContent = (content.mutableCopy() as? UNMutableNotificationContent) self.forwardRequestToExtension() } catch { // Handle errors appropriately } } } else { forwardRequestToExtension() } } private func forwardRequestToExtension() { guard let receivedRequest = receivedRequest, let bestAttemptContent = bestAttemptContent else { return } OneSignalExtension.didReceiveNotificationExtensionRequest(receivedRequest, with: bestAttemptContent, withContentHandler: contentHandler) } override func serviceExtensionTimeWillExpire() { guard let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent else { return } OneSignalExtension.serviceExtensionTimeWillExpireRequest(receivedRequest!, with: bestAttemptContent) contentHandler(bestAttemptContent) } }
内容的提问来源于stack exchange,提问作者romants
相关产品推荐
相关产品推荐

