आईओएस जावास्क्रिप्ट पुल


101

मैं एक ऐसे ऐप पर काम कर रहा हूँ जहाँ मैं UI5ebView और देशी iOS फ्रेमवर्क दोनों का एक साथ उपयोग करने जा रहा हूँ। मुझे पता है कि मैं जावास्क्रिप्ट और उद्देश्य-सी के बीच संचार को लागू कर सकता हूं। क्या कोई पुस्तकालय है जो इस संचार को लागू करने को सरल बनाता है? मुझे पता है कि HTML5 और जावास्क्रिप्ट (उदाहरण के लिए AppMobi, PhoneGap) में देशी iOS ऐप बनाने के लिए कई लाइब्रेरी हैं, लेकिन मुझे यकीन नहीं है कि कोई जावास्क्रिप्ट जावास्क्रिप्ट भारी उपयोग के साथ देशी आईओएस ऐप बनाने में मदद करता है। मुझे निम्न की जरूरत है:

  1. ऑब्जेक्टिव-सी से जेएस तरीके निष्पादित करें
  2. जेएस से ऑब्जेक्टिव-सी के तरीके निष्पादित करें
  3. ऑब्जेक्टिव-सी से डोमेस्टिक जेएस इवेंट्स को सुनें (उदाहरण के लिए DOM रेडी इवेंट)

1
आप WKWebView का उपयोग कर सकते हैं: javascript window.webkit.messageHandlers से कॉल करें। {NAME} .postMessage (संदेश) और उसके बाद इसे [WKUserContentController CScriptMessageHandler: name:] के साथ Object-C को JS
Kostyl

जवाबों:


150

कुछ पुस्तकालय हैं, लेकिन मैंने इनमें से किसी भी बड़ी परियोजना का उपयोग नहीं किया है, इसलिए आप इन्हें आज़माना चाहते हैं:

-

हालाँकि, मुझे लगता है कि यह काफी सरल है कि आप इसे स्वयं आजमा सकते हैं। जब मैंने ऐसा करने की जरूरत पड़ी तो मैंने व्यक्तिगत रूप से ऐसा किया। आप एक साधारण पुस्तकालय भी बना सकते हैं जो आपकी आवश्यकताओं के अनुरूप हो।

1. ऑब्जेक्टिव-सी से जेएस तरीकों का निष्पादन करें

यह वास्तव में कोड की सिर्फ एक पंक्ति है।

NSString *returnvalue = [webView stringByEvaluatingJavaScriptFromString:@"your javascript code string here"];

आधिकारिक UIWebView प्रलेखन पर अधिक जानकारी ।

2. जेएस से उद्देश्य-सी तरीकों का निष्पादन

यह दुर्भाग्य से थोड़ा अधिक जटिल है, क्योंकि मैक ओएसएक्स पर मौजूद समान विंडोस्क्रिप्टऑबजेक्ट प्रॉपर्टी (और क्लास) दोनों के बीच पूर्ण संचार की अनुमति नहीं है।

हालाँकि, आप आसानी से जावास्क्रिप्ट कस्टम-निर्मित URL से कॉल कर सकते हैं, जैसे:

window.location = yourscheme://callfunction/parameter1/parameter2?parameter3=value

और इसे इसके साथ Objective-C से इंटरसेप्ट करें:

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
   NSURL *URL = [request URL]; 
   if ([[URL scheme] isEqualToString:@"yourscheme"]) {
       // parse the rest of the URL object and execute functions
   } 
}

यह उतना साफ नहीं है जितना होना चाहिए (या windowScriptObject का उपयोग करके) लेकिन यह काम करता है।

3. उद्देश्य-सी (उदाहरण के लिए डोम तैयार घटना) से देशी जेएस घटनाओं को सुनें

उपरोक्त स्पष्टीकरण से, आप देखते हैं कि यदि आप ऐसा करना चाहते हैं, तो आपको कुछ जावास्क्रिप्ट कोड बनाने होंगे, इसे उस घटना से संलग्न करें जिसे आप मॉनिटर करना चाहते हैं और window.locationफिर कॉल करने के लिए सही कॉल करें।

फिर से, जैसा कि होना चाहिए, साफ नहीं है, लेकिन यह काम करता है।


12
संकेत: अपनी योजना में अंडरस्कोर या समान न डालें।
फेब

4
और जब आप
मानने वाले हों

