2012-04-18 36 views
9

與這一次有一段時間。通過控制檯從JavaScript調用Obj-C代碼:參數被丟棄?

我有一個超級簡單的Cocoa應用程序,它包含一個WebView,一個在頁面中定義的WebScripting API和一個在該API上定義的NSObject。當我打開調試器工具(在嵌入式WebView中)時,我可以在JavaScript窗口對象上看到API,並且可以看到我的「api」屬性 - 但是當我調用API的「get」方法時,參數沒有被序列化 - 當Obj-C方法被調用時,參數丟失。見下文,這有望說明:

enter image description here

我已經通過文檔梳理,我(顯然)設置相應的方法暴露需要暴露的一切,我可以看到該方法的調用。我必須要有一些愚蠢的東西,但作爲這個環境的相對新手,我沒有看到它。

在此先感謝您的幫助!

+0

有趣的是,它看起來當我打電話用的WebView加載頁面內腳本這些方法一樣,事情看起來沒問題。只有當我使用開發人員工具調用JavaScript方法時,參數纔會被刪除。同樣,方法被調用,斷點(在Xcode中),但沒有參數。難住了。 – 2012-04-18 17:23:57

+0

你是否嘗試過改變get(NSString *)輸入來獲取:(id)輸入並設置斷點(而不是NSLog),以查看是否有任何事情發生? – JoeCortopassi 2012-05-01 22:04:31

+1

我們可以請看看一些JavaScript代碼嗎? – Sam 2012-05-02 14:04:47

回答

1

根據你使用的Xcode版本,你可能會得到一個已知的錯誤。如果您對最新版本以外的任何內容使用LLDB,它可能不會在調試器中爲您提供正確的變量。在Apple解決問題之前,解決方案一直使用GDB而不是LLDB。但我認爲他們在最新版本中解決了這個問題。我會改變調試器來使用GDB,看看你是否在Xcode中獲得正確的變量。 (Product-> Edit Scheme ...-> Run - > Debugger)。但是,我在iOS中遇到了這個問題,所以我不知道它適用於OSX。無論如何值得一試。

我最初碰到問題就在這裏:https://stackoverflow.com/a/9485349/1147934

+0

最可怕的事情,但似乎並沒有工作,要麼。還是)感謝你的建議。 – 2012-05-01 17:04:08

+0

沒問題,對不起,它沒有工作。 – 2012-05-01 17:11:10

2

是否已經設置WebKitDeveloperExtras爲是在默認用戶的默認值當您發送 - [NSUserDefaults的registerDefaults:]?

+0

只是試圖確保 - 沒有骰子。哎呀!感謝您的建議。 – 2012-05-01 21:52:27

+0

爲什麼這會降低投票率? – JoeCortopassi 2012-05-02 00:03:35

0

我從存儲在apps目錄中的本地文件處理我的應用程序的主線程中的javascript。我檢查我正在執行的js函數的開始和結束標記以及函數是否包含變量。

希望這可以給你一些你的問題的好主意。您也可以在js中發出警報,以查看運行應用程序時值是否正確發佈(我確信您已經想到了這一點,但值得一提)。快樂編碼!我希望這有幫助!

在.h文件

定義:

NSMutableString *processedCommand; 
NSArray *commandArguments; 

在.m文件:

// tokens 
#define kOpenToken @"<%%" 
#define kCloseToken @"%%>" 

// this will throw 
-(void)executeJScriptCommand:(NSString *)aCommand { 

[self performSelectorOnMainThread:@selector(executeThisCommand:) withObject:aCommand waitUntilDone:YES]; 
} 

// this will throw 
-(NSString *)executeCommand:(NSString *)command { 

NSString *aCommand = [[[command stringByReplacingOccurrencesOfString:kOpenToken withString:@""] 
         stringByReplacingOccurrencesOfString:kCloseToken withString:@""] 
         stringByTrimmingLeadingAndTrailingWhitespaces]; 

if ([aCommand hasPrefix:@"="]) 
{ 
    // variable. get value 
    [self getVariableFromCommand:aCommand]; 
} 
else { 
    [self executeThisCommand:aCommand]; 
} 

NSString *returnValue = [NSString stringWithString:processedCommand]; 

self.processedCommand = nil; 
self.commandArguments = nil; 

return returnValue; 
} 

-(void)executeThisCommand:(NSString *)aCommand { 

BOOL hasError = NO; 

// clear result 
self.processedCommand = nil; 
self.commandArguments = nil; 

BOOL isFromJS = NO; 
NSString *function = nil; 
NSMutableArray *commandParts = nil; 

@try { 
    // first, break the command into its parts and extract the function that needs to be called, and the (optional) arguments 
    commandParts = [[NSMutableArray alloc] initWithArray:[aCommand componentsSeparatedByString:@":"]]; 
    if ([[[commandParts objectAtIndex:0] lowercaseString] isEqualToString:@"js-call"]) { 
     isFromJS = YES; 
     [commandParts removeObjectAtIndex:0]; 
    } 

    // get our function, arguments 
    function = [[commandParts objectAtIndex:0] retain]; 
    [commandParts removeObjectAtIndex:0]; 

    if ([commandParts count] > 0){ 
     if (isFromJS == YES) { 
      NSString *arguments = [[commandParts objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 
      if ([arguments length] > 0) { 
       self.commandArguments = [arguments JSONValue]; 
      } 
     } 
     else { 
      self.commandArguments = [NSArray arrayWithArray:commandParts]; 
     } 
    } 

    // build invoke 
    SEL sel = NSSelectorFromString(function); 

    if ([self respondsToSelector:sel]) { 

     [self performSelectorOnMainThread:sel withObject:nil waitUntilDone:YES]; 

     // using invocation causes a SIGABORT because the try/catch block was not catching the exception. 
     // using perform selector fixed the problem (i.e., the try/catch block now correctly catches the exception, as expected) 

    } 
    else { 
     [appDelegate buildNewExceptionWithName:@"" andMessage:[NSString stringWithFormat:@"Object does not respond to selector %@", function]]; 
    } 

} 
@catch (NSException * e) { 
    hasError = YES; 
    [self updateErrorMessage:[NSString stringWithFormat:@"Error processing command %@: %@", aCommand, [e reason]]]; 
} 
@finally { 
    [function release]; 
    [commandParts release]; 
} 

if (hasError == YES) { 
    [appDelegate buildNewExceptionWithName:@"executeThisCommand" andMessage:self.errorMessage]; 
} 
} 

// this can return nil 
-(NSString *)getQueryStringValue:(NSString *)name { 

NSString *returnValue = nil; 
if (queryString != nil) { 
    returnValue = [queryString objectForKey:[name lowercaseString]]; 
} 

return returnValue; 
} 
相關問題