AngularJS en WKWebView: ¿alguna solución para manejar el file: // en iOS 9?

Estoy portando una enorme aplicación angular JS a iOS 9 y quería beneficiarme de WKWebView (migrando desde UIWebView). La aplicación es autónoma localmente, por lo tanto, todos los files se envían al package principal de la aplicación utilizando el protocolo file: //.

Lamentablemente, suena WKWebView originalmente rompe el protocolo file: // en iOS 8.x, pero se lanzó algo de luz cuando vi la nueva API loadFileURL (basePath :, allowingReadAccessToURL 🙂 iOS 9.

let readAccessPath = NSURL(string:"app", relativeToURL:bundleURL)?.absoluteURL webView.loadFileURL(basePath!, allowingReadAccessToURL:readAccessPath!) 

Por desgracia, mientras configuro allowingReadAccessToURL en la carpeta raíz dentro de mi package (app /), solo obtuve el "file índice", no se cargan files asíncronos.

¿Alguien que tenga algo de experiencia con ese problema?

[ACTUALIZACIÓN] Veo que mi descripción inicial del problema no era lo suficientemente precisa. Tengo mi HTML en ejecución. Pero mis llamadas asíncronas angulares JS son bloqueadas por el supervisor de security en el marco de WebKit.

introduzca la descripción de la imagen aquí introduzca la descripción de la imagen aquí

Aunque no tengo una respuesta rápida (me refiero a una solución rápida), tengo una solución.

Esto implica renunciar al file: // protocolo y cambiar a http: // sobre localhost.

RESPUESTA CORTA

Estos son los pasos:

1): instale un server web local en su propia aplicación;

2): configura el server web local para que sirva desde el host local en un puerto determinado de su elección;

3): configura el delegado que realmente sirve el file de los resources de su aplicación dado el tipo de mímica correcto;

4): autorice a omitir iOS 9 ATS para manejar http (y no solo https).

Y voila!

RESPUESTA DETALLADA

1) Instale un server web local en su propia aplicación;

Instale GCDWebServer desde su repository Github: https://github.com/swisspol/GCDWebServer

2) Configura el server web local para que sirva desde localhost en un puerto determinado de su

Dado el hecho de que su angularjs o files de aplicaciones HTML están ubicados en la carpeta "aplicación" en su carpeta de resources.

