简体   繁体   English

iOS 8小部件,向前和向后在应用程序组之间共享数据

[英]iOS 8 widget, sharing data between app groups forward and backward

I've a messages app and I started to create a widget. 我有一个消息应用程序,我开始创建一个小部件。 Updating the core data with the new messages happens when user open the app. 用户打开应用程序时,会使用新消息更新核心数据。 My wish is when: 我的愿望是何时:

- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler

called I will get the UIViewController and call the my get messages thread. 调用我将获取UIViewController并调用获取消息线程。 Linking the UIViewController against my widget target gave me an error: UIViewController链接到我的小部件目标给了我一个错误:

'sharedApplication' is unavailable....

So I canceled it. 所以我取消了。

What I'm trying to achieve: 1. widgetPerformUpdateWithCompletionHandler is being called 2. Application start the get messages thread/method 3. when it finish, it send back data to the widget using NSUserDefaults 我要实现的目标:1.正在调用widgetPerformUpdateWithCompletionHandler 2.应用程序启动获取消息线程/方法3.完成后,它将使用NSUserDefaults将数据发送回小部件

My code: 我的代码:

1: 1:

- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler
{
    // Perform any setup necessary in order to update the view.

    [self startGetMessages];

    // If an error is encountered, use NCUpdateResultFailed
    // If there's no update required, use NCUpdateResultNoData
    // If there's an update, use NCUpdateResultNewData

    completionHandler(NCUpdateResultNewData);
}

2: 2:

- (void)startGetMessages
{
    NSLog(@"%s", __PRETTY_FUNCTION__);

    NSBundle *deviceBundle = [NSBundle mainBundle];
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:deviceBundle];
    id MainController = [storyboard instantiateViewControllerWithIdentifier:@"MainTableViewController"];
    SEL getMessagesSelector = NSSelectorFromString(@"startGetMessages:");

    if (MainController)
    {
        NSThread *startGetMessagesThread = [[NSThread alloc] initWithTarget:MainController
                                                                   selector:getMessagesSelector
                                                                     object:StringForInt(HRTableDataSourceKindUpdate)];
        [startGetMessagesThread start];
    }
}

3: 3:

- (void)notifyWidgetForChanges
{

    __block NSMutableDictionary *newMessages = [NSMutableDictionary new];

    NSArray *results = [CoreDataPhotoRecord MR_findAllSortedBy:@"message.originalDate"
                                                     ascending:NO
                                                 withPredicate:[NSPredicate predicateWithFormat:@"(message.delete_message == %@) AND (message.type.integerValue == %d) AND (message.originalDate >= %@)",
                                                                @NO, NORMAL_MESSAGE, _notiftWidgetDate]];

    NSLog(@"%s, _notiftWidgetDate: %@, newMessages.count: %d", __PRETTY_FUNCTION__, _notiftWidgetDate, newMessages.count);

    [results enumerateObjectsUsingBlock:^(CoreDataPhotoRecord *photoDetails, NSUInteger idx, BOOL *stop)
    {
        if (photoDetails != nil && photoDetails.message != nil)
        {
            NSString *cleanMobile = [[ABAddressBook sharedAddressBook] getCleanMobile:photoDetails.message.mobile];
            Contact *person = [[ABAddressBook sharedAddressBook] findContactWithPhoneNumber:cleanMobile];
            ContactWidget *contact = [[ContactWidget alloc] init];
            contact.name = (person != nil && person.name != nil && person.name.length > 0) ? person.name : cleanMobile;

            [newMessages setObject:contact forKey:cleanMobile];
        }
    }];

    [SharedUtilities archiveObject:newMessages.copy forKey:MESSAGES_KEY_NEW widget:true];

    [DEFAULTS_WIDGET setObject:@"111" forKey:@"111"];
    [DEFAULTS_WIDGET synchronize];

    newMessages = nil;
    results = nil;
}

widgetDefaults = [[NSUserDefaults alloc] initWithSuiteName:WIDGET_GROUP_NAME];

Nothing is happen since the MainController in step 2 is nil. 由于步骤2中的MainController为nil,因此没有任何反应。 What can I do? 我能做什么?

The nil problem occurs because you try to access application's storyboard from widget. 出现nil问题是因为您尝试从小部件访问应用程序的故事板。 It's not straightforward, since the containing app and widget extension are being kept in a separate bundles. 这并不简单,因为包含的应用程序和窗口小部件扩展被保存在单独的捆绑包中。 So the [NSBundle mainBundle] in step 2) is not the same bundle as the one in your app. 因此,步骤2)中的[NSBundle mainBundle]与您的应用中的捆绑包不同。

Possible solutions include: 可能的解决方案包括:

  • including the app's Main.storyboard in extensions bundle either via adding it to Copy Bundle resources list at widget's target Build Phases tab or just adding widget target to Main.storyboard list of Target Membership 通过将应用程序的Main.storyboard添加到小部件的“目标Build Phases选项卡上的“ Copy Bundle resources列表中,或仅将小部件目标添加到目标成员资格的 Main.storyboard列表中

  • moving the code responsible for getting the messages from MainController startGetMessages: into a shared framework that will be accessible both from the app and the widget, preferably into a dedicated object. 将负责从MainController startGetMessages:获取消息的代码移动可以从应用程序和小部件均可访问的共享框架中,最好是移到专用对象中。

The second one is way better. 第二个更好。 As a rule of thumb it's best to follow SOLID principles when doing the object-oriented programming, where S stands for single responsibility . 根据经验,在进行面向对象的编程时最好遵循SOLID原则,其中S代表单一职责 It should not be a responsibility of view controller to provide the messages fetching system-wide. 视图控制器不应负责在整个系统范围内提供消息获取。 Creating a dedicated object that will have only one job - to get messages - and sharing it across the targets is a way to go. 创建一个只有一个任务的专用对象-获取消息-在目标之间共享它是一种方法。

Please consult the docs for the detailed explanation on how to create the shared framework : https://developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW1 请参阅文档以获取有关如何创建共享框架的详细说明: https : //developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/ UID / TP40014214-CH21-SW1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM