在Photoshop SDK中发送多条消息

时间:2013-03-04 17:51:58

标签: iphone objective-c networking sdk photoshop

我正在使用Photoshop Connection SDK将我的iPad应用程序连接到Photoshop。

(如果您想近距离观看,可以在此处下载包含所有示例iOS项目的SDK:http://www.adobe.com/devnet/photoshop/sdk.html

虽然我有它工作,但我很难解决我的问题,因为我不完全理解iPad和Photoshop之间的网络。所以这是我的问题:

NSString *s1 = [NSString stringWithUTF8String:"app.activeDocument.layers[0].name;"];
NSData *dataToSend = [s1 dataUsingEncoding:NSUTF8StringEncoding];
[self sendJavaScriptMessage:dataToSend];
artLayerName_transaction = transaction_id -1;

有一小段代码,要发送一条消息,询问索引0处的图层名称。这很有用。但是,假设我尝试在此之后直接发送相同的消息,但对于索引1也是如此。

两个消息都被发送,但只有一个返回其字符串。字符串在此处返回:

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)streamEvent;

如果您看到示例项目的内容相同,则每条消息都有自己的事务ID。该方法通过一堆解密和接收该字符串的东西然后到达:

NSString *string = [[NSString alloc] initWithBytes:received_data length:received_length encoding:NSUTF8StringEncoding];
if (content != 1)
{
     if (transaction == artLayerName_transaction)
         {
              [self processLayerName:string];
              needOutput = NO;
         }
}

我已经在底部完整的方法进行全面分析。

它会检查它是否接收到特定的消息,然后我可以获取结果(字符串,我的图层名称)并按照我喜欢的方式执行操作。但是,当我尝试发送多条具有相同事务ID的消息时,我只得到两个结果中的一个。在上面的代码中,string给我两个我的图层名称,但if语句只调用一次。

是否有一种已知的方法可以同时发送多条消息?我已经尝试过一个阵列而不是几个没有运气的字符串。

