Skip to content

Instantly share code, notes, and snippets.

@Avangelista
Created January 23, 2023 01:16
Show Gist options
  • Select an option

  • Save Avangelista/9f9546df30903c7e3a6c8b6d11ae5277 to your computer and use it in GitHub Desktop.

Select an option

Save Avangelista/9f9546df30903c7e3a6c8b6d11ae5277 to your computer and use it in GitHub Desktop.
Navigate forward and back in WebKit with previews
// Add recognisers for back and forward
let swipeLeftRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipe(recognizer:)))
let swipeRightRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipe(recognizer:)))
swipeLeftRecognizer.direction = .left
swipeRightRecognizer.direction = .right
webView.addGestureRecognizer(swipeLeftRecognizer)
webView.addGestureRecognizer(swipeRightRecognizer)
@objc private func handleSwipe(recognizer: UISwipeGestureRecognizer) {
if (recognizer.direction == .left) {
if webView.canGoForward {
// snapshot current page
guard let webViewSnapshot = webView.snapshotView(afterScreenUpdates: true) else { webView.goForward(); return }
webViewSnapshot.frame = view.frame
view.insertSubview(webViewSnapshot, belowSubview: webView)
// go back in the browser
webView.goForward()
// get snapshot of previous page
let image = CIImage(ioSurface: webView._snapshotLayerContents(forBackForwardListItem: webView.backForwardList.forwardItem) as! IOSurfaceRef)
let imageView = UIImageView(image: UIImage(ciImage: image))
imageView.frame = view.frame
imageView.isUserInteractionEnabled = false
view.insertSubview(imageView, aboveSubview: webView)
// animate the current page snapshot away
imageView.frame.origin.x += imageView.frame.size.width
self.webView.frame.origin.x += self.webView.frame.size.width
Timer.scheduledTimer(withTimeInterval: 0.2, repeats: false) { _ in
UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut, animations: {
imageView.frame.origin.x -= imageView.frame.size.width
self.webView.frame.origin.x -= self.webView.frame.size.width
}, completion: { _ in
webViewSnapshot.removeFromSuperview()
UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseIn, animations: {
imageView.alpha = 0
}, completion: {_ in
imageView.removeFromSuperview()
})
})
}
}
}
if (recognizer.direction == .right) {
if webView.canGoBack {
// snapshot current page
guard let webViewSnapshot = webView.snapshotView(afterScreenUpdates: true) else { webView.goBack(); return }
webViewSnapshot.frame = view.frame
view.insertSubview(webViewSnapshot, aboveSubview: webView)
// go back in the browser
webView.goBack()
// get snapshot of previous page
let image = CIImage(ioSurface: webView._snapshotLayerContents(forBackForwardListItem: webView.backForwardList.backItem) as! IOSurfaceRef)
let imageView = UIImageView(image: UIImage(ciImage: image))
imageView.frame = view.frame
imageView.isUserInteractionEnabled = false
view.insertSubview(imageView, belowSubview: webViewSnapshot)
// animate the current page snapshot away
UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseIn, animations: {
webViewSnapshot.frame.origin.x += webViewSnapshot.frame.size.width
}, completion: { _ in
webViewSnapshot.removeFromSuperview()
UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseIn, animations: {
imageView.alpha = 0
}, completion: {_ in
imageView.removeFromSuperview()
})
})
}
}
}
#import <WebKit/WKWebView.h>
@interface WKWebView ()
-(id)_snapshotLayerContentsForBackForwardListItem:(id)arg1;
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment