如何缓冲 iPhone 应用程序正在观察的传入事件/通知,以免触发每个事件的事件代码?

发布于 2024-12-09 12:21:41 字数 295 浏览 0 评论 0原文

缓冲 iPhone 应用程序正在观察的传入事件/通知以免触发每个事件的事件代码的最佳方法是什么?代码示例会很棒...

例如,是否可以在控制器中创建一个 NSMutableArray 以添加每个事件,并且对于其中出现的每个事件都会触发 2 秒的倒计时,因此计时器倒计时将触发事件处理代码...在这种情况下,用于此类缓冲区/计时器/倒计时的最佳 Objective-C 类是什么...

背景 - 就我而言,它是我处理的“EKEventStoreChangedNotification”事件,但请注意有多个可以通过的相同的单个日历项目更改(据我所知)

What is the best way to buffer incoming events/notifications your iPhone app is observing so as not to trigger event code for each event? A code sample would be great...

e.g. would it be to create an NSMutableArray in the controller to add each event to, and for each event that comes in it triggers a count down time for 2 seconds, so the timer countdown would trigger the events handling code...in which case what would be the best Objective-C classes to use for such a buffer/timer/countdown...

background - in my case it the events from "EKEventStoreChangedNotification" that I handle, but noting there are multiple that can come through for the same single calendar item change (well as far as i can tell)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

莳間冲淡了誓言ζ 2024-12-16 12:21:41

将一个对象附加到主运行循环(通常通过计时器)。该对象根据需要接收、收集、过滤和合并事件。

像这样的东西将是一个起点(未编译):

@interface MONEventHandler : NSObject
{
    NSMutableArray * events;
    NSRecursiveLock * lock;
}

@end

@implementation MONEventHandler

- (id)init
{
    self = [super init];
    if (nil != self) {
        events = [NSMutableArray new];
        lock = [NSRecursiveLock new];
        /* begin listening for incoming events */
    }
    return self;
}

- (void)dealloc
{
/* stop listening for incoming events */
    [lock release], lock = nil;
    [events release], events = nil;
    [super dealloc];
}

- (void)postEvents:(NSTimer *)timer
{
    [lock lock];
    /* ... clear out self.events here ... */
    [lock unlock];
}

/* a few methods for your event entries, or callbacks */

@end

现在创建计时器并将其添加到主运行循环中:

/* call me on main thread ONLY */
void SetupEventHandler() {
    MONEventHandler * eventHandler = [MONEventHandler new];
    NSTimeInterval seconds = 0.100; /* 10Hz */
    NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval:seconds target:eventHandler selector:@selector(postEvents:) userInfo:nil repeats:YES];
    /* you will need timer if you want to explicitly stop updates or destroy eventHandler. you do this by invalidating the timer. you can also access it from postEvents: */
   [eventHandler release];
}

attach an object to your main run loop (typically via a timer). the object receives, collects, filters, and coalesces the events as needed.

something like this would be a starting point (not compiled):

@interface MONEventHandler : NSObject
{
    NSMutableArray * events;
    NSRecursiveLock * lock;
}

@end

@implementation MONEventHandler

- (id)init
{
    self = [super init];
    if (nil != self) {
        events = [NSMutableArray new];
        lock = [NSRecursiveLock new];
        /* begin listening for incoming events */
    }
    return self;
}

- (void)dealloc
{
/* stop listening for incoming events */
    [lock release], lock = nil;
    [events release], events = nil;
    [super dealloc];
}

- (void)postEvents:(NSTimer *)timer
{
    [lock lock];
    /* ... clear out self.events here ... */
    [lock unlock];
}

/* a few methods for your event entries, or callbacks */

@end

Now create the timer and add it to the main run loop:

/* call me on main thread ONLY */
void SetupEventHandler() {
    MONEventHandler * eventHandler = [MONEventHandler new];
    NSTimeInterval seconds = 0.100; /* 10Hz */
    NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval:seconds target:eventHandler selector:@selector(postEvents:) userInfo:nil repeats:YES];
    /* you will need timer if you want to explicitly stop updates or destroy eventHandler. you do this by invalidating the timer. you can also access it from postEvents: */
   [eventHandler release];
}
别在捏我脸啦 2024-12-16 12:21:41

在您的 ivar 声明中:

NSMutableArray *queuedEvents;

在您的类实现中:

- (void)queueEvent:(id)event
{
    if (!queuedEvents) {
        queuedEvents = [[NSMutableArray alloc] init];
        [self performSelector:@selector(processQueuedEvents) withObject:nil afterDelay:2.0];
    }
    [queuedEvents addObject:event];
}

- (void)processQueuedEvents
{
    NSArray *events = queuedEvents;
    queuedEvents = nil;
    for (id event in events) {
        // Do something with event
    }
    [events release];
}

这将在处理事件之前缓冲最多两秒的事件。

In your ivar declaration:

NSMutableArray *queuedEvents;

In your class implementation:

- (void)queueEvent:(id)event
{
    if (!queuedEvents) {
        queuedEvents = [[NSMutableArray alloc] init];
        [self performSelector:@selector(processQueuedEvents) withObject:nil afterDelay:2.0];
    }
    [queuedEvents addObject:event];
}

