<
  • Главная
Статьи

Використання NSURLProtocol в Swift

  1. початок
  2. Огляд вихідного проекту
  3. Перехоплення мережевих запитів
  4. Призначена для користувача завантаження URL
  5. Розрив нескінченного циклу запитів
  6. Реалізація локального кеша
  7. замітка:
  8. Отримання закеширувалася відповіді
  9. Коли потрібно використовувати NSURLProtocol?
  10. Забезпечення індивідуальних відповідей для мережевих запитів:
  11. Пропустити активність мережі і надати локальні дані:
  12. Перенаправлення мережевих запитів:
  13. Зміна user-agent вашого запиту:
  14. Використовуйте свій власний мережевий протокол:

NSURLProtocol - це як чарівний ключ до URL. Він дозволяє визначити, як працює система завантаження URL у Apple, визначаючи схеми для користувача URL і повторно перевизначаючи поведінку існуючих схем URL.

Звучить як диво? Так і повинно бути, тому що URL немов любов, яка всюди навколо нас. Що використовують UIWebView і WKWebView? Звичайно ж URL. Що використовується для потокового відео в MPMoviePlayer? І знову URL. Як ви відправляєте когось на iTunes за вашим додатком, входите в FaceTime або Skype, завантажуєте додаток в систему, або навіть вставляєте зображення в HTML файл? І знову з URL. Погляньте на NSFileManager і зверніть увагу, як багато з його методів, які працюють з файлами, вимагають і повертають URL!

У цьому туторіали по NSURLProtocol ви дізнаєтеся, як визначити обробника протоколу, який змінює схеми URL. При цьому він додає грубий і готовий прозорий шар кешування, зберігаючи витягнуті дані в Core Data. При його включенні звичайний UIWebView може взяти на себе роль браузера і ре завантажених сторінок для можливості перегляду їх в офлайні пізніше.

Перш ніж заглибитися з головою в тему, вам знадобиться базове розуміння мережевих концепцій і знайомство з тим, як працює NSURLConnection.

Отже, ви готові почати вивчення можливостей NSURLProtocol? Добре, влаштовуйтеся зручніше з чашкою чаю і почнемо розширює свідомість обговорення і покрокові вправи.

початок

Для проекту цього Тутор, ви створите елементарний мобільний веб-браузер, такий, який ви могли б додати до вашого такого додатка. Він буде мати базовий інтерфейс користувача, який дозволить йому увійти і перейти до URL. Але ваш браузер зможе успішно кешувати отримані результати. Тому користувач зможе завантажувати сторінки, які він відвідав раніше, в одну мить, адже стаття не буде завантажуватися з мережевого запиту, а тільки з локального кеша додатки.

Ви вже знаєте, що швидке завантаження сторінки == щасливі користувачі, так що це хороший приклад того, як можна поліпшити NSURLProtocol для успішної роботи вашого додатка.

Кроки, через які ви пройдете:

  1. використання UIWebView для відображення веб-сайтів;
  2. використання Core Data для кешування результатів.

Якщо ви не знайомі з Core Data, то можете заглянути в підручник. Однак, коду в цьому уроці повинно бути достатньо для того, щоб зрозуміти можливості NSURLProtocol. Використання Core Data є простим способом реалізації локального кеша, так що на цьому етапі вам цього буде достатньо.

Огляд вихідного проекту

Ви можете скачати вихідний проект тут (архів) . Як тільки завантаження буде завершена, розпакуйте файл і відкрийте проект.

Коли ви відкриєте проект, то побачите два основних файлу. Перший файл - Main.storyboard. Він має стандартний UIViewController, якраз такий, який вам потрібен для реалізації. Зверніть увагу на UITextField (для введення URL), UIButton (для виклику веб-запитів) і UIWebView.

Відкрийте BrowserViewController.swift. Тут ви побачите основне поведінку, встановлене для UI компонентів. UIViewController реалізує протокол UITextFieldDelegate так, що ви можете відправляти запит, коли користувач натискає кнопку повернення. IBAction для кнопки попередньо встановлений на таку ж поведінку, як і клавіші повернення. Метод sendRequest () бере текст з текстового поля, створює об'єкт NSURLRequest і викликає метод loadRequest (_ :) з UIWebView для завантаження.