2
एक और संकेत: झिलमिलाहट को रोकने के लिए एक iFrame में URL लोड करें
iCaramba

@Folleto हाय, आपने कहा "लेकिन मैंने बड़ी परियोजनाओं में इनमें से किसी का भी उपयोग नहीं किया", क्यों नहीं ?? क्या आपको इन पुस्तकालयों में कई मुद्दे मिले ??? अग्रिम में धन्यवाद।
जेईआरसी

1
कोई बात नहीं। मैंने बस उनका उपयोग नहीं किया, इसलिए मैं बड़ी परियोजनाओं पर उनका उपयोग करने पर टिप्पणी नहीं कर सकता। मैं यह स्पष्ट करना चाहता था। :)
फोलेटो

57

स्वीकार किए गए उत्तर में JS से ऑब्जेक्टिव कॉलिंग की सुझाई गई विधि की सिफारिश नहीं की गई है। समस्याओं का एक उदाहरण: यदि आप लगातार दो कॉल करते हैं तो एक को अनदेखा कर दिया जाता है (आप स्थान को बहुत तेज़ी से नहीं बदल सकते हैं)।

मैं निम्नलिखित वैकल्पिक दृष्टिकोण की सिफारिश करता हूं:

function execute(url) 
{
  var iframe = document.createElement("IFRAME");
  iframe.setAttribute("src", url);
  document.documentElement.appendChild(iframe);
  iframe.parentNode.removeChild(iframe);
  iframe = null;
}

आप executeबार-बार फ़ंक्शन को कॉल करते हैं और चूंकि प्रत्येक कॉल अपने स्वयं के iframe में निष्पादित होती है, उन्हें जल्दी से कॉल करने पर नजरअंदाज नहीं किया जाना चाहिए।

इस आदमी को श्रेय ।


1
आप जावास्क्रिप्ट में एक कतार का उपयोग भी कर सकते हैं जो कि संदेशों को जल्दी से बदलने से बचाने के लिए iOS प्राप्त कर सकता है। ऊपर दिए गए कार्यान्वयन, github.com/marcuswestin/WebViewJavascriptBridge , एक कतार दृष्टिकोण का उपयोग करता है।
kevintcoughlin

12

अद्यतन: यह iOS 8 में बदल गया है। मेरा उत्तर पिछले संस्करणों पर लागू होता है।

एक विकल्प, जो आपको ऐप स्टोर से खारिज कर दिया जा सकता है, वेबस्क्रिप्टऑब्जेक्ट का उपयोग करना है।

ये API OSX पर सार्वजनिक हैं, लेकिन iOS पर नहीं हैं।

आपको आंतरिक कक्षाओं में इंटरफेस को परिभाषित करने की आवश्यकता है।

@interface WebScriptObject: NSObject
@end

@interface WebView
- (WebScriptObject *)windowScriptObject;
@end

@interface UIWebDocumentView: UIView
- (WebView *)webView;
@end

आपको अपनी ऑब्जेक्ट को परिभाषित करने की आवश्यकता है जो आपके WebScriptObject के रूप में काम करने वाली है

@interface WebScriptBridge: NSObject
- (void)someEvent: (uint64_t)foo :(NSString *)bar;
- (void)testfoo;
+ (BOOL)isKeyExcludedFromWebScript:(const char *)name;
+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector;
+ (WebScriptBridge*)getWebScriptBridge;
@end

static WebScriptBridge *gWebScriptBridge = nil;

@implementation WebScriptBridge
- (void)someEvent: (uint64_t)foo :(NSString *)bar
{
    NSLog(bar);
}

-(void)testfoo {
    NSLog(@"testfoo!");
}

+ (BOOL)isKeyExcludedFromWebScript:(const char *)name;
{
    return NO;
}

+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector;
{
    return NO;
}

+ (NSString *)webScriptNameForSelector:(SEL)sel
{
    // Naming rules can be found at: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/WebKit/Protocols/WebScripting_Protocol/Reference/Reference.html
    if (sel == @selector(testfoo)) return @"testfoo";
    if (sel == @selector(someEvent::)) return @"someEvent";

    return nil;
}
+ (WebScriptBridge*)getWebScriptBridge {
    if (gWebScriptBridge == nil)
        gWebScriptBridge = [WebScriptBridge new];

    return gWebScriptBridge;
}
@end

अब उस उदाहरण को अपने UIWebView पर सेट करें

