2012-04-18 57 views
9

Có một khoảng thời gian với cái này.Gọi mã Obj-C từ JavaScript thông qua Bảng điều khiển: Các đối số bị xóa?

Tôi đã có một ứng dụng Cocoa đơn giản chứa một WebView, một API WebScript được xác định trong trang và một NSObject được xác định trên API đó. Khi tôi bật công cụ gỡ lỗi (trong WebView được nhúng), tôi có thể thấy API trên đối tượng cửa sổ JavaScript và tôi có thể thấy thuộc tính "api" của tôi được xác định trên đó - nhưng khi tôi gọi phương thức "get" của API, các đối số không được tuần tự hóa - khi phương thức Obj-C được gọi, các đối số bị thiếu. Xem dưới đây, hy vọng minh họa:

enter image description here

Tôi đã chải qua các tài liệu, tôi đã (rõ ràng) thiết lập các phương pháp thích hợp để lộ tất cả những gì cần phải được tiếp xúc, và tôi có thể thấy phương pháp phúc gọi là. Tôi phải mất một cái gì đó ngu ngốc, nhưng như một người mới tương đối với môi trường này, tôi không nhìn thấy nó.

Cảm ơn trước sự giúp đỡ của bạn!

+0

thú vị, nó trông giống như khi tôi gọi những phương pháp này từ kịch bản trong một trang nạp bởi WebView, mọi thứ trông ổn. Chỉ khi tôi gọi các phương thức JavaScript với các công cụ phát triển mà các đối số bị loại bỏ. Một lần nữa, các phương thức được gọi, các điểm ngắt nhận được nhấn (trong Xcode), nhưng không có đối số. Stumped. –

+0

Bạn đã thử thay đổi get: (NSString *) đầu vào để có được: (id) đầu vào và thiết lập một breakpoint (không NSLog) chỉ để xem nếu bất cứ điều gì đang đi qua? – JoeCortopassi

+1

Chúng tôi cũng có thể xem một số mã javascript không? – Sam

Trả lời

1

Tùy thuộc vào phiên bản Xcode bạn đang sử dụng, bạn có thể gặp phải lỗi đã biết. Nếu bạn đang sử dụng LLDB trên bất kỳ thứ gì ngoài phiên bản mới nhất, nó có thể không cung cấp cho bạn các biến đúng trong trình gỡ lỗi. Giải pháp đã được sử dụng GDB thay vì LLDB cho đến khi Apple khắc phục vấn đề. Nhưng tôi nghĩ rằng họ đã khắc phục sự cố trong phiên bản mới nhất. Tôi muốn thay đổi trình gỡ lỗi để sử dụng GDB và xem liệu bạn có đang nhận được các biến đúng trong Xcode hay không. (Product-> Edit Scheme ...-> Run -> Debugger). Mặc dù vậy, tôi đã gặp vấn đề này trong iOS nên tôi không biết khả năng ứng dụng của nó cho OSX. Giá trị một thử anyway.

tôi ban đầu tình cờ gặp vấn đề ở đây: https://stackoverflow.com/a/9485349/1147934

+0

Điều đáng sợ nhất, nhưng điều đó dường như không hoạt động. Nhờ đề nghị mặc dù. –

+0

Không sao, xin lỗi nó không hoạt động. –

2

Bạn đã thiết WebKitDeveloperExtras YES ở giá trị mặc định người dùng mặc định của bạn khi bạn gửi - [NSUserDefaults registerDefaults:]?

+0

Chỉ cần cố gắng để chắc chắn - không có súc sắc. Argh! Cám ơn vì sự gợi ý. –

+0

Tại sao điều này lại được bình chọn? – JoeCortopassi

0

Tôi xử lý javascript trong chuỗi chính của ứng dụng từ một tệp cục bộ được lưu trữ trong thư mục ứng dụng. Tôi kiểm tra các thẻ bắt đầu và kết thúc cho các hàm js mà tôi đang thực hiện và liệu hàm có chứa biến hay không.

Hy vọng điều này có thể cung cấp cho bạn một số ý tưởng hay về sự cố của bạn. Bạn cũng có thể làm cảnh báo trong js để xem nếu các giá trị đăng chính xác như bạn chạy các ứng dụng (Tôi chắc chắn bạn nghĩ về điều đó đã có, nhưng nó đáng nhắc đến.) Chúc mừng mã hóa! Tôi hi vọng cái này giúp được!

trong file .h xác định:

NSMutableString *processedCommand; 
NSArray *commandArguments; 

Trong tập tin .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; 
} 
Các vấn đề liên quan