显然我需要修改代码以接受更多信息。但是我并不太了解代码,所以请解释它背后的任何原理。

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)streamEvent
{
    NSInputStream * istream;
    switch(streamEvent)
    {
        case NSStreamEventHasBytesAvailable:;

            UInt8 buffer[1024];
            unsigned int actuallyRead = 0;

            istream = (NSInputStream *)aStream;
            if (!dataBuffer)
            {
                dataBuffer = [[NSMutableData alloc] initWithCapacity:2048];
            }

            actuallyRead = [istream read:buffer maxLength:1024];

            [dataBuffer appendBytes:buffer length:actuallyRead];

            // see if we have enough to process, loop over messages in buffer
            while( YES )
            {

                // Did we read the header yet?
                if ( packetBodySize == -1 )
                {
                    // Do we have enough bytes in the buffer to read the header?
                    if ( [dataBuffer length] >= sizeof(int) ) {
                        // extract length
                        memcpy(&packetBodySize, [dataBuffer bytes], sizeof(int));
                        packetBodySize = ntohl( packetBodySize );       // size is in network byte order

                        // remove that chunk from buffer
                        NSRange rangeToDelete = {0, sizeof(int)};
                        [dataBuffer replaceBytesInRange:rangeToDelete withBytes:NULL length:0];
                    }
                    else {
                        // We don't have enough yet. Will wait for more data.
                        break;
                    }
                }

                // We should now have the header. Time to extract the body.
                if ( [dataBuffer length] >= ((NSUInteger) packetBodySize) )
                {
                    // We now have enough data to extract a meaningful packet.
                    const int kPrologLength = 16;
                    char *buffer = (char *)[dataBuffer bytes];

                    // if incoming message is color change, then don't display message
                    BOOL needOutput = YES;

                    // fetch the communication status
                    unsigned long com_status = *((unsigned long *)(buffer + 0));
                    com_status = ntohl( com_status );

                    // decrypt the message
                    size_t decryptedLength = (size_t) packetBodySize - 4;  // don't include com status

                    int skip_message = 0;

                    if (com_status == 0 && sCryptorRef)
                    {
                        PSCryptorStatus decryptResult = EncryptDecrypt (sCryptorRef, false, buffer+4, decryptedLength, buffer+4, decryptedLength, &decryptedLength);

                        if (kCryptorSuccess != decryptResult)
                        {
                            // failed to decrypt.  Ingore messageg and disconnect
                            skip_message = 1;
                            [self logMessage:@"ERROR:  Decryption failed.  Wrong password.\n" clearLine:NO];
                        }
                    }
                    else
                    {
                        if (com_status != 0)
                        [self logMessage:@"ERROR: Problem with communication, possible wrong password.\n" clearLine:NO];

                        if (!sCryptorRef)
                        [self logMessage:@"ERROR: Cryptor Ref is NULL, possible reason being that password was not supplied or password binding function failed.\n" clearLine:NO];
                    }

                    // Interpret encrypted section
                    if (!skip_message)
                    {
                        // version, 32 bit unsigned int, network byte order
                        unsigned long protocol_version = *((unsigned long *)(buffer + 4));
                        protocol_version = ntohl( protocol_version );

                        if (protocol_version != 1)
                        {
                            // either the message is corrupted or the protocol is newer.
                            [self logMessage:@"Incoming protocol version is different the expected. (or the message is corrupted.)  Not processing.\n" clearLine:NO];
                            skip_message = 1;
                        }

                        if (!skip_message)
                        {
                            // transaction, 32 bit unsigned int, network byte order
                            unsigned long transaction = *((unsigned long *)(buffer + 8));
                            transaction = ntohl( transaction );

                            // content type, 32 bit unsigned int, network byte order
                            unsigned long content = *((unsigned long *)(buffer + 12));
                            content = ntohl( content );

                            unsigned char *received_data = (unsigned char *)(buffer+kPrologLength);
                            int received_length = (decryptedLength-(kPrologLength-4));

                            if (content == 3) // image data
                            {
                                // process image data
                                unsigned char image_type = *((unsigned char *)received_data);
                                [self logMessage:@"Incoming data is IMAGE.  Skipping\n" clearLine:NO];

                                if (image_type == 1) // JPEG
                                {
                                    [self logMessage:@"By the way, incoming image is JPEG\n" clearLine:NO];
                                }
                                else if (image_type == 2) // Pixmap
                                {
                                    [self logMessage:@"By the way, incoming image is Pixmap\n" clearLine:NO];
                                }
                                else
                                {
                                    [self logMessage:@"Unknown image type\n" clearLine:NO];
                                }
                            }
                            else
                            {
                                // Set the response string
                                NSString *string = [[NSString alloc] initWithBytes:received_data length:received_length encoding:NSUTF8StringEncoding];

                                //NSLog(@"string: %@\n id:%li", string, transaction);

                                // see if this is a response we're looking for
                                if (content != 1)
                                {                                    
                                    if (transaction == foregroundColor_subscription || transaction == foregroundColor_transaction)
                                    {
                                        [self processForegroundChange:string];
                                        needOutput = NO;
                                    }
                                    if (transaction == backgroundColor_subscription || transaction == backgroundColor_transaction)
                                    {
                                        [self processBackgroundChange:string];
                                        needOutput = NO;
                                    }
                                    if (transaction == tool_transaction)
                                    {
                                        [self processToolChange:string];
                                        needOutput = NO;
                                    }
                                    if (transaction == artLayerName_transaction)
                                    {
                                        [self processLayerName:string];
                                        needOutput = NO;
                                    }
                                }
                                //Tells me about every event thats happened (spammy tech nonsence, no good for user log)
                                //if (needOutput) [self logMessage:string clearLine:NO];
                            }
                        }

                    }

                    // Remove that chunk from buffer
                    NSRange rangeToDelete = {0, packetBodySize};
                    [dataBuffer replaceBytesInRange:rangeToDelete withBytes:NULL length:0];

                    // We have processed the packet. Resetting the state.
                    packetBodySize = -1;
                }
                else
                {
                    // Not enough data yet. Will wait.
                    break;
                }
            }

            break;
        case NSStreamEventEndEncountered:;
            [self closeStreams];
            [self logMessage:[NSString stringWithFormat: @"%@ End encountered, closing stream.\n", outputMessage.text] clearLine:NO];
            break;
        case NSStreamEventHasSpaceAvailable:
        case NSStreamEventErrorOccurred:
        case NSStreamEventOpenCompleted:
        case NSStreamEventNone:
        default:
            break;
    }
}

编辑:

虽然这有效,但它让我陷入了另一个问题。我查看了psconnection示例,看到了你在说什么,但是我还没有使用完整的框架,而是像其他示例项目一样连接它。每次处理图层名称时,我只需将事务ID增加1,例如上面的代码。

像这样:

if (transaction == docName_transaction)
{
     docName_transaction++;
     [self processDocName:string];
}

这在大多数情况下都有效,但是如果我在同一时间对另一个事务ID执行此操作,则会出现重叠。意思是我最终在错误的时间处理一个id的结果。假设我同时获得了文档的总数和每个文档的名称。

所以我有两个如上所述的if语句,但我最终处理了两个if语句中的总文档,我无法看到如何处理这种重叠。能够一次接收多条消息非常重要。

1 个答案:

答案 0 :(得分:0)

我刚刚下载了样本,据我所见,您应该为等待响应的事务使用唯一的事务ID。

我的意思是如果您发送带有transactionID 1的layer_name请求,则在收到响应之前不能使用1。

更好的情况是,将您的transactionID存储在Dictionary中(transactionID作为键),并将消息类型存储为值。

就像:

transactions [transaction_id] = @“layername”;

当你收到回复时:

使用: 用于获取消息类型的事务[transaction_id](例如:layername)根据此行为。

您还可以将其他一些细节添加到事务字典中(您可以放置​​包含所有信息的字典,哪个命令,哪个对象等)