блокировать рекламу с URL, загруженного в WKWebView - PullRequest
0 голосов
/ 24 мая 2018

Я загружаю URL в webView, и теперь я хочу заблокировать рекламу из URL в webView.Как мне этого добиться?

[_webVw loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:page_url]]];

Ответы [ 2 ]

0 голосов
/ 10 июля 2018

Если вы не возражаете против показа рекламы на iOS 10 или более ранней версии, то iOS 11 и более поздние версии включают правила блокировки содержимого.

Обзор

Предположим, у меня есть подкласс UIViewController, которыйимеет свойство webView, указывающее на мой экземпляр WKWebView.Я реализую пользовательский метод с именем goHome, который посещает определенный домашний URL.Прежде чем я сделаю это, я, возможно, захочу загрузить правила блокировки контента в свое веб-представление.Я начинаю с чего-то вроде этого:

- ( void ) viewDidLoad
{
    [ super viewDidLoad ];

    // (other setup stuff here...)

    [ self reloadContentBlockingRulesAndGoHome ];
}

Материал 'reload blocking rules' загружает правила, если я на iOS 11 или новее.Если вам нужна поддержка других версий iOS, см. Другие ответы.Простите за странности расположения пробелов, у меня есть причудливый стиль кодирования, когда дело доходит до сообщений Objective C, которые включают блоки в параметрах:

- ( void ) reloadContentBlockingRulesAndGoHome
{
    if ( @available( iOS 11, * ) )
    {
        [
            WKContentRuleListStore.defaultStore
                compileContentRuleListForIdentifier: @"ContentBlockingRules"
                             encodedContentRuleList: @"...see below!..."
                                  completionHandler: ^ ( WKContentRuleList * ruleList, NSError * error )
            {
                [ super viewDidLoad ];

                if ( error == nil )
                {
                    [ self.webView.configuration.userContentController addContentRuleList: ruleList ];
                    [ self goHome ];
                }
            }
        ];
    }
    else
    {
        [ self goHome ];
    }
}

Этот параметр encodedContentRuleList принимает строку JSON.Я склонен помещать это в свой собственный метод для ясности, поэтому приведенный выше код может на самом деле сказать:

[ WKContentRuleListStore.defaultStore
     compileContentRuleListForIdentifier: @"ContentBlockingRules"
                  encodedContentRuleList: [ self contentBlockingRules ]
                       completionHandler: ^ ( WKContentRuleList * ruleList, NSError * error ) { ... } ];

Так что бы [ self contentBlockingRules ] сделал?Это просто возвращает строку NSString, дающую данные о блокировке контента.Без интеграции с какой-либо сторонней службой блокировки рекламы все, что вы можете сделать, - это проверить отдельные страницы, представляющие интерес, и начать замечать общие имена классов или идентификаторы элементов HTML, которые содержат рекламу, плюс уведомление (например, на вкладке «Сеть» веб-инспектора Safari).) все домены, с которых вытащен рекламный материал.Это осветительный, хотя и несколько удручающий процесс, когда вы понимаете, что , сколько рекламных материалов включено на типичном веб-сайте сейчас.

Правила JSON, пример

Внимательно прочтите это:

Вот пример, который включает в себя некоторые элементы CSS-селектора, блокирующие определенный URL-адрес с самого сервера (например, некоторый пользовательский рекламный код, которым они могут быть), плюс некоторые правила для обобщенных сторонних доменов, которые вы хотите заблокировать (я часто их использую).

- ( NSString * ) contentBlockingRules
{
    return @" \
    [ \
      { \
        \"trigger\": { \
          \"url-filter\": \".*\" \
        }, \
        \"action\": { \
          \"type\": \"css-display-none\", \
          \"selector\": \".some_css_class, .some_other_class, #some_css_id\" \
        } \
      }, \
      { \
        \"trigger\": { \
          \"url-filter\": \"\\/some\\/very-specific-filename\\\\.js\", \
          \"resource-type\": [ \"script\" ] \
        }, \
        \"url-filter-is-case-sensitive\": true, \
        \"action\": { \
          \"type\": \"block\" \
        } \
      }, \
      { \
        \"trigger\": { \
          \"url-filter\": \".*\", \
          \"if-domain\": [ \"doubleclick.net\", \"adservice.google.com\", \"etc\" ], \
          \"resource-type\": [ \"script\" ] \
        }, \
        \"action\": { \
          \"type\": \"block\" \
        } \
      } \
    ]";
}

Нелегко брать JSON и кодировать его в NSString - как вы можете видеть,В результате получилось очень много экранирования, особенно для некоторых частей URL, которые экранируются один раз для JSON, а затем снова экранируются для литерала NSString.Вероятно, есть более чистые способы сделать это, которые значительно упростят обслуживание данных JSON.

Заключительные мысли

