阻止与ios附件的通信

时间:2013-11-04 13:17:12

标签: ios objective-c cocoa-touch external-accessory

Apple似乎建议使用runloops与外部附件进行数据通信。但是,除非我遗漏了某些内容,否则runloops不适合某些类型的通信。

我们有一个-experimental-附件,我们需要发送任意数量的字节(最多,比如1024),然后附件处理该数据(可变延迟,比如介于1ms到1000ms之间),然后是附件的可变长度响应(最多1024个字节)。

我们希望开发一个静态库(框架)来与附件进行通信。基本上,这个库将有一个函数,它将NSArray或NSMutableArray作为输入,并返回包含响应的NSArray或NSMutableArray。

问题在于推荐的runloops策略不适合这种类型的应用程序。在静态库函数中,在准备好要传输的数据并调度传输之后,我们必须进入某种“等待”状态。但是,此等待状态不能基于轮询方法(例如等待接收路由设置的-synchronized-变量),因为接收例程永远不会执行(因为它们在同一个线程上)

如果我们不使用runloops,那么我们就不知道何时读取数据,因为我们不知道数据何时到达。

有关如何解决此问题的任何想法或建议?那里有什么例子吗?

1 个答案:

答案 0 :(得分:3)

这不是runLoop或ExternalAccessories问题。 这是每天的OOP问题。

最好的方法是创建一个可以写入outputStream并等待响应的Communication对象。 使用@protocols执行此操作! (事件监听器驱动程序)

尝试:

首先,您必须将输入/输出流附加到runLoop:

[[session inputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[[session inputStream] open];
[[session outputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[[session outputStream] open];

成为他们的代表:

[[session outputStream] setDelegate:self];
[[session inputStream] setDelegate:self];

成为委托后,您必须实施此方法:

-(void)stream:handleEvent:{};

这是将数据写入流的命令:

/* data is a NSData containing data to transmit. */
[[session outputStream] write:(uint8_t *)[data bytes] maxLength:[data length]];

这是一个示例代码,(一旦你创建了会话,而我们期望的答案是一个字节):

Comm.h中的

/* Define your protocol */
@protocol CommDelegate <NSObject>
    -(void)byteReceived: (char) byte;
@end

@interface Comm <NSObject> {
    [...]
    id<CommDelegate> delegate;
}
@end

@property (nonatomic, retain) id<CommDelegate> delegate;

在Comm.m中:

@implementation Comm

[...]
-(id)init {
    [...]
    delegate = nil;
    [...]
}

-(void)write: (NSData *) data {
    [[session outputStream] write:(uint8_t *)[data bytes] maxLength:[data length]];
}

-(void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)_event {
    switch (_event)
    {
        case NSStreamEventHasBytesAvailable:
            /* This part will be executed every time your rx buffer contains at least 1 byte */
            switch(state) {
                uint8_t ch;
                /* Read byte per byte */
                [stream read:&ch maxLength:1];
                /* now ch contains a byte from your MFI device
                ** and 'read' function decrease the length of the rx buffer by -1 */

                /* Now you can notify this to the delegate
                */
                if(self.delegate != nil)
                    [delegate byteReceived: ch];
            }
            break;
    }
}

your_app_controller.h:

@interface MyApp : UIViewController <CommDelegate> {
    Comm comm;
}
@end

<强> your_app_controller.m:

@implementation MyApp

-(id)init {
    [...]
    comm = [[Comm alloc] init];
    [comm setDelegate: self];   /* Now your thread is listening your communication. */
}

-(void)write {
    byte out = 'X';
    [comm write: [NSData dataWithBytes: &out length: 1]];
}

-(void)bytereceived:(char)reply {
    if(reply == 'Y') {
        [self write];
        //[self performSelectorInBackground:@selector(write) withObject:nil]; IT'S BETTER!!!
    }

}

@end

希望这有帮助!