Skip to content

Commit

Permalink
Speeds up proxy creation/deletion
Browse files Browse the repository at this point in the history
  • Loading branch information
acadet committed Jan 28, 2016
1 parent 9761371 commit 87f9a7e
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 43 deletions.
2 changes: 2 additions & 0 deletions caravel/Caravel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ public class Caravel {

internal func dispatch(busName: String, eventName: String, eventData: AnyObject?) {
if busName != self.name {
// Different buses can use the same web view so same proxy
// If not a potential receiver, ignore event
return
}

Expand Down
34 changes: 19 additions & 15 deletions caravel/internal/proxies/WKScriptMessageHandlerProxy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,43 @@ import WebKit
Sets up a custom script message handler for the provided configuration
*/
internal class WKScriptMessageHandlerProxy: NSObject, WKScriptMessageHandler {
private static let subscriberLock = NSObject()
private let subscriberLock = NSObject()

/**
All the subscribers.
*/
private lazy var subscribers: [IWKWebViewObserver] = []

init(configuration: WKWebViewConfiguration) {
super.init()

configuration.userContentController.addScriptMessageHandler(self, name: "caravel")
}

private func lockSubscribers(@noescape action: () -> Void) {
synchronized(WKScriptMessageHandlerProxy.subscriberLock, action: action)
synchronized(subscriberLock, action: action)
}

private func iterateOverDelegates(callback: (IWKWebViewObserver) -> Void) {
self.lockSubscribers {
for e in self.subscribers {
callback(e)
}
}
}

func subscribe(subscriber: IWKWebViewObserver) {
lockSubscribers {
for s in self.subscribers {
if s.hash == subscriber.hash {
return
}
}

self.subscribers.append(subscriber)
}
}

func unsubscribe(subscriber: IWKWebViewObserver) {
lockSubscribers {
var i = 0
Expand All @@ -55,19 +55,23 @@ internal class WKScriptMessageHandlerProxy: NSObject, WKScriptMessageHandler {
}
}
}

func hasSubscribers() -> Bool {
return self.subscribers.count > 0
}


func willBeDeleted(config: WKWebViewConfiguration) {
config.userContentController.removeScriptMessageHandlerForName("caravel")
}

func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {
let body = message.body as! Dictionary<String, AnyObject>
let busName = body["busName"] as! String
let eventName = body["eventName"] as! String
let eventData = body["eventData"]
iterateOverDelegates {e in
background {e.onMessage(busName, eventName: eventName, eventData: eventData)}

iterateOverDelegates { e in
background { e.onMessage(busName, eventName: eventName, eventData: eventData) }
}
}
}
52 changes: 24 additions & 28 deletions caravel/internal/proxies/WKWebViewMediator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,51 +7,47 @@ import WebKit
*/
internal class WKScriptMessageHandlerProxyMediator {
private static let creationLock = NSObject()

/**
Indexed by WKWebViewConfiguration's hash
*/
private static var proxies: [Int: WKScriptMessageHandlerProxy] = [:]

private static func lockProxies(@noescape action: () -> Void) {
synchronized(creationLock, action: action)
}

static func subscribe(configuration: WKWebViewConfiguration, observer: IWKWebViewObserver) {
let action: Void -> Bool = {
for (k, v) in proxies {
if k == configuration.hash {
v.subscribe(observer)
return true
}
}
return false
}

if !action() {
let key = configuration.hash

if let p = proxies[key] {
p.subscribe(observer)
} else {
lockProxies {
if action() {
return
} else {
let p = WKScriptMessageHandlerProxy(configuration: configuration)
if let p = proxies[key] {
p.subscribe(observer)
proxies[configuration.hash] = p
} else {
let proxy = WKScriptMessageHandlerProxy(configuration: configuration)
proxy.subscribe(observer)
proxies[key] = proxy
}
}
}
}

static func unsubscribe(configuration: WKWebViewConfiguration, observer: IWKWebViewObserver) {
for (k, v) in proxies {
if k == configuration.hash {
v.unsubscribe(observer)

if !v.hasSubscribers() {
lockProxies {
proxies.removeValueForKey(configuration.hash)
let key = configuration.hash

if let p = proxies[key] {
p.unsubscribe(observer)

if !p.hasSubscribers() {
lockProxies {
if !p.hasSubscribers() {
p.willBeDeleted(configuration)
proxies.removeValueForKey(key)
}
}
return
}
}
}
Expand Down

0 comments on commit 87f9a7e

Please sign in to comment.