Version: 2019.3
准备应用程序进行应用内购 (IAP)
应用程序精简

自定义 iOS 上的 WWW 请求

可以使用插件替换 Unity 在处理 WWW 类请求时使用的默认代码。例如,通过这种方式可以更改默认缓存行为(默认情况下仅基于 URL 进行缓存)。

示例

以下代码(在下面有更详细的描述)禁用默认缓存方法,并且除了从游戏的脚本代码指定的标头之外,还向请求添加“secret”标头字段。

    // 代码放置于 Assets 文件夹中的 Plugins/iOS/CustomConnection.mm 位置。

        #include "Unity/WWWConnection.h"

        @interface UnityWWWCustomRequestProvider : UnityWWWRequestDefaultProvider
        {
        }
        + (NSMutableURLRequest*)allocRequestForHTTPMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers;
        @end

        @implementation UnityWWWCustomRequestProvider
        + (NSMutableURLRequest*)allocRequestForHTTPMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers
        {
            NSMutableURLRequest* request = [super allocRequestForHTTPMethod:method url:url headers:headers];

            // 假设我们出于安全原因不希望有任何缓存和 Cookie
            request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
            [request setHTTPShouldHandleCookies:NO];

            // 假设我们希望标头中包含特殊秘密信息
            [request setValue:@"123456789"forHTTPHeaderField:@"Secret"];

            return request;
        }
        @end

        @interface UnityWWWCustomConnectionDelegate : UnityWWWConnectionDelegate
        {
        }
        @end

        @implementation UnityWWWCustomConnectionDelegate
        - (NSCachedURLResponse*)connection:(NSURLConnection*)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse
        {
            // 我们不希望缓存
            return nil;
        }
        - (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
        {
            // 我们仅在此处输出一些信息进行测试
            [super connection:connection didReceiveResponse:response];
            if([response isMemberOfClass:[NSHTTPURLResponse class]])
                ::printf_console("We've got response with status: %d\n", [(NSHTTPURLResponse*)response statusCode]);
        }
        @end

        IMPL_WWW_DELEGATE_SUBCLASS(UnityWWWCustomConnectionDelegate);
        IMPL_WWW_REQUEST_PROVIDER(UnityWWWCustomRequestProvider);

代码细分如下。首先,我们创建 UnityWWWRequestDefaultProvider 的子类,从而提供已修改的 NSURLRequest 对象以进行连接。另一个选择就是从头开始在类中实现 UnityWWWRequestProvider 协议。但是,在这种情况下,我们希望使用 Unity 的现有代码。

    @interface UnityWWWCustomRequestProvider : UnityWWWRequestDefaultProvider
        {
        }
        + (NSMutableURLRequest*)allocRequestForHTTPMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers;
        @end

“action”发生在 allocRequestForHTTPMethod 中,这是通过调用超类上的同一方法启动的:

    @implementation UnityWWWCustomRequestProvider
        + (NSMutableURLRequest*)allocRequestForHTTPMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers
        {
            NSMutableURLRequest* request = [super allocRequestForHTTPMethod:method url:url headers:headers];

在此处,我们禁用 iOS 完成的默认数据缓存,并禁用 Cookie:

    request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
        [request setHTTPShouldHandleCookies:NO];

接下来,我们添加一个名为“Secret”的标头字段来提供一些额外数据。在真实游戏中,这可能是由服务器检查以验证连接源的值。

    [request setValue:@"123456789"forHTTPHeaderField:@"Secret"];

创建了自定义请求处理类之后,我们还需要创建 UnityWWWConnectionDelegate 的子类来自定义连接的处理:

    @interface UnityWWWCustomConnectionDelegate : UnityWWWConnectionDelegate
        {
        }
        @end

我们可以通过从 connection:willCacheResponse: 方法返回一个 nil 值来禁用数据缓存:

    - (NSCachedURLResponse*)connection:(NSURLConnection*)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse
        {
            // 我们不希望缓存
            return nil;
        }

我们可以从 connection:didReceiveResponse: 处理连接本身,它应该调用超类上的同一方法来实际获取数据。在此处,我们只是在进行连接时向控制台输出一条消息,但您可以在此处实现所需的任何东西:

    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
        {
            // 我们仅在此处输出一些信息进行测试
            [super connection:connection didReceiveResponse:response];
            if([response isMemberOfClass:[NSHTTPURLResponse class]])
                ::printf_console("We've got response with status: %d\n", [(NSHTTPURLResponse*)response statusCode]);
        }

最后,我们向 Unity 注册新的连接委托和请求提供程序,以便在从脚本发出 WWW 请求时调用它们:

    IMPL_WWW_DELEGATE_SUBCLASS(UnityWWWCustomConnectionDelegate);
        IMPL_WWW_REQUEST_PROVIDER(UnityWWWCustomRequestProvider);

自定义代码对于在 Unity 中使用 WWW 类而言是透明的:不需要在 C# 脚本中添加额外的代码。


  • 2018–06–14 页面已修订
准备应用程序进行应用内购 (IAP)
应用程序精简