WKWebView view not resizable - swift

I'm creating a macOS Swift app, I'm new to Swift. I'm trying to make the view resizable like web browsers (Chrome, Firefox, etc.), however my code doesn't seem to work, and I didn't find anything useful about WKWebView resizing.
Here's my code for the ViewController:
import Cocoa
import WebKit
class ViewController: NSViewController, WKUIDelegate
{
var webView: WKWebView!
override func loadView()
{
let webConfiguration = WKWebViewConfiguration ();
webConfiguration.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs");
webView = WKWebView (frame: CGRect(x:0, y:0, width:1920, height:1080), configuration:webConfiguration);
webView.uiDelegate = self;
self.view = webView;
}
override func viewDidLoad() {
super.viewDidLoad()
let webView = WKWebView(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.webView.frame.size.height))
self.view.addSubview(webView)
let url = URL(string: "https://www.google.com/")
webView.load(URLRequest(url: url!))
}
}
Results:

Okay so I figured out how to fix the issue with Willeke's recommendation:
Replace this:
let webView = WKWebView(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.webView.frame.size.height))
self.view.addSubview(webView)
let url = URL(string: "https://www.google.com/")
webView.load(URLRequest(url: url!))
With this:
if let url = URL(string: "https://www.roblox.com/") {
let request = URLRequest(url: url)
webView.load(request)
}

Related

Implementing UIView in SwiftUI

I am trying to implement a video player in SwiftUI via a UIView following this tutorial: https://medium.com/flawless-app-stories/avplayer-swiftui-b87af6d0553
Unfortunately the video is not displaying, I have AVFoundation imported so I am not sure of the issue. Has anyone found a solution to this?
Here are the classes I created:
class PlayerUIView: UIView {
private let playerLayer = AVPlayerLayer()
init(frame: CGRect, urlString: String) {
super.init(frame: frame)
guard let url = URL(string: urlString) else {
return
}
let player = AVPlayer(url: url)
player.play()
playerLayer.player = player
layer.addSublayer(playerLayer)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override func layoutSubviews() {
super.layoutSubviews()
playerLayer.frame = bounds
}
}
struct VideoPlayerUIView: UIViewRepresentable {
var frame: CGRect
var urlString: String
func makeUIView(context: Context) -> some UIView {
return PlayerUIView(frame: self.frame, urlString: self.urlString)
}
func updateUIView(_ uiView: UIViewType, context: Context) {
}
}
Here I how I am using the implementation in SwiftUI:
var body: some View {
Text("Videos")
VideoPlayerUIView(frame: CGRect(x: 0, y: 0, width: 400, height: 300), urlString: urlString)
}
This was the output (no video)
enter image description here
You did everything right here.
The only thing that is causing error is how you are process the URL.
Try initialising the player like this instead
let player = AVPlayer(url: Bundle.main.url(forResource: urlString, withExtension: "mp4")!)
Change the extension according to the format you are using. Remember, here I am force wrapping the optional. So, if you give a wrong urlString or have a video extension other than mp4, the app will crash

WKWebView - Margin Top

I'm starting swift.
Code is a webview without superior navigation, constrain moves the webview from the top leaving an upper margin.
see the image
Image Result
My code
import UIKit
import WebKit
class ViewController: UIViewController,WKNavigationDelegate, WKUIDelegate {
lazy var webView: WKWebView = {
let webConfiguration = WKWebViewConfiguration()
let webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
webView.navigationDelegate = self
webView.translatesAutoresizingMaskIntoConstraints = false
return webView
}()
func setupUI() {
self.view.backgroundColor = .red
self.view.addSubview(webView)
NSLayoutConstraint.activate([
webView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
webView.leftAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leftAnchor),
webView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor),
webView.rightAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.rightAnchor)
])
}
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
let myURL = URL(string: "https://www.google.com.br/")
let myRequest = URLRequest(url: myURL!,cachePolicy: NSURLRequest.CachePolicy.useProtocolCachePolicy,timeoutInterval: 10.0)
webView.load(myRequest)
}
}
Solved. Just add:
self.navigationController? .isNavigationBarHidden = true

How to give alpha value for WKWebView in swift?

I am Using WKWebView to show webpage, here i want to add alpha value to webpage while open the side menu. I am able to add alpha value to UIView but which is not working for WKWebView? How to add alpha value to WKWebView and delete that value?
For view i am using and works:
view?.backgroundColor = UIColor(white: 1, alpha: 0.7)
For WKWebView it's not working why?
aboutusWeb.isOpaque = false
testWebView?.backgroundColor = UIColor(white: 1, alpha: 0.7)
Complete code for webview:
import UIKit
import WebKit
import SideMenu
class AboutUsController: UIViewController, WKNavigationDelegate {
#IBOutlet weak var aboutusWeb: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
guard let url = URL(string: "https://developer.apple.com/swift/") else { return }
let request = URLRequest(url: url)
aboutusWeb.load(request)
}
#IBAction func sideMenubtn(_ sender: Any) {
print("in aboutus")
aboutusWeb.isOpaque = false
aboutusWeb?.backgroundColor = UIColor(white: 1, alpha: 0.9)
}
}
extension AboutUsController : UISideMenuNavigationControllerDelegate {
internal func sideMenuWillDisappear(menu: UISideMenuNavigationController, animated: Bool) {
//*do the color thing*
print("sidemenu disappear")
aboutusWeb?.backgroundColor = UIColor.white
}
}
Please help me to add alpha value to WKWebView and delete that value.
not sure about alpha but can set Transparent background for WKWebView with this code
webView.opaque = false
webView.backgroundColor = UIColor.clearColor()
webView.scrollView.backgroundColor = UIColor.clearColor()

Can't generate PNG file from UIView snapshot

I want to generate a .png file from UIView snapshot but it's always nil. Could you give me a hint what's wrong with my code? I'm running Catalina 10.15.2 with Xcode 11.3 and iOS 13.3.
Here's my code's snippet:
extension UIView {
fileprivate func snapShot(view: UIView) -> UIView {
let snapshot = view.snapshotView(afterScreenUpdates: false)
self.addSubview(snapshot!)
return snapshot!
}
}
class ViewController: UIViewController {
var image: UIImage?
var imageView: UIImageView?
#IBAction func take(_ sender: UIButton) {
let oneThird = CGRect(x: 0,
y: 0,
width: view.frame.size.width / 3,
height: view.frame.size.height / 3)
let snap = view.snapShot(view: self.view)
snap.frame = oneThird
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
let png = snap.largeContentImage?.pngData()
if let pngData = png {
self.image = UIImage(data: pngData)
}
self.imageView = UIImageView(image: self.image)
}
print(self.view.subviews.indices) // 0..<5
print(imageView?.image as Any) // NIL
}
}
Any help appreciated.
Try the following extension:
extension UIView {
func getImageFromCurrentContext(bounds: CGRect? = nil) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(bounds?.size ?? self.bounds.size, false, 0.0)
self.drawHierarchy(in: bounds ?? self.bounds, afterScreenUpdates: true)
guard let currentImage = UIGraphicsGetImageFromCurrentImageContext() else {
return nil
}
UIGraphicsEndImageContext()
return currentImage
}
}
Pass the bounds if you would like 1/3 of the view or don't provide a bounds to get the image of the entire view.
Tested with sample code:
import UIKit
class ViewController: UIViewController {
#IBOutlet private(set) var testView: UIView!
#IBOutlet private(set) var testImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.testImageView.image = self.testView.getImageFromCurrentContext()
}
}
}
I made UIView on the storyboard have a sample label inside it and changed the background color just to verify it is in fact creating the image. Then added an UIImageView under that. Connected the UIView to testView and the UIImageView to testImageView.

IBAction stops working when I connect IBOutlet