- (void)processQueuedEvents
{
    NSArray *events = queuedEvents;
    queuedEvents = nil;
    for (id event in events) {
        // Do something with event
    }
    [events release];
}

This will buffer up to two seconds of events before processing them.

年华零落成诗 2024-12-16 12:21:41

使用 GCD 和块,任务的排队和执行变得非常容易。

-(void) delayHandler:(NSNotification *)notif {
   // check if notif is already on the event queue
   for (NSNotification *note in self.eventqueue) {
       if (note == notif) // use proper compare function, this is just a pointer compare
          return;
   }
   [self.eventqueue addObject:notif];

   dispatch_queue_t queue = self.handlerQueue;
   dispatch_time_t delay;delay = dispatch_time(DISPATCH_TIME_NOW, 50000 /* 50μs */);
   dispatch_after(delay, queue, ^{ 
      //event handling code here
      for (NSNotification *note in self.eventqueue) {
         // handle note in any way
         [self.eventqueue removeObject note];
      }
   );
}

只是一个总体想法。

queuing and execution of tasks became very easy with GCD and block.

-(void) delayHandler:(NSNotification *)notif {
   // check if notif is already on the event queue
   for (NSNotification *note in self.eventqueue) {
       if (note == notif) // use proper compare function, this is just a pointer compare
          return;
   }
   [self.eventqueue addObject:notif];

   dispatch_queue_t queue = self.handlerQueue;
   dispatch_time_t delay;delay = dispatch_time(DISPATCH_TIME_NOW, 50000 /* 50μs */);
   dispatch_after(delay, queue, ^{ 
      //event handling code here
      for (NSNotification *note in self.eventqueue) {
         // handle note in any way
         [self.eventqueue removeObject note];
      }
   );
}

Just a general idea.

锦欢 2024-12-16 12:21:41

我不太明白你的问题,但我假设你想对事件运行过滤器。

使用 NSNotificationCenter 有一种非常简单的方法。我们将发布通知,然后在 NSNotificationuserInfo 属性上设置一些参数,然后通过过滤器运行通知。

首先,在将发送通知的文件的 .m 中,应发送通知的位置:

NSNotification *notification = [NSNotification notificationWithName:@"notification" 
                                                             object:self
                                                           userInfo:[NSDictionary dictionaryWithObject:someFilterObject
                                                                                                forKey:@"object"]];
[[NSNotificationCenter defaultCenter] postNotification:notification];

现在,在将读取的文件的 .m 中通知:

init (或某些初始值设定项)中:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(filterNotification:)
                                             name:@"notification"
                                           object:/* the object that sends the notification */];

filterNotification:(NSNotification *)notification 中:

if ([[notification.userInfo objectForKey:@"object"] isEqual:desiredObject]) {
    // Do something
} else {
    return;
}

I don't quite understand your question, but I assume that you want to run a filter on events.

There's a pretty straightforward approach to this with NSNotificationCenter. We'll be posting a notification, then setting some parameters on the userInfo property of NSNotification, then running the notification through a filter.

First, in the .m of the file that will be sending the notification, where the notification should be sent:

NSNotification *notification = [NSNotification notificationWithName:@"notification" 
                                                             object:self
                                                           userInfo:[NSDictionary dictionaryWithObject:someFilterObject
                                                                                                forKey:@"object"]];
[[NSNotificationCenter defaultCenter] postNotification:notification];

Now, in the .m of the file that will be reading the notification:

In init (or some initializer):

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(filterNotification:)
                                             name:@"notification"
                                           object:/* the object that sends the notification */];

In filterNotification:(NSNotification *)notification:

if ([[notification.userInfo objectForKey:@"object"] isEqual:desiredObject]) {
    // Do something
} else {
    return;
}
唱一曲作罢 2024-12-16 12:21:41

我还没有研究为什么你可能会收到多个 EKEventStoreChangedNotification 事件,而且我不知道这是否正常 - 但当我读到你只是想延迟处理 2 秒时,我的第一个感觉听起来像是一个拼凑,并且有一定是解决这个问题的更好方法。

阅读 Apple 文档 它建议,如果您不想更新,除非绝对有必要这样做,您应该调用刷新,只有当这是“是”时,您才会发布并重新加载您保留的所有 EKEvent 对象。在我看来,这将确保重复的 EKEventStoreChangedNotification 消息不会导致您的代码运行多次,前提是您的代码响应此消息是在接收通知的线程上进行处理的(因此在代码执行时不会收到后续通知)响应第一个仍在运行)。

I have not looked into why you might be getting multiple EKEventStoreChangedNotification events, and I don't know if that is normal—but my first though when I read that you just wanted to delay processing by 2 seconds was that sounded like a kludge and there must be a better way to solve this.

Reading the Apple documentation it suggests that if you do not wish to update unless it is absolutely necessary to do so, you should call a refresh and only if this is YES would you then release and reload all EKEvent objects that you were retaining. It seems to me that this would ensure that duplicate EKEventStoreChangedNotification messages would not result in your code running multiple times, providing your code in response to this is processed on the thread that is receiving the notifications (so subsequent notifications are not being received while the code in response to the initial one is still running).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文