2014-04-30 32 views
1

我在我的iOS增强现实iOS项目中从Metaio第三方sdk获得了Logic.js文件。这个.JS文件是由Metaio创建者创建的。从Javascript调用iOS到iOS Webview委托不是触发

我正在修改这个文件来调用我的iOS原生web视图。基本上,我想从这个.JS文件调用iOS本机视图。

下面是iOS项目中使用的Logic.js文件。使用window.location我试图从这个.JS文件调用UIWebview委托。

var methodExists = function (object, method) { 
    return typeof object !== 'undefined' && typeof method === 'function'; 
}; 

arel.sceneReady(function() { 

    var scenario = {}; 
    scenario.objectName = "scenario"; 
    scenario.contents = []; // Array of all contents in this AR scenario 
    scenario.trackables = []; // Array of all trackables in this AR scenario 
    scenario.scenes = []; // Array of all scenes in this AR scenario 
    scenario.googleAnalytics = null; 
    scenario.currentScene = null; 
    scenario.currentExperience360 = null; 
    scenario.instantTrackingMode = false; // True if instant tracking is currently running 
    scenario.currentTrackingConfigPathOrIdentifier = "html/resources/TrackingData.zip"; 

    scenario.addObject = function (object) { 
     arel.Debug.log("scenario.addObject(" + object.objectName + ")"); 
     this.registerObject(object); 
     arel.Scene.addObject(object); 
    }; 

    scenario.registerObject = function (object) { 
     arel.Debug.log("scenario.registerObject(" + object.objectName + ")"); 
     arel.Events.setListener(object, this.objectEventsCallback, scenario); 
    }; 

    scenario.groupID = 0; 
    scenario.getNewGroupID = function() { 
     this.groupID++; 
     return this.groupID; 
    }; 

    scenario.getTrackable = function (identifier) { 
     arel.Debug.log("scenario.getTrackable(" + identifier + ")"); 
     var i; 
     var trackable = null; 
     if (!identifier || identifier === "") { 
      arel.Debug.log("scenario.getTrackable(): Warning - identifier is empty, returning null"); 
      return trackable; 
     } 
     var allTrackables = this.trackables; 
     for (i = 0; i < allTrackables.length; ++i) { 
      trackable = allTrackables[i]; 
      if (trackable.objectName == identifier) { 
       return trackable; 
      } 
      if (trackable.cosName == identifier) { 
       return trackable; 
      } 
      if (trackable.cosID == identifier) { 
       return trackable; 
      } 
     } 
     arel.Debug.log("scenario.getTrackable(" + identifier + "): Error - could not correlate the given identifier to any known trackable."); 
     return null; 
    }; 

    scenario.sceneCallback = function (type, result) { 
     if (!type) { 
      return; 
     } 
     switch (type) { 
     case arel.Events.Scene.ONTRACKING: 
      this.onTrackingChanged(result); 
      break; 
     case arel.Events.Scene.ONVISUALSEARCHRESULT: 
      break; 
     case arel.Events.Scene.ONREADY: 
      break; 
     case arel.Events.Scene.ONLOAD: 
     case arel.Events.Scene.ONLOCATIONUPDATE: 
     default: 
      break; 
     } 
    }; 

    scenario.objectEventsCallback = function (object, type, params) { 
     switch (type) { 
     case arel.Events.Object.ONREADY: 
      if (methodExists(object, object.onLoaded)) { 
       object.onLoaded(); 
      } 
      break; 
     case arel.Events.Object.ONTOUCHSTARTED: 
      if (this.googleAnalytics) { 
       this.googleAnalytics.logUIInteraction(arel.Plugin.Analytics.Action.TOUCHSTARTED, object.getID()); 
      } 
      break; 
     case arel.Events.Object.ONTOUCHENDED: 
      if (this.googleAnalytics) { 
       this.googleAnalytics.logUIInteraction(arel.Plugin.Analytics.Action.TOUCHENDED, object.getID()); 
      } 
      break; 
     case arel.Events.Object.ONINVISIBLE: 
     case arel.Events.Object.ONVISIBLE: 
     case arel.Events.Object.ONANIMATIONENDED: 
     case arel.Events.Object.ONMOVIEENDED: 
     case arel.Events.Object.ONLOAD: 
     case arel.Events.Object.ONROTATED: 
     case arel.Events.Object.ONSCALED: 
     case arel.Events.Object.ONTRANSLATED: 
     default: 
      break; 
     } 
    }; 

    scenario.onTrackingChanged = function (trackingValuesList) { 
     if (trackingValuesList.length === 0) { 
      arel.Debug.log("scenario.onTrackingChanged: Error - list of tracking values is empty, this should be impossible."); 
      return; 
     } 
     var i, trackingValues, cosName, cosID, trackable, trackingMethod, gaTrackingMethod; 
     for (i = 0; i < trackingValuesList.length; i++) { 
      trackingValues = trackingValuesList[i]; 
      trackable = null; 
      cosName = trackingValues.getCoordinateSystemName(); 
      cosID = trackingValues.getCoordinateSystemID(); 
      // Try to find the trackable by its COS name first. If that fails, try the COS ID. 
      if (cosName && cosName !== "") { 
       trackable = this.getTrackable(cosName); 
      } 
      if (trackable === null && cosID) { 
       trackable = this.getTrackable(cosID); 
      } 
      if (trackable === null) { 
       arel.Debug.log("onTrackingChanged: Error - Can't find a trackable matching COS name '" + cosName + "' or COS ID '" + cosID + "'"); 
       return; 
      } 
      else { 
       // The cosID 1 is strictly reserved for the 360 experience if it is running. 
       if (scenario.currentExperience360 && cosID === 1) { 
        return; 
       } 
      } 

      switch (trackingValues.getState()) { 
      case arel.Tracking.STATE_NOTTRACKING: 
       arel.Debug.log("onTrackingChanged: " + trackable.objectName + " is not tracking"); 
       if (methodExists(trackable, trackable.onTrackingLost)) { 
        trackable.onTrackingLost(trackingValues); 
       } 
       break; 
      case arel.Tracking.STATE_TRACKING: 
       arel.Debug.log("onTrackingChanged: " + trackable.objectName + " is tracking"); 
       if (methodExists(trackable, trackable.onDetected)) { 
        trackable.onDetected(); 
       } 
       if (methodExists(trackable, trackable.onTracked)) { 
        trackable.onTracked(trackingValues); 
       } 
       if (this.googleAnalytics) { 
        trackingMethod = trackingValues.getType(); 
        gaTrackingMethod = this.googleAnalytics.trackingTypeToAnalyticsType(trackingMethod); 
        this.googleAnalytics.logTrackingEvent(gaTrackingMethod, arel.Plugin.Analytics.Action.STATE_TRACKING, cosID, cosName); 
       } 
       break; 
      case arel.Tracking.STATE_EXTRAPOLATED: 
      case arel.Tracking.STATE_INITIALIZED: 
      case arel.Tracking.STATE_REGISTERED: 
      default: 
       break; 
      } 
     } 
    }; 


    scenario.startInstantTracking = function() { 
     arel.Debug.log("scenario.startInstantTracking()"); 
     if (this.instantTrackingMode) { 
      return; 
     } 
     this.instantTrackingMode = true; 

      if (scenario.currentExperience360) { 
      scenario.currentExperience360.hide(); 
     } 

     // Iterate over all trackables, simulate an onTrackingLost() for all those which are currently tracking. 
     var i, trackable; 
     for (i = 0; i < this.trackables.length; ++i) { 
      trackable = this.trackables[i]; 
      if (trackable.isCurrentlyTracking && trackable != userDevice) { 
       if (methodExists(trackable, trackable.onTrackingLost)) { 
        trackable.onTrackingLost(); 
       } 
      } 
     } 
     arel.Scene.startInstantTracking(arel.Tracking.INSTANT2D); 
     if (methodExists(this, this.onStartInstantTracking)) { 
      this.onStartInstantTracking(); 
     } 
    }; 

    scenario.stopInstantTracking = function() { 
     arel.Debug.log("scenario.stopInstantTracking()"); 
     if (!this.instantTrackingMode) { 
      return; 
     } 
     this.instantTrackingMode = false; 
     if (methodExists(instantTracker, instantTracker.onTrackingLost)) { 
      instantTracker.onTrackingLost(); 
     } 
     this.setTrackingConfiguration(this.currentTrackingConfigPathOrIdentifier); 
     if (methodExists(this, this.onStopInstantTracking)) { 
      this.onStopInstantTracking(); 
     } 
    }; 

    scenario.skipTrackingInitialization = function() { 
     arel.Debug.log("scenario.skipTrackingInitialization()"); 
     arel.Scene.sensorCommand("initialize", "", function(a) {}); 
     if (methodExists(this, this.onSkipTrackingInitialization)) { 
      this.onSkipTrackingInitialization(); 
     } 
    }; 

    scenario.reloadTrackingConfiguration = function() { 
     arel.Debug.log("scenario.reloadTrackingConfiguration()"); 
     this.setTrackingConfiguration(this.currentTrackingConfigPathOrIdentifier); 
     if (methodExists(this, this.onReloadTrackingConfiguration)) { 
      this.onReloadTrackingConfiguration(); 
     } 
    }; 

    scenario.setTrackingConfiguration = function (trackingConfigPathOrIdentifier) { 
     // Iterate over all trackables, simulate an onTrackingLost() for all those which are currently tracking. 
     var i, trackable; 
     for (i = 0; i < this.trackables.length; ++i) { 
      trackable = this.trackables[i]; 
      if (trackable.isCurrentlyTracking && trackable != userDevice) { 
       if (methodExists(trackable, trackable.onTrackingLost)) { 
        trackable.onTrackingLost(); 
       } 
      } 
     } 

     // Set the new tracking configuration. 
     arel.Scene.setTrackingConfiguration(trackingConfigPathOrIdentifier); 
    }; 

    scenario.onStartup = function() { 
     arel.Debug.log("Welcome to the 'HouseProject' Augmented Reality experience."); 

     arel.Events.setListener(arel.Scene, scenario.sceneCallback, scenario); 

     if (google_analytics_id) { 
      arel.Debug.log("Google Analytics is enabled. Your account ID is: " + google_analytics_id); 
      arel.Debug.log("The event sampling rate is: arel.Plugin.Analytics.EventSampling.ONCE"); 
      scenario.googleAnalytics = new arel.Plugin.Analytics(google_analytics_id, arel.Plugin.Analytics.EventSampling.ONCE, ""); 
     } else { 
      arel.Debug.log("Note: No Google Analytics ID is set - Google Analytics will be disabled."); 
     } 

     if (methodExists(scenario, scenario.onLoaded)) { 
      scenario.onLoaded(); 
     } 

     // The following contents have been defined in the index.xml file, therefore we need to register them 
     // and call their onLoaded() event manually. 
     scenario.registerObject(model6); 
     if (methodExists(model6, model6.onLoaded)) { 
      model6.onLoaded(); 
     } 
     scenario.registerObject(model7); 
     if (methodExists(model7, model7.onLoaded)) { 
      model7.onLoaded(); 
     } 


     if (methodExists(userDevice, userDevice.onLoaded)) { 
      userDevice.onLoaded(); 
     } 

     // All objects have been defined, so start the AR experience by calling each trackable's .onLoaded() method. 
     var i, trackable; 
     for (i = 0; i < scenario.trackables.length; ++i) { 
      trackable = scenario.trackables[i]; 
      if (methodExists(trackable, trackable.onLoaded)) { 
       trackable.onLoaded(); 
      } 
     } 

     // Call the first scene's display() once to make sure that the content of that scene is initially visible. 
     scene1.display(); 
    }; 


    var scene1 = {}; 
    scenario.scenes.push(scene1); 
    scene1.objectName = "scene1"; 

    scene1.display = function() { 
     arel.Debug.log(this.objectName + ".display()"); 

     if (scenario.currentScene == this) { 
      return; 
     } 

     // Iterate over all trackables, simulate an onTrackingLost() for all those which are currently tracking. 
     var trackingTrackables = []; 
     var i, trackable; 
     for (i = 0; i < scenario.trackables.length; ++i) { 
      trackable = scenario.trackables[i]; 
      if (trackable.isCurrentlyTracking) { 
       // The instant tracker should be excluded from the tracking ones because it will be stopped later on. 
       if (trackable !== instantTracker) { 
        trackingTrackables.push(trackable); 
       } 
       if (methodExists(trackable, trackable.onTrackingLost)) { 
        trackable.onTrackingLost(); 
       } 
      } 
     } 

     // In case any instant tracking is currently running, stop it before switching to the other scene. 
     scenario.stopInstantTracking(); 

     var previousExperience360 = null; 
     if (scenario.currentExperience360) { 
      previousExperience360 = scenario.currentExperience360; 
      scenario.currentExperience360.hide(); 
     } 

     scenario.currentScene = this; 

     // Iterate over all tracking trackables again, this time simulating an onDetected() and onTracked() event 
     // for all those which are currently tracking. 
     for (i = 0; i < trackingTrackables.length; ++i) { 
      trackable = trackingTrackables[i]; 
      if (methodExists(trackable, trackable.onDetected)) { 
       trackable.onDetected(); 
      } 
      if (methodExists(trackable, trackable.onTracked)) { 
       trackable.onTracked(trackable.currentTrackingValues); 
      } 
     } 

     if (previousExperience360) { 
      // A 360 was displayed in the previous scene, we now need to check whether any 360 in the new scene 
      // is triggered by the same trackable. If so, that 360 should be displayed. 
      var i, content; 
      for (i = 0; i < scenario.contents.length; ++i) { 
       content = scenario.contents[i]; 
       if (content.type == "Experience360" && content.scene == this && 
        content.associatedTrackable == previousExperience360.associatedTrackable) { 
        content.display(); 
        break; 
       } 
      } 
     } 

     if (methodExists(this, this.onDisplayed)) { 
      this.onDisplayed(); 
     } 
    }; 


    var instantTracker = {}; 
    scenario.trackables.push(instantTracker); 
    instantTracker.objectName = "instantTracker"; 
    instantTracker.cosName = "InstantTracker"; 
    instantTracker.cosID = "1"; 
    instantTracker.isCurrentlyTracking = false; 
    instantTracker.currentTrackingValues = null; 
    instantTracker.onTracked = function (trackingValues) { 
     arel.Debug.log(this.objectName + ".onTracked()"); 
     this.isCurrentlyTracking = true; 
     this.currentTrackingValues = trackingValues; 
    }; 

    instantTracker.onTrackingLost = function (trackingValues) { 
     arel.Debug.log(this.objectName + ".onTrackingLost()"); 
     this.isCurrentlyTracking = false; 
     this.currentTrackingValues = null; 
    }; 


    var pattern2 = {}; 
    scenario.trackables.push(pattern2); 
    pattern2.objectName = "pattern2"; 
    pattern2.cosName = "Home1_1"; 
    pattern2.cosID = "1"; 
    pattern2.isCurrentlyTracking = false; 
    pattern2.currentTrackingValues = null; 
    pattern2.onTracked = function (trackingValues) { 
     arel.Debug.log(this.objectName + ".onTracked()"); 
     this.isCurrentlyTracking = true; 
     this.currentTrackingValues = trackingValues; 
       // Try to call native from here 

     window.location = "js-call:" + "myObjectiveCFunction"; 

     model6.display(); 
     model6.play("Default Take", false); 

    }; 

    pattern2.onTrackingLost = function (trackingValues) { 
     arel.Debug.log(this.objectName + ".onTrackingLost()"); 
     this.isCurrentlyTracking = false; 
     this.currentTrackingValues = null; 
     model6.hide(); 
    }; 


    var pattern3 = {}; 
    scenario.trackables.push(pattern3); 
    pattern3.objectName = "pattern3"; 
    pattern3.cosName = "Home2_2"; 
    pattern3.cosID = "2"; 
    pattern3.isCurrentlyTracking = false; 
    pattern3.currentTrackingValues = null; 
    pattern3.onTracked = function (trackingValues) { 
     arel.Debug.log(this.objectName + ".onTracked()"); 
     this.isCurrentlyTracking = true; 
     this.currentTrackingValues = trackingValues; 
     model7.display(); 
     model7.play("Default Take", false); 
    }; 

    pattern3.onTrackingLost = function (trackingValues) { 
     arel.Debug.log(this.objectName + ".onTrackingLost()"); 
     this.isCurrentlyTracking = false; 
     this.currentTrackingValues = null; 
     model7.hide(); 
    }; 


    var userDevice = {}; 
    userDevice.isCurrentlyTracking = true; // The pose of the user's device is always tracked... 
    scenario.trackables.push(userDevice); 
    userDevice.objectName = "userDevice"; 
    userDevice.cosName = "Device"; 
    userDevice.cosID = "-1"; 
    userDevice.onTracked = function (trackingValues) { 
     arel.Debug.log(this.objectName + ".onTracked()"); 
     this.isCurrentlyTracking = true; 
     this.currentTrackingValues = trackingValues; 
    }; 

    userDevice.onTrackingLost = function (trackingValues) { 
     arel.Debug.log(this.objectName + ".onTrackingLost()"); 
     this.isCurrentlyTracking = false; 
     this.currentTrackingValues = null; 
    }; 

    // Kick-off the AR experience by calling the scenario's onStartup() method as soon as AREL is ready 
    scenario.onStartup(); 
}); 