Из-за большого количества рекламных и отслеживающих кодов на многих сайтах разница в страницеСкорость загрузки, когда вы блокируете вещи, может быть драматичной.Это стоит усилий, чтобы дать вашим пользователям лучший опыт и меньше использовать их мобильные данные, НО:

  • Возможно, вы нарушаете условия обслуживания на посещаемых вами сайтах
  • Еслисайты обновляют свой код, после чего вы можете пропустить некоторые объявления, которые вы намеревались заблокировать
  • Существует несколько более высокий риск того, что обновление сайта или слишком общее правило блокировки могут случайно скрыть "законный" нерекламный контент страницы.

Вместо того, чтобы просто копировать и вставлять что-либо из вышеперечисленного, вместо этого внимательно прочитайте документацию Apple для разработчиков по различным методам и методам фреймворка, приведенным выше, чтобы вы понимали ограничения, требования к обработке ошибок и так далее.Приведенные выше примеры предназначены только для того, чтобы вы начали знакомство с концепциями, но важно писать реальный код с позиции полного понимания того, что вы делаете, - пользователи вашего приложения заслуживают стабильного опыта: -)

0 голосов
/ 24 мая 2018

Вам необходимо использовать webView: shouldStartLoadWithRequest: navigationType: метод из UIWebViewDelegate и выполнить проверку с помощью черного списка URL-адресов для блокировки.Если вы хотите вдохновение или подобный процесс, вы можете увидеть эту библиотеку Блокатор рекламы iOS

--- EDIT ---

Это мой код блокировки рекламы WKWebView отNSString.

//
//  ViewController.m
//  WKWebView
//
//  Created by Carlos Landaverde on 6/21/18.
//

#import "ViewController.h"

#define NSStringMultiline(...) [[NSString alloc] initWithCString:#__VA_ARGS__ encoding:NSUTF8StringEncoding]

static NSString *rexKey1 = @"rexKey1";

@interface ViewController () <WKNavigationDelegate, WKUIDelegate>
@property (nonatomic) WKWebView *webView;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.view setBackgroundColor: [UIColor whiteColor]];

    dispatch_group_t dispatchGroup = dispatch_group_create();
    __weak typeof(self) weakSelf = self;

    [NSUserDefaults.standardUserDefaults registerDefaults: @{ rexKey1: @NO }];
    [NSUserDefaults.standardUserDefaults synchronize];

    _webView = [[WKWebView alloc] initWithFrame: self.view.bounds];
    [_webView setNavigationDelegate: self];
    [_webView setUIDelegate: self];
    [_webView setAllowsBackForwardNavigationGestures: YES];
    [self.view addSubview: _webView];

    // If you want to remove previous WKContentRuleList
    // [_webView.configuration.userContentController removeAllContentRuleLists];

    dispatch_group_enter(dispatchGroup);
    [self setupContentBlockFromStringLiteral: ^{
        dispatch_group_leave(dispatchGroup);
    }];

    dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{
        [weakSelf beginLoading];
    });
}

- (void)beginLoading
{
    NSURLRequest *urlReq = [[NSURLRequest alloc] initWithURL: [NSURL URLWithString: @"https://www.google.com"]];
    [_webView loadRequest: urlReq];
}

- (void)setupContentBlockFromStringLiteral: (void (^)(void))callback
{
    /*
     Or you can block from a JSON file
     */
    NSString *jsonStr = NSStringMultiline([{
        "trigger": {
            "url-filter": "://googleads\\\\.g\\\\.doubleclick\\\\.net.*"
        },
        "action": {
            "type": "block"
        }
    }]);

    if ([[NSUserDefaults.standardUserDefaults objectForKey: rexKey1] boolValue]) {
        [WKContentRuleListStore.defaultStore compileContentRuleListForIdentifier: rexKey1 encodedContentRuleList: jsonStr completionHandler: ^(WKContentRuleList *contentRuleList, NSError *err) {

            if (err != nil) {
                NSLog(@"Error on content rule list compiled");
                [NSUserDefaults.standardUserDefaults setObject: @NO forKey: rexKey1];
                return;
            }

            if (contentRuleList) {
                [_webView.configuration.userContentController addContentRuleList: contentRuleList];
                callback();
            }
        }];
    }
    else {
        [WKContentRuleListStore.defaultStore compileContentRuleListForIdentifier: rexKey1 encodedContentRuleList: jsonStr completionHandler: ^(WKContentRuleList *contentRuleList, NSError *err) {

            if (err != nil) {
                NSLog(@"Error on content rule list not compiled");
            }

            if (contentRuleList) {
                [_webView.configuration.userContentController addContentRuleList: contentRuleList];
                [NSUserDefaults.standardUserDefaults setObject: @YES forKey: rexKey1];
                callback();
            }
        }];
    }
}

@end
...