En vc ViewDidLoad:

 @implementation ViewController GCDWebServer* _webServer; - (void)viewDidLoad { [super viewDidLoad]; self.webView = [[WKWebView alloc] initWithFrame:self.view.frame]; [self.view addSubview:self.webView]; self.webView.navigationDelegate = self; NSURL *bundleURL = [NSBundle mainBundle].bundleURL; NSURL *basePath = nil; // Init WebServer [self initWebServer:[[NSURL URLWithString:@"app" relativeToURL:bundleURL] absoluteURL]]; basePath = [NSURL URLWithString:@"http://localhost:8080/page.html#/home" relativeToURL:nil]; NSURLRequest *request = [[NSURLRequest alloc] initWithURL:basePath]; [self.webView loadRequest:request]; } 

3) Configura el delegado que de hecho sirve el file de los resources de su aplicación dado el tipo correcto de mímica;

 -(void)initWebServer:(NSURL *)basePath { // Create server _webServer = [[GCDWebServer alloc] init]; #define GCDWebServer_DEBUG 0 #define GCDWebServer_VERBOSE 1 #define GCDWebServer_INFO 2 #define GCDWebServer_WARNING 3 #define GCDWebServer_ERROR 4 #define GCDWebServer_EXCEPTION 5 [GCDWebServer setLogLevel:GCDWebServer_ERROR]; // Add a handler to respond to GET requests on any URL [_webServer addDefaultHandlerForMethod:@"GET" requestClass:[GCDWebServerRequest class] processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) { //NSLog([NSString stringWithFormat:@"WS: loading %@", request]); NSString * page = request.URL.lastPathComponent; NSString * path = request.URL.path; NSString * file = path; //NSLog(@"WS: loading %@", file); NSString * fullPath = [NSString stringWithFormat:@"%@%@", basePath, path]; NSString * sFullPath = [fullPath substringFromIndex:7]; BOOL isText = NO; if([page.lastPathComponent hasSuffix:@"html"]) { isText = YES; } if (isText) { NSError * error = nil; NSString * html = [NSString stringWithContentsOfFile:sFullPath encoding:NSUTF8StringEncoding error: &error]; return [GCDWebServerDataResponse responseWithHTML:html]; } else { NSData * data = [NSData dataWithContentsOfFile:sFullPath]; if (data !=nil) { NSString * type = @"image/jpeg"; if ([page.lastPathComponent hasSuffix:@"jpg"]) type = @"image/jpeg"; else if ([page.lastPathComponent hasSuffix:@"png"]) type = @"image/png"; else if ([page.lastPathComponent hasSuffix:@"css"]) type = @"text/css"; else if ([page.lastPathComponent hasSuffix:@"js" ]) type = @"text/javascript"; return [GCDWebServerDataResponse responseWithData:data contentType:type]; } else { return [GCDWebServerDataResponse responseWithHTML:[NSString stringWithFormat:@"<html><body><p>404 : unknown file %@ World</p></body></html>", sFullPath]]; //return [GCDWebServerDataResponse responseWithHTML:@"<html><body><p>Hello World</p></body></html>"]; } } }]; // Start server on port 8080 [_webServer startWithPort:8080 bonjourName:nil]; NSLog(@"Visiting %@", _webServer.serverURL); } 

4) Autorizar para omitir iOS 9 ATS para manejar http (y no solo https)

En su file info.plist en Xcode, debe agregar un dictionary llamado "Configuración de security de transporte de aplicaciones" con un valor key como sigue:

NSAllowsArbitraryLoads = true

Espero eso ayude. ¡Cualquier persona que tropiece con algo más simple puede responder!

Como puedo decir, estás haciendo aplicaciones mobilees y comstackndolas después … Tuve un problema bastante similar. Pero para mí, la compilation final fue hecha por adobe build.phonegap service. Y ahí lo único que tuve que hacer es agregar cordova-whitelist-plugin en config.xml como este

 < gap:plugin name="cordova-plugin-whitelist" source="npm" version="1.0.0" /> 

Y que agregar permiso para acceder a dichos enlaces

 <allow-intent href="file:///*/*" /> 

también en config.xml

Lo siento, si te entendí mal.

Usar GCDWebServer es lo que recomendaría, puede ejecutar un server web local como http://localhost .

Swift 3.0

  1. Agregue el pod de pod "GCDWebServer", "~> 3.0"

  2. Haga clic y arrastre su carpeta web AngularJS en Xcode y, cuando se le solicite, select 'Copiar elementos si es necesario' y 'Crear references de carpeta'

  3. Use este código en su controller para ejecutar un server web localhost

     class MainViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler, WKUIDelegate, GIDSignInUIDelegate { var webView : WKWebView! var webServer:GCDWebServer? override func viewDidLoad() { super.viewDidLoad() self.webView.load(URLRequest(url: loadDefaultIndexFile()!)) } private func loadDefaultIndexFile() -> URL? { self.webServer = GCDWebServer() let mainBundle = Bundle.main // The path to my index.html is www/index.html. If using a default public folder then it could be public/index.html let folderPath = mainBundle.path(forResource: "www", ofType: nil) self.webServer?.addGETHandler(forBasePath: "/", directoryPath: folderPath!, indexFilename: "index.html", cacheAge: 0, allowRangeRequests: true) do { try self.webServer?.start(options: [ "Port": 3000, "BindToLocalhost": true ]); }catch{ print(error) } // Path should be http://localhost:3000/index.html return self.webServer?.serverURL } }