Version: 2019.3
Preparing your application for In-App Purchases (IAP)
App thinning

Customising WWW requests on iOS

Вы можете использовать плагин, чтобы заменить стандартный код, который Unity использует при встрече с классом WWW. Сделать это вы можете, например, чтобы изменить стандартное поведение кэша, который кэширует на основании только URL.

Пример

Следующий код (ниже описанный в деталях) отключает стандартный метод кэширования и добавляет хедер-поле “Secret” , в дополнение к хедерам, указанным из скриптового кода игры.

    // Code placed at Plugins/iOS/CustomConnection.mm within the Assets folder.

    #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];

        // let's pretend for security reasons we dont want ANY cache nor cookies
        request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
        [request setHTTPShouldHandleCookies:NO];

        // let's pretend we want special secret info in header
        [request setValue:@"123456789"forHTTPHeaderField:@"Secret"];

        return request;
    }
    @end

    @interface UnityWWWCustomConnectionDelegate : UnityWWWConnectionDelegate
    {
    }
    @end

    @implementation UnityWWWCustomConnectionDelegate
    - (NSCachedURLResponse*)connection:(NSURLConnection*)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse
    {
        // we dont want caching
        return nil;
    }
    - (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
    {
        // let's just print something here for test
        [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

“Действие” происходит в методе allocRequestForHTTPMethod, который запускается вызовом такого же метода в суперклассе:

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

Оттуда вы отключаете стандартное кэширование данных, выполняемое iOS, и также отключаете куки:

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

Next, we add a header field called “Secret” that provides some additional data. In a real game, this might be a value checked by the server to verify the source of the connection.

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

Теперь, когда у нас есть пользовательский класс для обработки запросов, нам также понадобится создать подкласс от UnityWWWConnectionDelegate, чтобы настроить обработку связи:

    @interface UnityWWWCustomConnectionDelegate : UnityWWWConnectionDelegate
    {
    }
    @end

Мы можем отключить кэширование данных вернув нулевое (nil) значение из метода connection:willCacheResponse::

    - (NSCachedURLResponse*)connection:(NSURLConnection*)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse
    {
        // we dont want caching
        return nil;
    }

Само соединение мы можем обработать из connection:didReceiveResponse:, что должно вызвать такой же метод в суперклассе, чтобы действительно получить данные. В данном случае, при установке соединения мы просто печатаем сообщение в консоль, но вы можете реализовать всё, что захотите:

    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
    {
        // let's just print something here for test
        [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);

The custom code is transparent to the use of the WWW class within Unity - no extra code needs to be added to the C# script.


  • 2018–06–14 Page amended
Preparing your application for In-App Purchases (IAP)
App thinning