سؤال

لدي جدول ذاكرة تخزين مخزنة في الجدول الزمني NSDictionary.

على سبيل المثال أدناه ، لديّ جدول زمني 13 يناير 20120 2:00 مساءً و 13 يناير 2012 2:05 مساءً. كيف يمكنني إضافة كلاهما إلى قائمة انتظار لإطلاق النار بمفردهم؟

قم ببناء ذاكرة التخزين المؤقت الجدول:

-(void) buildScheduleCache
{  
    NSCalendarDate *now = [NSCalendarDate calendarDate];

    NSFileManager *manager = [[NSFileManager defaultManager] autorelease];
    path = @"/var/mobile/Library/MobileProfiles/Custom Profiles";
    theProfiles = [manager directoryContentsAtPath:path];

    myPrimaryinfo = [[NSMutableArray arrayWithCapacity:6] retain];
    keys = [NSArray arrayWithObjects:@"Profile",@"MPSYear",@"MPSMonth",@"MPSDay",@"MPSHour",@"MPSMinute",nil];

    for (NSString *profile in theProfiles) 
    {
        plistDict = [[[NSMutableDictionary alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/%@",path,profile]] autorelease];

        [myPrimaryinfo addObject:[NSDictionary dictionaryWithObjects:
                                  [NSArray arrayWithObjects:
                                   [NSString stringWithFormat:@"%@",profile], 
                                   [NSString stringWithFormat:@"%@",[plistDict objectForKey:@"MPSYear"]], 
                                   [NSString stringWithFormat:@"%@",[plistDict objectForKey:@"MPSMonth"]], 
                                   [NSString stringWithFormat:@"%@",[plistDict objectForKey:@"MPSDay"]], 
                                   [NSString stringWithFormat:@"%@",[plistDict objectForKey:@"MPSHour"]], 
                                   [NSString stringWithFormat:@"%@",[plistDict objectForKey:@"MPSMinute"]],
                                   nil]forKeys:keys]];

        profileSched =
        [NSCalendarDate dateWithYear:[plistDict objectForKey:@"MPSYear"]
                               month:[plistDict objectForKey:@"MPSMonth"]
                                 day:[plistDict objectForKey:@"MPSDay"]
                                hour:[plistDict objectForKey:@"MPSHour"]
                              minute:[plistDict objectForKey:@"MPSMinute"]
                              second:01
                            timeZone:[now timeZone]];

        [self rescheduleTimer];
    }

    NSString *testPath = @"/var/mobile/Library/MobileProfiles/Schedules.plist";
    [myPrimaryinfo writeToFile:testPath atomically:YES];
}

جدولة الحدث:

-(void) scheduleProfiles
{
    NSFileManager *manager = [[NSFileManager defaultManager] autorelease];
    path = @"/var/mobile/Library/WrightsCS/MobileProfiles/Custom Profiles";
    theProfiles = [manager contentsOfDirectoryAtPath:path error:nil];

    for (NSString *profile in theProfiles) 
    {
        NSMutableDictionary * plistDict = [[[NSMutableDictionary alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/%@",path,profile]] autorelease];

        profileSched =
        [NSCalendarDate dateWithYear:[[plistDict objectForKey:@"MPSYear"] intValue]
                               month:[[plistDict objectForKey:@"MPSMonth"] intValue]
                                 day:[[plistDict objectForKey:@"MPSDay"] intValue]
                                hour:[[plistDict objectForKey:@"MPSHour"] intValue]
                              minute:[[plistDict objectForKey:@"MPSMinute"] intValue]
                              second:01
                            timeZone:[NSTimeZone localTimeZone]];


            NSLog(@"DATE: %@      SCHEDULE: %@      PROFILE: %@",[NSDate date],profileSched,profile);
        if([NSDate date] < profileSched)
        {
            NSLog(@"IGNORING PROFILE: %@     WITH SCHEDULE: %@",profile,profileSched);
        }else{
            //Create the timer from the Cached Array
            schedTimer = [[NSTimer alloc] initWithFireDate:profileSched //[NSDate dateWithTimeIntervalSinceNow: 10]
                                                  interval:0.1f
                                                    target:self
                                                  selector:@selector(fireCustomProfile:)
                                                  userInfo:profile
                                                   repeats:NO];//[[plistDict objectForKey:@"MPSRepeat"] boolValue]];

            MLogString(@"Scheduling Profile: %@",profile);
            [[NSRunLoop currentRunLoop] addTimer:schedTimer forMode:NSDefaultRunLoopMode];
        }
    }
}

أطلق النار على الحدث:

-(void)fireCustomProfile:(NSTimer *)timer
{   
    if([[NSDate date] earlierDate:[schedTimer fireDate]])
    {
        NSLog(@"Ignoring Profile: %@",[schedTimer userInfo]);
        return;
    }

    notify_post("com.wrightscs.MobileProfiles.setCustomProfile");
}

مثال الحدث:

<array>
    <dict>
        <key>MPSDay</key>
        <string>13</string>
        <key>MPSHour</key>
        <string>21</string>
        <key>MPSMinute</key>
        <string>15</string>
        <key>MPSMonth</key>
        <string>1</string>
        <key>MPSYear</key>
        <string>2012</string>
        <key>Profile</key>
        <string>Event 1</string>
        <key>Repeat</key>
        <true/>
    </dict>
</array>
<array>
    <dict>
        <key>MPSDay</key>
        <string>13</string>
        <key>MPSHour</key>
        <string>21</string>
        <key>MPSMinute</key>
        <string>20</string>
        <key>MPSMonth</key>
        <string>1</string>
        <key>MPSYear</key>
        <string>2012</string>
        <key>Profile</key>
        <string>Event 2</string>
        <key>Repeat</key>
        <true/>
    </dict>
</array>
هل كانت مفيدة؟

المحلول

يمكنك استخدام UilocalNotification بدلاً من nstimer. تشير القيود إلى عدم وجود إجراءات في تطبيقك دون تفاعلك ، ولكن هناك إشعار حتى إذا تم إيقاف التطبيق.

وثائق Apple حول uilocalnotifications:

تمثل مثيلات UilocalNotification الإخطارات التي يمكن لأي تطبيق جدولة لتقديمها لمستخدميه في تواريخ وأوقات محددة. نظام التشغيل مسؤول عن تقديم الإشعار في الوقت المناسب ؛ لا يجب أن يحدث التطبيق حتى يحدث هذا.

...

عندما يقدم النظام إشعارًا محليًا ، يمكن أن تحدث العديد من الأشياء ، اعتمادًا على حالة التطبيق ونوع الإخطار. إذا لم يكن التطبيق في المقدمة ومرئية ، فإن النظام يعرض رسالة التنبيه ، ويقوم شارات التطبيق ، ويلعب صوتًا - أيا كان المحدد في الإخطار. إذا كان الإشعار تنبيهًا وتم استغلال المستخدم زر الإجراء (أو ، إذا تم قفل الجهاز ، فإنه يفتح شريط التمرير) ، يتم إطلاق التطبيق. في التطبيق: didFinishLaunchingWithOptions: طريقة يمكن أن يحصل مندوب التطبيق على كائن UilocalNotification من قاموس الخيارات التي تم تمريرها باستخدام مفتاح UiapplicationLaunchOptionSlocalNotificationKey. يمكن للمندوب فحص خصائص الإخطار ، وإذا كان الإشعار يتضمن بيانات مخصصة في قاموس المستخدم الخاص به ، فيمكنه الوصول إلى هذه البيانات ومعالجتها وفقًا لذلك. من ناحية أخرى ، إذا كان الإخطار المحلي فقط يشارات في أيقونة التطبيق ، ويقوم المستخدم باستجابة بتغيير التطبيق ، والتطبيق: DidFinishLaunchingWithOptions: يتم استدعاء الطريقة ، ولكن لا يتم تضمين كائن UilocalNotification في قاموس الخيارات.

إذا كان التطبيق قبل كل شيء ومرئي عندما يقدم النظام الإشعار ، فلا يتم عرض أي تنبيه ، ولا يتم تخفيف أيقونة ، ولا يتم تشغيل أي صوت. ومع ذلك ، فإن التطبيق: didreceivelocalnotification: يسمى إذا كان مندوب التطبيق ينفذه. يتم تمرير مثيل UilocalNotification إلى هذه الطريقة ، ويمكن للمندوب التحقق من خصائصه أو الوصول إلى أي بيانات مخصصة من قاموس UserInfo.

يمكنك العثور على برنامج تعليمي جيد هنا حيث الفكرة الرئيسية مثل هذه:

إعداد الإخطار:

Class cls = NSClassFromString(@"UILocalNotification");
if (cls != nil) {
    UILocalNotification *notif = [[cls alloc] init];
    notif.fireDate = [datePicker date];
    notif.timeZone = [NSTimeZone defaultTimeZone];

    notif.alertBody = TEXT;
    notif.alertAction = LAUNCH_BUTTON;
    notif.soundName = UILocalNotificationDefaultSoundName;
    notif.applicationIconBadgeNumber = NOTIFICATIONS_REMAINING;

    NSDictionary *userDict = [NSDictionary dictionaryWithObject:CUSTOM_INFO 
                                            forKey:kRemindMeNotificationDataKey];
    notif.userInfo = userDict;

    [[UIApplication sharedApplication] scheduleLocalNotification:notif];
    [notif release];
}

التعامل مع nofitication عندما لا يتم تشغيل التطبيق (في مندوب التطبيق):

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

    Class cls = NSClassFromString(@"UILocalNotification");
    if (cls) {
        UILocalNotification *notification = [launchOptions objectForKey:
                        UIApplicationLaunchOptionsLocalNotificationKey];

        if (notification) {
            NSString *reminderText = [notification.userInfo 
                        objectForKey:kRemindMeNotificationDataKey];
           [viewController showReminder:reminderText];
        }
    }

    application.applicationIconBadgeNumber = NOTIFICATIONS_REMAINING_LESS_ONE;

    [window addSubview:viewController.view];
    [window makeKeyAndVisible];

    return YES;
}

التطبيق في المقدمة (في مندوب التطبيق):

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {

    UIApplicationState state = [application applicationState];
    if (state == UIApplicationStateInactive) {
        // Application was in the background when notification
        // was delivered.
    }
}

نصائح أخرى

هل أنت متأكد من أن مؤقتًا هو ما تريد؟ تذكر أن المؤقت نشط فقط عندما يكون تطبيقك نشطًا. لا يعمل عندما يكون التطبيق غير نشط. إذا كنت تحاول جعل تطبيقك يفعل شيئًا في أي وقت في المستقبل البعيد ، فلن يحل المؤقت مشكلتك حقًا لأنه في كل مرة تتخلى فيها عن التطبيق ، تموت جميع أجهزة ضبط الوقت.

على افتراض أنك (1) تريد فقط تعيين أجهزة ضبط الوقت للأحداث بينما يكون التطبيق نشطًا و (2) لديك دائمًا عدد غير معروف من الأحداث في قائمة الانتظار. أجهزة ضبط الوقت لعدد تعسفي للأحداث.

لحسن الحظ ، يمكن أن تمرير أجهزة ضبط الوقت أي كائن تعسفي في userInfo الخاصية حتى تريد لف كل حدث في كائن ما وتمرير هذا الكائن إلى المؤقت. ثم يمكن لطريقة إطلاق الموقت استخراج الحدث والتصرف عليه.

شيء من هذا القبيل:

// assume a data model with event objects with the attributes and methods shown

- (void) setTimerForEvent:(EventClass *) anEvent{
    [NSTimer timerWithTimeInterval:[anEvent eventTimeFromNow] 
                            target:self 
                          selector:@selector(fireEvent:) 
                          userInfo:anEvent 
                           repeats:NO];

}//------------------------------------setTimerForEvent:------------------------------------

- (void)fireEvent:(NSTimer*)theTimer{
    [self handleEvent:(EventClass *)theTimer.userInfo]; 
    [theTimer invalidate];
}//------------------------------------fireEvent:------------------------------------

ال -[EventClass eventTimeFromNow] يجب إعادة nstimerinterval من الثواني المتبقية بين الوقت الذي يتم فيه استدعاء الطريقة ووقت الحدث.

ستحتاج إلى مؤقت لكل حدث. ربما لا تخصص المؤقت إلى timer عامل. يمكنك فقط إنشاء هذه الموقتات وإطلاقها في theFireEvent. ستحتاج إلى تغيير هذا المحدد @selector(theFireEvent) رغم ذلك ، وتأكد من أن الطريقة لها توقيع:

- (void)timerFireMethod:(NSTimer*)theTimer

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top