3

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 ステートメントで合計ドキュメントを処理することになり、このオーバーラップをどのように処理するかわかりません。一度に複数のメッセージを受信できることはかなり重要です。

4

1 に答える 1

0

サンプルをダウンロードしたところですが、私が見る限り、応答を待っているトランザクションには一意のトランザクション ID を使用する必要があります。

つまり、transactionID 1 で layer_name リクエストを送信すると、レスポンスが受信されるまで 1 を使用できません。

したがって、トランザクション ID をディクショナリ (トランザクション ID をキーとして) に格納し、メッセージの種類を値として格納する方がよいでしょう。

と同じように:

transactions[transaction_id] = @"layername";

そして、あなたが応答を受け取ったとき:

使用: transactions[transaction_id] を取得して、メッセージ タイプ (例: layername) をこれに従って動作させます。

その他の詳細をトランザクション ディクショナリに入れることもできます (すべての情報、どのコマンド、どのオブジェクトなどを含むディクショナリを入れることができます)

于 2013-03-09T14:32:23.853 に答える