在TVML应用程序

时间:2015-11-13 21:14:45

标签: tvos apple-tv tvjs

我正在使用TVMLKit开发Apple TV应用。我的应用程序的JavaScript代码尝试使用XMLHttpRequest向服务器发送HTTP请求。服务器期待特定的用户代理,所以我尝试了这个:

var request = new XMLHttpRequest();
request.open("GET", url, true);
request.setRequestHeader("User-Agent", "MyApp");
request.send();

服务器接收不同的User-Agent标头:

User-Agent: <Projectname>/1 CFNetwork/758.1.6 Darwin/15.0.0

如果我将标题名称更改为其他名称,则会在请求标题中显示。我猜Apple正在发送请求之前正在替换User-Agent字段。有办法防止这种情况吗?

1 个答案:

答案 0 :(得分:0)

在花了两天时间调查这个问题后,我开始尝试在swift端创建原生的GETPOST方法,将它们暴露给javascript。这不是最佳解决方案,但我仍想分享它。也许它可以帮助别人。

这是如何运作的

首先我们需要安装Alamofire库。我们将使用它来创建请求。

  

github上的自述文件包含安装它所需的所有说明

安装Alamofire后,我们需要在AppDelegate.swift

中导入它
import Alamofire

然后我们需要在app控制器(AppDelegate.swift)中创建将j方法公开的函数

func appController(appController: TVApplicationController, evaluateAppJavaScriptInContext jsContext: JSContext)
{
    let requests = [String : AnyObject]()

    let get: @convention(block) (String, String, [String : String]?) -> Void = { (cId:String, url:String, headers:[String : String]?) in

        Alamofire.request(.GET, url, headers: headers)
            .responseString { response in
                jsContext.evaluateScript("requests." + cId + "(" + response.result.value! + ")")
        }
    }

    let post: @convention(block) (String, String, [String : AnyObject]?, [String : String]?) -> Void = { (cId:String, url:String, parameters:[String : AnyObject]?, headers:[String : String]?) in

        Alamofire.request(.POST, url, parameters: parameters, headers: headers)
            .responseString { response in
                jsContext.evaluateScript("requests." + cId + "(" + response.result.value! + ")")
        }
    }

    jsContext.setObject(requests, forKeyedSubscript: "requests");
    jsContext.setObject(unsafeBitCast(get, AnyObject.self), forKeyedSubscript: "nativeGET");
    jsContext.setObject(unsafeBitCast(post, AnyObject.self), forKeyedSubscript: "nativePOST");
}
  

AppDelegate.swift的完整代码,您可以找到here

全套!现在,我们可以通过javascript访问nativeGETnativePOST个函数。

最后一件事是提出请求并检索回复。我不明白如何在swift中执行回调执行,因此我使用jsonp方法使用运行时生成的函数并将其名称传递给本机函数。

以下是javascript中的内容

export function get(url, headers = {}) {
    return new Promise((resolve) => {
        const cId = `get${Date.now()}`;
        requests[cId] = response => {
            delete requests[cId];
            resolve(response);
        }
        nativeGET(cId, url, headers);
    });
}

export function post(url, parameters = {}, headers = {}) {
    return new Promise((resolve) => {
        const cId = `post${Date.now()}`;
        requests[cId] = response => {
            delete requests[cId];
            resolve(response);
        }
        nativePOST(cId, url, parameters, headers);
    });
}
  

上面的代码是用ES6编写的,您需要在TVJS应用中加入Promise polifill。

现在,我们可以GETPOST请求应用我们需要的任何标头

post('http://example.com/', {
    login: 'xxx', 
    password: 'yyy'
}, {
    'User-Agent': 'My custom User-Agent'
})