if ([uiWebView.subviews count] > 0) {
    UIView *scrollView = uiWebView.subviews[0];

    for (UIView *childView in scrollView.subviews) {
        if ([childView isKindOfClass:[UIWebDocumentView class]]) {
            UIWebDocumentView *documentView = (UIWebDocumentView *)childView;
            WebScriptObject *wso = documentView.webView.windowScriptObject;

            [wso setValue:[WebScriptBridge getWebScriptBridge] forKey:@"yourBridge"];
        }
    }
}

अब आपकी जावास्क्रिप्ट के अंदर आप कॉल कर सकते हैं:

yourBridge.someEvent(100, "hello");
yourBridge.testfoo();

मेरा ऐप ऐप स्टोर में अस्वीकार कर दिया गया है। : इस मुद्दे को मैं प्राप्त था "UIWebDocumentView एप्लिकेशन शामिल है या AppName में गैर सरकारी कक्षाओं से विरासत में मिली"
चंद्रू

5

IOS8 में आप UIWebView के बजाय WKWebView को देख सकते हैं । इसमें निम्न वर्ग है: WKScriptMessageHandler: एक वेबपेज में चल रहे जावास्क्रिप्ट से संदेश प्राप्त करने के लिए एक विधि प्रदान करता है।


बेशक, लेकिन विधि निरंतरता को निष्पादित नहीं कर रही है .. यह एक बग में है जो कि सेब द्वारा प्रदान किया जाता है
जोश केथपल्ली

WKWebViewकुकीज़ को ठीक से नहीं संभालने सहित कई समस्याएं हैं। यहाँ आने वाले किसी भी व्यक्ति के लिए बस एक चेतावनी, इसे अपनाने से पहले आपकी सभी समस्याओं को हल कर दिया जाएगा - Google थोड़ा सा।
CupawnTae

3

IOS7, चेकआउट http://blog.bignerdranch.com/3784-javascriptcore-and-ios-7/ के साथ यह संभव है


3
वास्तव में नहीं: JavaScriptCore UIWebViews के साथ बातचीत नहीं करता है। यह एक महान उपकरण है, लेकिन समस्याओं के एक अलग वर्ग के लिए। ;)
फोलेट्टो

1
हाँ यह करता है: JSContext * संदर्भ = [_webView मानForKeyPath: @ "documentView.webView.mainFrame.javaScriptContext"]; लेकिन किसी भी वास्तविक उपयोग के लिए JavaScriptCore इस समय बहुत छोटा है।
मल्हल

0

आपका सबसे अच्छा शर्त Appcelerators Titanium की पेशकश है। वे पहले ही एक वीजे इंजन जावास्क्रिप्ट इंजन का उपयोग कर Obj-C जावास्क्रिप्ट पुल का निर्माण कर चुके हैं जो वेबकिट द्वारा उपयोग किया जाता है। यह भी खुला स्रोत है, इसलिए आप इसे डाउनलोड कर सकते हैं और ओब्ज-सी के साथ टिंकर कर सकते हैं जैसे आप चाहते हैं।


@ बोवा, नो ऑब्ज-सी वी 8 ब्रिज है। V8 केवल एंड्रॉइड के लिए लीवरेज्ड है।
रोस

0

किरिनजेएस परियोजना पर एक नज़र डालें: किरिन जेएस जो एप्लिकेशन लॉजिक और देशी यूआई के लिए जावास्क्रिप्ट का उपयोग करने की अनुमति देती है, जिस पर वह चलता है।


क्या अब भी कोई किरिन में योगदान देता है? मुझे पिछले कुछ महीनों में कोई गतिविधि नहीं दिख रही है ...
सैम

0

मैंने WebViewJavascriptBridge जैसी लाइब्रेरी बनाई, लेकिन यह अधिक JQuery की तरह है, सेटअप करना आसान है और उपयोग करना आसान है। JQuery पर भरोसा नहीं करता है (हालांकि इसके क्रेडिट के लिए, मुझे पता था कि यह देखने से पहले WebViewJavascriptBridge अस्तित्व में था, मैं सिर्फ डाइविंग से पहले थोड़ा वापस आयोजित किया जा सकता है)। आप क्या सोचते हैं मुझे बताओ! jockeyjs


0

आप iOS 8 पर WKWebView का उपयोग कर रहे हैं, तो एक बार देख ले XWebView जो स्वचालित रूप से जावास्क्रिप्ट के मूल निवासी इंटरफ़ेस का पर्दाफाश कर सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.