我正在使用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语句中的总文档,我无法看到如何处理这种重叠。能够一次接收多条消息非常重要。
答案 0 :(得分:0)
我刚刚下载了样本,据我所见,您应该为等待响应的事务使用唯一的事务ID。
我的意思是如果您发送带有transactionID 1的layer_name请求,则在收到响应之前不能使用1。
更好的情况是,将您的transactionID存储在Dictionary中(transactionID作为键),并将消息类型存储为值。
就像:
transactions [transaction_id] = @“layername”;
当你收到回复时:
使用: 用于获取消息类型的事务[transaction_id](例如:layername)根据此行为。
您还可以将其他一些细节添加到事务字典中(您可以放置包含所有信息的字典,哪个命令,哪个对象等)