在iOS端:UIWebview放置在视图控制器及其委托方法中以获得Javascript调用。

- (BOOL)webView:(UIWebView *)webView2 
    shouldStartLoadWithRequest:(NSURLRequest *)request 
    navigationType:(UIWebViewNavigationType)navigationType { 

     NSLog(@"Inside WebView"); 

NSString *requestString = [[request URL] absoluteString]; 

     if ([[[request URL] absoluteString] hasPrefix:@"js-call:"]) { 

      NSLog(@"Call from Javascript"); 
      return NO; 
     } 

     // Accept this location change 
     return YES; 

    } 

这里是头文件中创建的网页视图对象:

#import "MetaioSDKViewController.h" 
#import <metaioSDK/GestureHandlerIOS.h> 
#import <metaioSDK/IARELInterpreterIOS.h> 

// forward declarations 
@class EAGLView; 

@interface ARELViewController : MetaioSDKViewController<UIGestureRecognizerDelegate, IARELInterpreterIOSDelegate, UIWebViewDelegate> 
{ 
    metaio::IARELInterpreterIOS* m_ArelInterpreter; 
    GestureHandlerIOS*    m_pGestureHandlerIOS; 
    NSString*      m_arelFile; 
} 

@property (nonatomic, retain) IBOutlet UIWebView* m_arelWebView; 

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil instructions:(NSString *)arelTutorialConfig; 

- (void) onSDKReady; 

@end 

而且在.mm其设置:(注意:Interface Builder的代表也已设置)

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    m_arelWebView.delegate = self; 

} 

这当这个功能正在执行的时候,根本不会从Javascript中调用。

有人能告诉我可能是什么原因?为什么Javascript调用不会触发这个原生的webview委托。

谢谢!

+0

[Rü确保了window.location =“js-调用:“+”myObjectiveCFunction“;是真的调用?你可以在搬迁之前弹出警报吗? – gran33

+0

你确定你的UIWebView的委托是正确的对象吗? – gran33

+1

你能分享一下你创建UIWebView对象的代码吗? – Brams

回答

0

我得到了同样的问题, 我认为你已经使用了Native Bridge库:https://github.com/ochameau/NativeBridge

这个库让你实现

- (BOOL)webView:(UIWebView *)webView2 shouldStartLoadWithRequest:(NSURLRequest *)request  navigationType:(UIWebViewNavigationType)navigationType 

方法,但在MetaioCloudPluginViewController(ARELViewController的超)ü可以看到,ü需要实现:

/** Overwrite this method if you want to be able to handle custom URL schemes that are launched 
* from your channel 
* \param request the request that is being sent 
* 
* You can use it like this: 
* NSURL* theURL = [request mainDocumentURL]; 
* NSString* absoluteString = [theURL absoluteString]; 
* if([[absoluteString lowercaseString] hasPrefix:@"yourapp://"]) 
* { 
* // do something 
* return NO; 
* } 
* return YES; 
*/ 
- (BOOL) shouldStartLoadWithRequest:(NSURLRequest *) request; 

ü只需要使用

0

我认为默认的webview委托调用在最新版本中被打破。然而,什么是工作:

在javascript文件(在自己选择的位置):

arel.Media.openWebsite("appname://actionID"); 

在iOS系统:

-(bool)openWebsiteWithUrl:(NSString *)url inExternalApp:(bool)openInExternalApp 
{  
    NSLog(@"URL: %@", url); 
    if([url rangeOfString:@"actionID"].location != NSNotFound) { 
     //Got it! I can communicate with my Javascript, hooray! 
    } 
}