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 についても同様です。
両方のメッセージが送信されますが、文字列を返すのは 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 で複数のメッセージを送信しようとすると、2 つの結果のうちの 1 つしか得られません。上記のコードでは、string によって両方のレイヤー名が得られますが、if ステートメントは 1 回しか呼び出されません。
一度に複数のメッセージを送信する既知の方法はありますか? いくつかの文字列ではなく、配列を取得しようとしましたが、運もありませんでした。
どうやら、メッセージよりも多くを受け入れるようにコードを変更する必要があります。しかし、私はコードを十分に理解していないので、その背後にあるプリンシパルも説明してください。
- (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 に対して同時に行うと、重複が発生します。つまり、間違った時間に 1 つの ID の結果を処理することになります。ドキュメントの総数とそれぞれの名前の両方を取得しているとします。
したがって、上記のような 2 つの if ステートメントがありますが、両方の if ステートメントで合計ドキュメントを処理することになり、このオーバーラップをどのように処理するかわかりません。一度に複数のメッセージを受信できることはかなり重要です。