I have an IBAction wired up to a button in my storyboard that plays a sound. This works just fine. However, when I wire up an IBOutlet to the same button, the code for the outlet takes over and the IBAction stops working. In this case, the IBOutlet serves the purpose of making the button pulse with animation. Here is my code:
import UIKit
import Firebase
import AVFoundation
class Page1: UIViewController, AVAudioPlayerDelegate, UIAlertViewDelegate {
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var pageControl: UIPageControl!
#IBOutlet weak var testpulse: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "ahh", withExtension: "mp3")
do {
ahh = try AVAudioPlayer(contentsOf: url!)
ahh.prepareToPlay()
}
catch let error as NSError {
print(error.debugDescription)
}
testpulse.isUserInteractionEnabled = true
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(Page1.addPulse))
tapGestureRecognizer.numberOfTapsRequired = 1
testpulse.addGestureRecognizer(tapGestureRecognizer)
}
#objc func addPulse(){
let pulse = Pulsing(numberOfPulses: 1, radius: 110, position: testpulse.center)
pulse.animationDuration = 0.8
pulse.backgroundColor = UIColor.purple.cgColor
self.view.layer.insertSublayer(pulse, below: testpulse.layer)
}
#IBAction func ahh(_ sender: Any) {
ahh.play()
}
}
And for my Swift animation file I have this:
import UIKit
class Pulsing: CALayer {
var animationGroup = CAAnimationGroup()
var initialPulseScale:Float = 0
var nextPulseAfter:TimeInterval = 0
var animationDuration:TimeInterval = 1.5
var radius:CGFloat = 200
var numberOfPulses:Float = Float.infinity
override init(layer: Any) {
super.init(layer: layer)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
init (numberOfPulses:Float = Float.infinity, radius:CGFloat, position:CGPoint) {
super.init()
self.backgroundColor = UIColor.black.cgColor
self.contentsScale = UIScreen.main.scale
self.opacity = 0
self.radius = radius
self.numberOfPulses = numberOfPulses
self.position = position
self.bounds = CGRect(x: 0, y: 0, width: radius * 2, height: radius * 2)
//self.cornerRadius = radius
DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async {
self.setupAnimationGroup()
DispatchQueue.main.async {
self.add(self.animationGroup, forKey: "pulse")
}
}
setupAnimationGroup()
self.add(animationGroup, forKey: "pulse")
}
func createScaleAnimation () -> CABasicAnimation {
let scaleAnimation = CABasicAnimation(keyPath: "transform.scale.xy")
scaleAnimation.fromValue = NSNumber(value: initialPulseScale)
scaleAnimation.toValue = NSNumber(value: 1)
scaleAnimation.duration = animationDuration
return scaleAnimation
}
func createOpacityAnimation() -> CAKeyframeAnimation? {
let opacityAnimation = CAKeyframeAnimation(keyPath: "opacity")
opacityAnimation.duration = animationDuration
opacityAnimation.values = [0.4, 0.8, 0]
opacityAnimation.keyTimes = [0, 0.2, 1]
return opacityAnimation
}
func setupAnimationGroup() {
self.animationGroup = CAAnimationGroup()
self.animationGroup.duration = animationDuration + nextPulseAfter
self.animationGroup.repeatCount = numberOfPulses
let defaultCurve = CAMediaTimingFunction(name: kCAMediaTimingFunctionDefault)
self.animationGroup.timingFunction = defaultCurve
self.animationGroup.animations = [createScaleAnimation(), createOpacityAnimation()!]
}
}
When I connect the IBAction to my button, the sound works. However when I connect the IBOutlet, the animation works but the IBAction doesn't. What could be causing this? It's still connected in the storyboard.
import UIKit
import Firebase
import AVFoundation
class Page1: UIViewController, AVAudioPlayerDelegate, UIAlertViewDelegate {
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var pageControl: UIPageControl!
#IBOutlet weak var testpulse: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "ahh", withExtension: "mp3")
do {
ahh = try AVAudioPlayer(contentsOf: url!)
ahh.prepareToPlay()
}
catch let error as NSError {
print(error.debugDescription)
}
testpulse.isUserInteractionEnabled = true
}
#objc func addPulse(){
let pulse = Pulsing(numberOfPulses: 1, radius: 110, position: testpulse.center)
pulse.animationDuration = 0.8
pulse.backgroundColor = UIColor.purple.cgColor
self.view.layer.insertSublayer(pulse, below: testpulse.layer)
}
#IBAction func ahh(_ sender: Any) {
ahh.play()
addPulse()
}
}