Після того, як ви ознайомитеся з додатком, запустіть його! Коли воно відкриється, введіть " http://swiftbook.ru "І натисніть кнопку" Go ". UIWebView завантажить відповідь і відобразить результат в додатку - досить просто для початку, правда? Прийшов час розім'яти м'язи на пальцях, приступаємо до коду!

Перехоплення мережевих запитів

Набір класів, відомих як URL Loading System (система завантаження URL), обробляє запити URL на iOS. У центрі системи завантаження URL знаходиться NSURL клас. Для мережевих запитів цей клас говорить, який саме хост (host) намагається досягти вашого застосування і вказує шлях до ресурсу на цьому хості. Крім того, об'єкт NSURLRequest додає таку інформацію, як: HTTP заголовки, тіло вашого повідомлення і т.д .. Система завантаження забезпечує кілька різних класів, які ви можете використовувати, щоб обробити запит, найбільш поширеними з яких є NSURLConnection і NSURLSession.

Тепер прийшов час, щоб почати перехоплення всіх NSURLRequest, відправлених з програми. Для цього вам потрібно створити свою власну реалізацію NSURLProtocol.

Натисніть File \ New \ File .... Виберете iOS \ Source \ Cocoa Touch Class і потім натисніть кнопку Next. В поле Class введіть MyURLProtocol, а в поле Subclass of введіть NSURLProtocol. Переконайтеся, що вибрана мова -Swift. Потім, натисніть Next і Create, коли з'явиться діалогове вікно.

Відкрийте MyURLProtocol.swift і замініть його вміст на наступне:

import UIKit var requestCount = 0 class MyURLProtocol: NSURLProtocol {override class func canInitWithRequest (request: NSURLRequest) -> Bool {print ( "Request # \ (requestCount ++): URL = \ (request.URL! .absoluteString)") return false} }

Кожен раз, коли система завантаження URL отримує запит, що потрібно завантажити URL, вона шукає зареєстрованого обробника протоколу для обробки запиту. Кожен обробник повідомляє системі, чи може він впоратися з даними запитом за допомогою canInitWithRequest (_ :).

Параметром цього методу є запит, а сам він звучить, як питання протоколу: чи зможе той обробити передається запит? Якщо метод повертає true, то завантаження системи буде спиратися на цей підклас NSURLProtocol для обробки запиту і ігнорувати всіх інших обробників.

Якщо жоден з призначених для користувача зареєстрованих обробників не зрозумiв запит, то система завантаження URL буде обробляти його сама, використовуючи поведінку системи за умовчанням.

Якщо ви хочете реалізувати новий протокол, такий як foo: //, то це те місце, яке потрібно перевірити, щоб побачити, чи є запитана схема URL foo. Але в наведеному вище прикладі ви просто повертаєте false, що говорить вам про те, що ваш додаток не зрозумiв запит. Просто почекайте хвилину і ви почнете їх обробляти найближчим часом!

Відкрийте AppDelegate.swift і замініть application (_: didFinishLaunchingWithOptions :) наступним:

func application (application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {NSURLProtocol .registerClass (MyURLProtocol) return true}

Тепер, коли ваш додаток запущено, воно буде реєструвати протокол з системою завантаження URL. Це означає, що він буде мати можливість обробляти кожен запит, доставлений системі завантаження URL. Сюди ми включаємо код, який викликає систему завантаження безпосередньо, а також багато компонентів системи, які покладаються на завантажувальні фреймворки URL, такі як UIWebView.

Запустіть проект. вставте http://swiftbook.ru як веб-сайт, натисніть на Go і перевірте консоль Xcode. Тепер на кожен запит додатки, який необхідно виконати, система завантаження URL запитує клас, якщо вона може обробити його. В консолі ви повинні побачити щось на зразок цього:

В даний час ваш клас тільки записує строкове відображення URL запиту і повертає false. Це означає, що ваш користувальницький клас не зрозумiв запит. Але якщо ви подивитеся в логах, то побачите всі запити з UIWebView. Сюди включені і головний сайт (.html), і все Ессет (набори), такі як зображення у форматі JPEG і CSS файли. Кожен раз, коли UIWebView потрібно відправити запит, він відображається в консолі, перш ніж спрацювати. Запитів буде ціла купа - понад п'ятсот - через різних наборів (Ессет) на веб-сторінці.

Отже, ваш користувальницький клас оголошується для кожного запиту URL, а в подальшому ви зможете вже зробити щось в кожному запиті!

Призначена для користувача завантаження URL

"Я люблю, коли сторінки завантажуються вічно" - ніхто так не скаже! Ніколи! Тепер ви повинні переконатися, що ваш додаток дійсно може обробляти запити. Як тільки true повертається в canInitWithRequest (_ :), на ваш клас переходить відповідальність щодо обробки запиту. Це означає, що ви повинні отримати запитані дані і надати їх назад в систему завантаження URL.

Як ви отримуєте дані?

Якщо ви реалізуєте новий мережевий протокол додатки з нуля (наприклад, додавання foo: // протоколу), то ви пізнаєте суворі радості реалізації мережевого протоколу додатки. Але так як наша мета просто вставити призначений для користувача шар кешування, то ви можете просто отримати дані за допомогою NSURLConnection.

Фактично ви тільки збираєтесь перехопити запит і потім передати його назад стандартній системі завантаження URL через використання NSURLConnection.

Ваш користувальницький підклас NSURLProtocol повертає дані через об'єкт, який реалізує протокол NSURLProtocolClient. Назва трохи збиває з пантелику: NSURLProtocol - це клас, а NSURLProtocolClient - протокол!

Через клієнта ви спілкуєтеся з системою завантаження URL для зворотної передачі основних змін, відповідей і даних.

Відкрийте MyURLProtocol.swift і додайте наступне властивість у верхній частині визначення класу MyURLProtocol:

var connection: NSURLConnection!

Потім знайдіть canInitWithRequest (_ :). Змініть рядок повернення на true:

return true

Додайте ще чотири методи:

override class func canonicalRequestForRequest (request: NSURLRequest) -> NSURLRequest {return request} override class func requestIsCacheEquivalent (aRequest: NSURLRequest, toRequest bRequest: NSURLRequest) -> Bool {return super .requestIsCacheEquivalent (aRequest, toRequest: bRequest)} override func startLoading ( ) {self .connection = NSURLConnection (request: self .request, delegate: self)} override func stopLoading () {if self .connection! = nil {self .connection.cancel ()} self .connection = nil}

Вашій належить визначати, що означає «канонічний запит» (взятий за зразок) і, як мінімум, він повинен повернути такий же канонічний запит для таких же вхідних запитів. Таким чином, якщо в цьому методі вводяться семантично рівні (тобто не обов'язково ===) запити, то вихідні запити повинні бути теж семантично рівні. Наприклад, якщо ваша призначена для користувача схема URL чутлива до регістру, то ви можете вирішити, що все канонічні URL будуть написані в рядковому регістрі.

Для досягнення абсолютного мінімуму просто поверніть сам запит. Як правило, це є надійним шляхом вирішення, тому що ви, як правило, не хочете міняти запит. Зрештою, ви ж довіряєте розробнику, правильно ?! Прикладом вашої роботи тут, буде заміна запиту з додаванням заголовка і повернення нового запиту.

requestIsCacheEquivalent (_: toRequest :) - місце, де ви можете визначити, коли два окремих запиту користувача схеми URL (тобто foo: //) рівні, з точки зору здатності можливості кешування. Якщо два запити рівні, то вони повинні використовувати одні і ті ж дані кеша. Це стосується і самої системи завантаження URL і вбудованої системи кешування, яку ми не розглядаємо в цьому туторіали. Таким чином, для даної вправи ви просто покладаєтеся на реалізацію за замовчуванням суперкласу.

Система завантаження використовує startLoading () і stopLoading () для того, щоб сказати NSURLProtocol, і почати або зупинити обробку запиту. Ваша початкова реалізація налаштовує NSURLConnection для завантаження даних. Існує метод зупинки, так що URL завантаження може бути скасована. У наведеному вище прикладі якраз відбувається така обробка, скасовуючи поточне з'єднання і позбавляючись від нього.

Ю-ху! Ви реалізували інтерфейс, необхідний для діючого екземпляра NSURLProtocol.

Але ваш код ще не готовий! Ви все ще повинні попрацювати з обробкою запиту, що ви і зробите, обробляючи зворотний зв'язок від делегата NSURLConnection, створеного вами.

Відкрийте MyURLProtocol.swift і додайте наступні методи:

func connection (connection: NSURLConnection !, didReceiveResponse response: NSURLResponse!) {self .client !. URLProtocol (self, didReceiveResponse: response, cacheStoragePolicy:. NotAllowed)} func connection (connection: NSURLConnection !, didReceiveData data: NSData!) {Self .client !. URLProtocol (self, didLoadData: data)} func connectionDidFinishLoading (connection: NSURLConnection!) {Self .client !. URLProtocolDidFinishLoading (self)} func connection (connection: NSURLConnection !, didFailWithError error: NSError!) {Self .client !. URLProtocol (self, didFailWithError: error)}

Всі методи делегата NSURLConnection викликаються тоді, коли екземпляр NSURLConnection, який ви використовуєте для завантаження даних, отримує відповідь (це відбувається тоді, коли у нього є дані щодо закінчення завантаження і падіння). У кожному з випадків вам необхідно передати цю інформацію клієнту.

Таким чином, обробник MyURLProtocol створює своє власне підключення NSURLConnection і запитує його продовжити запит. У відповідь методах делегата NSURLConnection, описаних вище, обробник протоколу ретранслює повідомлення від з'єднання назад, до системи завантаження URL. Ці повідомлення говорять про прогрес завантаження, про завершення операції та про помилки.

Подивіться і ви побачите схожість в сигнатури повідомлень NSURLConnectionDelegate і NSURLProtocolClient - обидва вони використовують API для асинхронної завантаження даних. Також зверніть увагу, як MyURLProtocol використовує властивість client для відправки повідомлень назад в систему завантаження URL.

Запустіть проект. Коли додаток відкриється, введіть той же URL і натисніть "Go".

Ой ой! Ваш браузер більше нічого не завантажує!

Якщо ви подивіться в панель дебаггера, то побачите, як росте число запитів одного і того ж URL. Що ж не так?

Що ж не так

Спочатку поверніться в Xcode і зупиніть симулятор, поки у вас не почалися серйозніші проблеми.

Розрив нескінченного циклу запитів

Подумайте знову про систему завантаження URL і реєстрації протоколу, може бути у вас з'явиться здогади, чому так відбувається. Коли UIWebView хоче завантажити URL, система завантаження URL запитує MyURLProtocol чи зможе він обробити цей запит, і ваш клас відповідає true - так, він може його обробити.

Таким чином система завантаження URL створює екземпляр вашого протоколу та викликає startLoading. Потім ваша реалізація створює і запускає свій NSURLConnection. Але крім цього вона також викликає систему завантаження URL. Так як ваш метод canInitWithRequest (_ :) повертає true, то він створює новий екземпляр MyURLProtocol.

Очевидно, що ви не можете завжди повертати true в методі canInitWithRequest (_ :). Вам потрібен свого роду контроль для того, щоб ви могли сказати системі завантаження URL, щоб вона обробляла запит одного разу. Рішення криється в інтерфейсі NSURLProtocol. Пошукайте метод класу setProperty (_: forKey: inRequest :), який дозволяє додавати додаткові властивості в зазначений URL. В цьому випадку ви зможете встановити «ярлик», прикріпивши до запиту це властивість, таким чином браузер зрозуміє, зустрічав він цей запит раніше чи ні.

Ось приклад того, як ви можете витягнути ваш браузер з нескінченного циклу божевілля: відкрийте NSURLProtocol.swift, змініть методи startLoading () і canInitWithRequest (_ :), ось так:

override class func canInitWithRequest (request: NSURLRequest) -> Bool {print ( "Request # \ (requestCount ++): URL = \ (request.URL! .absoluteString)") if NSURLProtocol .propertyForKey ( "MyURLProtocolHandledKey", inRequest: request)! = nil {return false} return true} override func startLoading () {var newRequest = self .request.mutableCopy () as NSMutableURLRequest NSURLProtocol .setProperty (true, forKey: "MyURLProtocolHandledKey", inRequest: newRequest) self .connection = NSURLConnection (request : newRequest, delegate: self)}

Тепер startLoading () виставляє властивість пов'язане з ключем «MyURLProtocolHandledKey» на true для поточного запиту. Це означає, що наступного разу, коли він викликає метод canInitWithRequest (_ :) для даного екземпляра NSURLProtocol, протокол може запитати, виставлено це властивість.

Якщо його значення виставлено на true, то це означає, що вам не потрібно обробляти цей запит ще раз, і система завантаження URL отримає дані з мережі. Так як екземпляр MyURLProtocol є делегатом для цього запиту, то він отримає відповідь від NSURLConnectionDelegate.

Запустіть вашу програму. Коли ви зробите це, відразу переконаєтеся в тому, що воно благополучно відображає всі дані в вашому UIWebView. Солодка перемога! Тепер консоль виглядає приблизно ось так:

Request # 0: URL = http: Request # 1: URL = http: Request # 2: URL = http: Request # 3: URL = http: Request # 4: URL = http: Request # 5: URL = http: Request # 6: URL = http: Request # 7: URL = http: Request # 8: URL = http: Request # 9: URL = http: Request # 10: URL = http: Request # 11: URL = http: Request # 12: URL = http: Request # 13: URL = http: Request # 14: URL = http: Request # 15: URL = http: Request # 16: URL = http: Request # 17: URL = http: Request # 18: URL = http: Request # 19: URL = http:

Вам напевно цікаво, чому довелося стільки всього зробити і все для того, щоб ваше додаток працювало точно так же, як воно працювало на початку туторіал? А це для того, щоб підготувати вас до найцікавішого! Тепер у вас є повний контроль над даними URL вашого застосування і ви можете робити з ними все, що захочете. Тепер саме час почати кешувати дані URL вашого застосування.

Реалізація локального кеша

Першою вимогою до додатка було те, що для кожного запиту, воно повинно було завантажувати дані з інтернету тільки один раз, і кешувати їх. Якщо запит повторюється надалі, то ваш протокол надає кеш відповідь без перезавантаження даних з мережі.

замітка:

Вихідний проект вже включає в себе базову модель Core Data і стек. Вам не потрібно знати деталі Core Data, думайте про нього, як про сховище даних.

Тепер саме час зберегти відповіді, які отримує додаток з мережі, щоб була можливість отримати їх, коли ми отримуємо запит схожий з кеш даними. Відкрийте MyURLProtocol.swift і додайте наступний import вгору файлу.

import CoreData

Потім додайте наступні властивості в реалізацію класу:

var mutableData: NSMutableData! var response: NSURLResponse!

Властивість response буде тримати посилання на метадані, які вам знадобляться для зберігання відповіді від сервера. Властивість mutableData буде використано для зберігання даних, які отримує з'єднання в методі делегата connection (_: didRecieveData).

Додайте наступний метод в клас:

func saveCachedResponse () {print ( "Saving cached response") let delegate = UIApplication .sharedApplication (). delegate as! AppDelegate let context = delegate.managedObjectContext let cachedResponse = NSEntityDescription .insertNewObjectForEntityForName ( "CachedURLResponse", inManagedObjectContext: context) as NSManagedObject cachedResponse.setValue (self .mutableData, forKey: "data") cachedResponse.setValue (self .request. URL! .AbsoluteString , forKey: "url") cachedResponse.setValue (NSDate (), forKey: "timestamp") cachedResponse.setValue (self .response. mIMEType, forKey: "mimeType") cachedResponse.setValue (self .response.textEncodingName, forKey: " encoding ") if context.hasChanges {do {try context.save ()} catch let error as NSError {NSLog (" сталася помилка \ (error), \ (error.userInfo) ") abort ()}}

Ось що робить цей метод:

  1. Отримує NSManagedObjectContext з Core Data примірника AppDelegate. Цей контекст є вашим інтерфейсом взаємодії з Core Data.
  2. Створюємо примірник NSManagedObject для відповідності моделі, яку ви бачили в фйле .xcdatamodeld. Встановлюємо значення, грунтуючись на посиланнях на NSURLResponse і NSMutableData, які у вас є.
  3. Зберігаємо контекст керованого об'єкта Core Data, якщо в ньому відбулися зміни.

Тепер у вас є можливість збереження даних, залишилося тільки викликати цей метод. Продовжуємо працювати в MyURLProtocol.swift. Змініть методи делегата NSURLConnection на наступні:

func connection (connection: NSURLConnection !, didReceiveResponse response: NSURLResponse!) {self .client !. URLProtocol (self, didReceiveResponse: response, cacheStoragePolicy:. NotAllowed) self .response = response self .mutableData = NSMutableData ()} func connection (connection: NSURLConnection !, didReceiveData data: NSData!) {Self .client !. URLProtocol (self, didLoadData: data) self .mutableData.appendData (data)} func connectionDidFinishLoading (connection: NSURLConnection!) {Self .client !. URLProtocolDidFinishLoading (self) self .saveCachedResponse ()}

Замість прямої передачі запиту і даних клієнта, вони зберігаються за допомогою вашого протокольного класу.

Запустіть вашу програму. Нічого не змінилося в його роботі, але запам'ятайте, що успішно отримані відповіді від сервера тепер зберігаються в локальній базі даних вашого застосування.

Отримання закеширувалася відповіді

Нарешті настав час отримати раніше закеширувалася запити і відправити їх клієнту NSURLProtocol. Відкрийте MyURLProtocol.swift і додайте наступний метод:

func cachedResponseForCurrentRequest () -> NSManagedObject? {Let delegate = UIApplication .sharedApplication (). Delegate as! AppDelegate let context = delegate.managedObjectContext let fetchRequest = NSFetchRequest () let entity = NSEntityDescription .entityForName ( "CachedURLResponse", inManagedObjectContext: context) fetchRequest.entity = entity let predicate = NSPredicate (format: "url ==% @", self. request. URL! .absoluteString) fetchRequest.predicate = predicate do {let possibleResult = try context.executeFetchRequest (fetchRequest) if! possibleResult.isEmpty {return possibleResult.first as? NSManagedObject}} catch let error as NSError {print ( "Fetch failed: \ (error.localizedDescription)")} return nil}

Ось що він робить:

  1. Бере контекст керованого об'єкта Core Data, точно так же, як і в saveCachedResponse ().
  2. Створює NSFetchRequest, кажучи про те, що ви хочете знайти всі сутності з ім'ям CachedURLResponse. Це і є та суть в моделі керованого об'єкта, яку ви хочете отримати.
  3. Предикат для вашого запиту (fetch request) повинен отримати об'єкт CachedURLResponse, який має відношення до URL і який ви намагаєтеся завантажити. Якраз цей блок це і робить.
  4. Виконує запит і перевіряє на наявність результатів. Якщо масив не пустили, то повертається перший з них.

Тепер нам потрібно повернутися і подивитися на реалізацію startLoading (). Замість того, щоб все підряд завантажувати з мережі, потрібно зробити так, щоб він спочатку перевіряв наявність закеширувалася відповіді по URL. Знайдіть відповідну реалізацію і замініть її на наступну:

override func startLoading () {let possibleCachedResponse = self .cachedResponseForCurrentRequest () if let cachedResponse = possibleCachedResponse {print ( "Serving response from cache") let data = cachedResponse.valueForKey ( "data") as! NSData! let mimeType = cachedResponse.valueForKey ( "mimeType") as! String! let encoding = cachedResponse.valueForKey ( "encoding") as! String! let response = NSURLResponse (URL: self .request. URL!, MIMEType: mimeType, expectedContentLength: data.length, textEncodingName: encoding) self .client !. URLProtocol (self, didReceiveResponse: response, cacheStoragePolicy:. NotAllowed) self .client !. URLProtocol (self, didLoadData: data) self .client !. URLProtocolDidFinishLoading (self)} else {print ( "Serving response from NSURLConnection") let newRequest = self .request.mutableCopy () as! NSMutableURLRequest NSURLProtocol .setProperty (true, forKey: "MyURLProtocolHandledKey", inRequest: newRequest) self .connection = NSURLConnection (request: newRequest, delegate: self)}}

Ось, що тут відбувається:

  1. Спочатку вам потрібно з'ясувати, чи є закеширувалася відповідь на поточний запит.
  2. Якщо є, то ми отримуємо відповідні дані з кеша.
  3. Створюємо об'єкт NSURLResponse зі збережених даних.
  4. Говоримо про дані у відповіді клієнту. Встановлюємо політику конфіденційності на .NotAllowed, так як ми не хочемо, щоб клієнт кешироваться що-небудь з тих самих пір, як це стало вашим обов'язком. Потім викликаєте URLProtocolDidFinishLoading для того, щоб подати сигнал про завершення завантаження. Ніяких мережевих запитів, так то!
  5. Якщо нічого в кеші за поточним запиту немає, то ми просто завантажуємо дані, як зазвичай.

Запустіть ваш проект знову. Зайдіть на парочку сайтів і вийдіть з програми. Встановіть режим роботи вашого пристрою на «в літаку» (або якщо ви працюєте на симуляторі, то вам потрібно вимкнути wi-fi вашого комп'ютера або просто витягніть кабель Ethernet) і знову запустіть проект. Спробуйте знову зайти на ті ж сайти, які ви тільки що відвідували. Ваші сторінки повинні довантажити з кeша!

В консолі ви побачите безліч сутностей наступного типу:

Request # 7: URL = http: Serving response from cache

Це лог того, що ваша відповідь надходить з кeша.

Ну от і все! Ваша програма благополучно кешує дані і зі швидкістю світла видає їх звідти при повторному запиті! Ваші користувачі будуть просто щасливі користуватися вашим додатком у себе на пристрої!

Коли потрібно використовувати NSURLProtocol?

Як ви можете використовувати NSURLProtocol, щоб зробити ваше додаток краще, швидше, сильніше і зубодробильної класним? Ось вам кілька прикладів:

Забезпечення індивідуальних відповідей для мережевих запитів:

Неважливо, чи робите ви запит з використанням UIWebView, NSURLConnection або використовуєте сторонню бібліотеку (типу AFTNetworking, MKNetworkKit ..., так як всі вони надбудовані на NSURLConnection). Ви можете створити індивідуальний відповідь і для метаданих, і для даних. Ви можете використовувати його заглушити відповідь на запит при тестуванні, наприклад.

Пропустити активність мережі і надати локальні дані:

Іноді ви думаєте, що немає ніякої необхідності кожен раз створювати мережеві запити, таким чином NSURLProtocol може налаштувати ваше додаток так, що дані будуть шукатися в локальній базі даних.

Перенаправлення мережевих запитів:

Чи хотілося вам коли-небудь перенаправити запит на proxy сервер без того, щоб довірити користувачеві змінити будь-які налаштування iOS? Що ж, ви можете! NSURLProtocol надає те, що вам потрібно - контроль над запитами. Ви можете налаштувати свій додаток так, що воно буде перехоплювати і перенаправляти запити на інший проксі-сервер або туди, куди вам тільки захочеться. Йдеться про контроль запиту!

Зміна user-agent вашого запиту:

До того, як спрацює будь-якої запит, ви можете вирішити, чи потрібно змінювати його метадані або дані. Наприклад, ви можете захотіти змінити його user-agent. Це дуже зручно, якщо ваш сервер змінює вміст в залежності від user-agent. У приклад цього можна навести те, як відображається сторінка в залежності від того, де ви її дивіться: з телефону або комп'ютера.

Використовуйте свій власний мережевий протокол:

Ви можете мати свій власний мережевий протокол (наприклад, що-небудь, побудоване на UDP). Ви можете реалізувати це в вашому додатку, що так само не обмежує ваші можливості у використанні будь-якої мережевої бібліотеки.

Пам'ятайте, що NSURLProtocol є потужним інструментом на додаток до бібліотеки, яку ви вже використовуєте. Якщо говорити коротко, то ви можете користуватися перевагами NSURLProtocol в той час, поки користуєтеся і своєї власної бібліотекою.

Якщо говорити коротко, то ви можете користуватися перевагами NSURLProtocol в той час, поки користуєтеся і своєї власної бібліотекою

Якщо ви знайшли друкарську помилку - виділіть її та натисніть Ctrl + Enter! Для зв'язку з нами ви можете використовувати [email protected] .

Звучить як диво?
Що використовують UIWebView і WKWebView?
Що використовується для потокового відео в MPMoviePlayer?
Як ви відправляєте когось на iTunes за вашим додатком, входите в FaceTime або Skype, завантажуєте додаток в систему, або навіть вставляєте зображення в HTML файл?
Отже, ви готові почати вивчення можливостей NSURLProtocol?
UIWebView завантажить відповідь і відобразить результат в додатку - досить просто для початку, правда?
Параметром цього методу є запит, а сам він звучить, як питання протоколу: чи зможе той обробити передається запит?
Application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?
Як ви отримуєте дані?
Зрештою, ви ж довіряєте розробнику, правильно ?


Новости
  • Виртуальный хостинг

    Виртуальный хостинг. Возможности сервера распределяются в равной мере между всеми... 
    Читать полностью

  • Редизайн сайта

    Редизайн сайта – это полное либо частичное обновление дизайна существующего сайта.... 
    Читать полностью

  • Консалтинг, услуги контент-менеджера

    Сопровождение любых интернет ресурсов;- Знание HTML и CSS- Поиск и обновление контента;-... 
    Читать полностью

  • Трафик из соцсетей

    Сравнительно дешевый способ по сравнению с поисковым и контекстным видами раскрутки... 
    Читать полностью

  • Поисковая оптимизация

    Поисковая оптимизация (англ. search engine optimization, SEO) — поднятие позиций сайта в результатах... 
    Читать полностью