Зачем нужен javascript в ios-приложениях. Евгений Дымов
DESCRIPTION
Зачем нужен JavaScript в iOS-приложенияхTRANSCRIPT
![Page 1: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/1.jpg)
![Page 2: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/2.jpg)
JavaScript в iOS приложениях
Александр Денисов Евгений Дымов
![Page 3: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/3.jpg)
Часть 1 JavaScript и WebView
![Page 4: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/4.jpg)
Почему WebView?
![Page 5: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/5.jpg)
5
Просто и удобно
Открытие веб-страниц
Safari
Пользователь остается в нашем приложении
WebView
![Page 6: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/6.jpg)
Социальная авторизация
6
Потому что никто не любит регистрироваться
![Page 7: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/7.jpg)
Просмотр документов
7
〉Microsoft Office
〉iWork
〉Медиа-контент
![Page 8: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/8.jpg)
UIWebView
![Page 9: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/9.jpg)
WKWebView!
![Page 10: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/10.jpg)
WKWebView
〉WebKit framework
〉Богатый API
〉Быстрый рендеринг
〉Быстрый JavaScript
〉Отдельный процесс
10
http://bigwol.com/surprised-baby-hd-widescreen-hd-free-wallpaper
![Page 11: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/11.jpg)
Скорость выполнения JavaScript
SunSpider: https://www.webkit.org/perf/sunspider/sunspider.html
11
@ iPhone 5s, iOS 8.1
WKWebView
UIWebView
0 375 750 1125 1500
Время выполнения, мс
![Page 12: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/12.jpg)
WKWebView
Бонус: “из коробки” получаем:
〉Навигация жестами
〉Звонок с другого устройства
〉Открытие в новой вкладке
〉Заголовок страницы
API diff: http://nshipster.com/wkwebkit/
12
![Page 13: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/13.jpg)
Как?
![Page 14: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/14.jpg)
Что нам потребуется
〉Процесс загрузки страницы
〉Выполнение JavaScript
〉Связь JavaScript — нативный код
14
![Page 15: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/15.jpg)
Процесс загрузки страницы
15
WKWebView
@protocol WKNavigationDelegate; @protocol WKUIDelegate;
UIWebView
@protocol UIWebViewDelegate;
![Page 16: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/16.jpg)
- (void)webView:(WKWebView*)webView decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
- (void)webView:(WKWebView*)webView decidePolicyForNavigationResponse: (WKNavigationResponse*)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;
- (void)webView:(WKWebView*)webView didStartProvisionalNavigation:(WKNavigation*)navigation;
- (void)webView:(WKWebView*)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation*)navigation;
WKNavigationDelegate
16
![Page 17: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/17.jpg)
17
- (void)webView:(WKWebView*)webView didFailProvisionalNavigation:(WKNavigation*)navigation withError:(NSError*)error;
- (void)webView:(WKWebView*)webView didCommitNavigation:(WKNavigation*)navigation;
- (void)webView:(WKWebView*)webView didFinishNavigation:(WKNavigation*)navigation;
- (void)webView:(WKWebView*)webView didFailNavigation:(WKNavigation*)navigation withError:(NSError*)error;
- (void)webView:(WKWebView*)webView didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge*)challenge completionHandler:(void (^)( NSURLSessionAuthChallengeDisposition disposition, NSURLCredential*credential))completionHandler;
![Page 18: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/18.jpg)
- (WKWebView*)webView:(WKWebView*)webView createWebViewWithConfiguration: (WKWebViewConfiguration*)configuration forNavigationAction:(WKNavigationAction*)navigationAction windowFeatures:(WKWindowFeatures*)windowFeatures;
- (void)webView:(WKWebView*)webView runJavaScriptAlertPanelWithMessage:(NSString*)message initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void (^)())completionHandler;
WKUIDelegate
18
![Page 19: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/19.jpg)
19
- (void)webView:(WKWebView*)webView runJavaScriptConfirmPanelWithMessage:(NSString*)message initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void (^)(BOOL result))completionHandler;
- (void)webView:(WKWebView*)webView runJavaScriptTextInputPanelWithPrompt:(NSString*)prompt defaultText:(NSString*)defaultText initiatedByFrame:(WKFrameInfo*)frame
![Page 20: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/20.jpg)
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType;
- (void)webViewDidStartLoad:(UIWebView*)webView;
- (void)webViewDidFinishLoad:(UIWebView*)webView;
- (void)webView:(UIWebView*)webView didFailLoadWithError:(NSError*)error;
UIWebViewDelegate
20
![Page 21: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/21.jpg)
Выполнение кода JavaScript
21
WKWebView
- (void)evaluateJavaScript:(NSString*)javaScriptString completionHandler:(void (^)(id, NSError*))completionHandler;
UIWebView
- (NSString*)stringByEvaluatingJavaScriptFromString:(NSString*)script;
![Page 22: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/22.jpg)
Выполнение кода JavaScript: пример
22
// Favicon NSString* faviconJS = @"document.querySelector(\"link[rel='shortcut icon']\")" ".getAttribute('href')"; [wkWebView evaluateJavaScript:faviconJS completionHandler: ^(NSString* favicon, NSError* error) { if (favicon) { [self didObtainFavicon:favicon]; } }];
WKWebView
![Page 23: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/23.jpg)
Выполнение кода JavaScript: пример
23
// Заголовок страницы NSString* titleJS = @"document.title"; return [uiWebView stringByEvaluatingJavaScriptFromString:titleJS];
UIWebView
![Page 24: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/24.jpg)
Связь JavaScript — нативный код
24
WKWebView
@protocol WKScriptMessageHandler <NSObject>
@required
- (void)userContentController: (WKUserContentController*)userContentController didReceiveScriptMessage:(WKScriptMessage*)message;
@end
![Page 25: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/25.jpg)
25
@interface WKUserContentController : NSObject
...
- (void)addScriptMessageHandler: (id<WKScriptMessageHandler>)scriptMessageHandler name:(NSString*)name;
@end !
!
!
// Добавление scriptMessageHandler создает для всех веб-фреймов // функцию: window.webkit.messageHandlers.<name>.postMessage(<messageBody>)
![Page 26: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/26.jpg)
Связь JavaScript — нативный код
26
UIWebView
function YACSendToNativeCode(name, data) { var message = { }; message.name = name; message.data = data; window.location = "jsbridge://" + escape(JSON.stringify(message)); };
![Page 27: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/27.jpg)
27
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType { if ([request.URL.scheme isEqualToString:@"jsbridge"]) { // Обработка сообщения return NO; } return YES; }
![Page 28: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/28.jpg)
JavaScript библиотеки
Пример: jQuery
〉Быстро получаем богатую функциональность
〉Возможен конфликт
〉Снижение производительности
〉Кроссбраузерная совместимость?
Можем реализовать необходимую функциональность самостоятельно!
28
![Page 29: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/29.jpg)
NSURLProtocol (только UIWebView)
Управление сетевым стеком с помощью NSURLProtocolhttps://tech.yandex.ru/events/yac/2013/talks/1076/
Можем реализовать:
〉Сжатие трафика
〉Поддержку новых форматов WebP WebM …
29
![Page 30: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/30.jpg)
Саади
«Два человека бесплодно трудились и без пользы старались: тот, кто копил богатство и не пользовался им, и тот, кто учился наукам, но не применял их»
![Page 31: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/31.jpg)
А теперь делаем «фичи»!
Inspired by
![Page 32: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/32.jpg)
Примеры
〉Prerendering, DNS prefetching
〉Управление медиаконтентом
〉Контекстное меню
〉Сохранение паролей
〉Социальная авторизация
〉Изменение DOM
32
![Page 33: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/33.jpg)
Prerendering, DNS prefetching
DNS-запросы: от 1мс до нескольких секунд
Prerendering: субъективное ускорение загрузки страниц
33
<link rel="prerender" href="http://example.org/index.html">
<link rel="dns-prefetch" href="http://host-to-prefetch.com">
![Page 34: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/34.jpg)
34
function YACPrerenderLinks() { var results = [], nodeList = document.querySelector("link[rel='prerender']"); !
for (var i = 0; i < nodeList.length; i++) { var href = nodeList[i].getAttribute("href"); results.push(href); } return results.join(); } !
function YACDNSPrefetchLinks() { ... }
![Page 35: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/35.jpg)
Управление медиаконтентом
var YACAudioElementsList = [ ], YACHTMLAudioElementPlay = window.HTMLAudioElement.prototype.play; !
function YACAddHTMLAudioElementToList(el) { YACHTMLAudioElementsList.push(el); } !
window.HTMLAudioElement.prototype.play = function() { YACAddHTMLAudioElementToList(this); this.play = YACHTMLAudioElementPlay; this.play(); }
35
![Page 36: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/36.jpg)
36
function YACPauseHTMLAudioElements() { for (i = 0; i < YACHTMLAudioElementsList.length; i++) { YACHTMLAudioElementsList[i].pause(); } } !
function YACResumePausedHTMLAudio() { ... }
![Page 37: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/37.jpg)
Контекстное меню
37
〉Открыть вкладку
〉Копировать ссылку
〉Поделиться ссылкой
〉Сохранить изображение
〉Позвонить с другого устройства
![Page 38: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/38.jpg)
Контекстное меню
// 1. Получаем элемент по координатам и декодируем из JSON // 2. Заполняем и показываем UIActionSheet - (void)openContextualMenuAtPoint:(CGPoint)point { YACInteractiveHTMLElement* element = [self interactiveElementAtPoint:point]; [self showContextualMenuForElement:element atPoint:point]; }
38
Разберем на примере YACImageLinkForTouchAtPoint
![Page 39: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/39.jpg)
39
function YACElementFromPoint(x, y) { var currentDocument = document, element = currentDocument.elementFromPoint(x, y), boundRect; try { while (element && (element.nodeName === "FRAME" || element.nodeName === "IFRAME")) { boundRect = element.getBoundingClientRect(); x -= boundRect.left; y -= boundRect.top; currentDocument = element.contentDocument; element = currentDocument.elementFromPoint(x, y); } } catch (e) { } return element; }
![Page 40: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/40.jpg)
40
function YACImageLinkForTouchAtPoint(x, y) { var element = YACElementFromPoint(x, y); return YACImageLinkForElement(element); } !
!
function YACImageLinkForElement(element) { if (element.tagName === "IMG" && element.src) { return element.src; } return null; }
![Page 41: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/41.jpg)
Сохранение паролей
41
Обязательно спрашиваем разрешения!
![Page 42: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/42.jpg)
42
// 1. Перехватываем событие отправки формы // Обработчик вызывается для каждой отправляемой формы window.addEventListener("submit", YACFormSubmitHandler, false); !
!
// 2. Сохраняем заполненные данные в обработчике события function YACFormSubmitHandler(e) { if (e.target.nodeName !== "FORM") { return; } !
YACCollectLoginFormDataAndSendToNativeCode(e.target); }
![Page 43: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/43.jpg)
43
// 3. Заполняем данные при загрузке страницы с такой же формой function YACFillLoginFormWithData( form, usernameElementName, usernameValue, passwordElementName, passwordValue) { !
var usernameElement = form.querySelector( "input[name='" + usernameElementName + "']"); usernameElement.value = usernameValue; !
var passwordElement = form.querySelector( "input[type='password'][name='" + passwordElementName + "']"); passwordElement.value = passwordValue; }
![Page 44: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/44.jpg)
Социальная авторизация
44
Это:
〉Удобно
〉Привычно для пользователя
〉“Must have”
![Page 45: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/45.jpg)
Социальная авторизация
45
Реализация с помощью WebView:
Доступ к данным на странице авторизации!
![Page 46: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/46.jpg)
Социальная авторизация
45
Реализация с помощью WebView:
Доступ к данным на странице авторизации!
![Page 47: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/47.jpg)
Социальная авторизация
45
Реализация с помощью WebView:
Доступ к данным на странице авторизации!
Совет: не используйте WebView для социальной авторизации
![Page 48: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/48.jpg)
Реализация с помощью OAuth
1. Регистрируем приложение
2. Отправляем запрос https://oauth.yandex.ru/authorize? response_type=token & client_id=<идентификатор приложения>
3. Пользователь авторизуется и выдает разрешения для нашего приложения
4. Получаем данные в ответе http://www.example.com/token# access_token=<новый OAuth-токен> & expires_in=<время жизни токена в секундах>
46
![Page 49: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/49.jpg)
47
// 1. Native SDK !
// 2. Callback URL scheme - обрабатываем в AppDelegate - (BOOL)application:(UIApplication*)application openURL:(NSURL*)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation; !
// 3. WebView (пример для UIWebView, WKWebView - аналогично) - (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType;
![Page 50: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/50.jpg)
Изменение DOM с помощью JavaScript
48
VIDEO
![Page 51: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/51.jpg)
Изменение DOM с помощью JavaScript
48
VIDEO
![Page 52: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/52.jpg)
Что же получилось?
〉Мы разобрались в возможностях UIWebView и WKWebView
〉Научились писать “фичи” для веб-контента
〉Делаем пользователей счастливее
〉И все это — благодаря JavaScript!
49
![Page 53: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/53.jpg)
Часть 2 JavaScript без WebView
![Page 54: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/54.jpg)
Зачем?
![Page 55: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/55.jpg)
Расширяемость
〉Внешняя логика
〉Интерпретация в runtime
〉JavaScript!
52
![Page 56: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/56.jpg)
Платформонезависимость
〉Нативный UI
〉Общая бизнес-логика
〉Мгновенное обновление бизнес-логики
〉JavaScript!
53
![Page 57: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/57.jpg)
Программируемость
Мы продолжаем наши передачи на этой частоте!
54
![Page 58: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/58.jpg)
Как?
![Page 59: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/59.jpg)
JavaScriptCore
〉Objective-C API доступно с iOS 7, Mac OS X 10.9
〉JavaScript движок в WebKit
〉Также известен как SquirrelFish, Nitro
56
© 2008 Goopymart
![Page 60: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/60.jpg)
JavaScriptCore
〉JSContext
〉JSValue
〉<JSExport>
〉JSManagedValue
〉JSVirtualMachine
57
![Page 61: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/61.jpg)
JSContext
〉Среда выполнения JavaScript кода
〉Глобальный объект (à la window)
!
- (JSValue*)evaluateScript:(NSString*)script;
58
![Page 62: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/62.jpg)
JSValue
Ссылка на JavaScript объект
!
+ (JSValue*)valueWithObject:(id)value inContext:(JSContext*)context;
59
![Page 63: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/63.jpg)
<JSExport>
Экспорт методов и свойств в JavaScript окружение
60
@protocol MyClassExports <JSExport>
- (void)foo; // Доступен из JavaScript
@end
@interface MyClass : NSObject <MyClassExports>
- (void)bar; // Недоступен из JavaScript
@end
![Page 64: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/64.jpg)
Поехали!
![Page 66: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/66.jpg)
Реализация
〉Нативная графика — Sprite Kit
〉Управление персонажем — JavaScript
〉Соединительное звено — JavaScriptCore
63
![Page 68: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/68.jpg)
CharacterAI.js
var CharacterAI = function() { }; !
CharacterAI.prototype.onIdle = function(event) { this.character.ahead(100); this.character.turn(45); this.character.back(100); }; !
CharacterAI.prototype.onScannedEnemy = function(event) { this.character.fire(); }; ...
65
![Page 69: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/69.jpg)
// TODO:
〉Создать экземпляр CharacterAI
〉Передать персонаж в JavaScript окружение
〉Экспортировать необходимые методы
〉Сообщать о событиях (onIdle, onScannedEnemy…)
66
![Page 70: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/70.jpg)
Создать экземпляр CharacterAI
@property JSContext* context; @property JSValue* characterAI; !
... !
self.context = [[JSContext alloc] init]; [self.context evaluateScript:self.script.contents]; self.characterAI = [self.context evaluateScript:@"new CharacterAI()"];
67
![Page 71: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/71.jpg)
Передать персонаж в JavaScript окружение
@property APAIntelligentHeroCharacter* character; !
... !
self.characterAI[@"character"] = self.character;
68
![Page 72: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/72.jpg)
Экспортировать необходимые методы
@protocol APAIntelligentHeroCharacterExports <JSExport> - (void)ahead:(CGFloat)amount; ... @end !
@interface APAIntelligentHeroCharacter : APAHeroCharacter <APAIntelligentHeroCharacterExports> @end !
@implementation APAIntelligentHeroCharacter - (void)ahead:(CGFloat)amount { } ... @end
69
![Page 73: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/73.jpg)
Сообщать о событиях
- (void)updateWithTimeSinceLastUpdate:(CFTimeInterval)interval { ... if (self.character.state == APACharacterStateIdle) { [self.characterAI invokeMethod:@"onIdle" withArguments:@[ event ]]; } ... }
70
![Page 74: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/74.jpg)
Demo
![Page 75: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/75.jpg)
72
![Page 76: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/76.jpg)
72
![Page 77: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/77.jpg)
Two more things…
![Page 78: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/78.jpg)
Управление памятью@property JSValue* characterAI; ... - (void)setCharacterAI:(JSValue*)characterAI { _managedCharacterAI = [JSManagedValue managedValueWithValue:characterAI]; [characterAI.context.virtualMachine addManagedReference:_managedCharacterAI withOwner:self]; } !
- (JSValue*)characterAI { return [_managedCharacterAI value]; }
74
removeManagedReference:withOwner: для удаления ссылки
![Page 79: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/79.jpg)
Многопоточность
〉API потокобезопасно
〉Область блокировки — JSVirtualMachine
〉JSVirtualMachine — контейнер для JSContext
〉Использование отдельной JSVirtualMachine для каждого потока
75
![Page 80: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/80.jpg)
Материалы
〉WWDC 2014 Introducing the Modern WebKit API
〉nshipster.com/wkwebkit
〉tech.yandex.ru/events/yac/2013/talks/1076
〉WWDC 2013 Integrating JavaScript into Native Apps
〉trac.webkit.org/wiki/JavaScriptCore
〉github.com/WebKit/webkit
〉bit.ly/yac2014-ios-jstalks76
![Page 81: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/81.jpg)
Зачем JavaScript в iOSприложениях?
![Page 82: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/82.jpg)
Спасибо за внимание!
![Page 83: Зачем нужен JavaScript в iOS-приложениях. Евгений Дымов](https://reader033.vdocuments.site/reader033/viewer/2022042508/55892fe3d8b42a57608b461a/html5/thumbnails/83.jpg)
79
Александр Денисов
Контакты
stonespb
@_dymv
Евгений Дымов