Mac Catalyst - Make window NSToolbar transparent - swift

Problem
Hi All,
I need help to make my window NSToolbar transparent, however, I still need to be able to use a toolbar within the window scene titlebar. Currently, you can set a titlebar to be transparent by either hiding your toolbar or not having one at all, but even though I will not be adding any actual tools within the toolbar, there needs to be one so that I can reposition the window traffic light buttons using the UITitlebarToolbarStyle property - I know that from Electron 8, developers are able to reposition the traffic light buttons (is this also possible in Swift?)
Any help is much appreciated 😊
Current Code
- this is situated within the AppDelegate
guard let windowScene = (scene as? UIWindowScene) else { return }
#if targetEnvironment(macCatalyst)
windowScene.sizeRestrictions?.minimumSize = CGSize(width: 1366 * 0.9, height: 1024 * 0.9)
if let titlebar = windowScene.titlebar {
let customToolbar = NSToolbar()
titlebar.titleVisibility = .hidden
titlebar.toolbar = customToolbar
titlebar.toolbarStyle = .unified
titlebar.autoHidesToolbarInFullScreen = true
}
#endif
window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window?.windowScene = windowScene
window?.makeKeyAndVisible()

Related

How do I create and print an offscreen SwiftUI view on Mac not iPhone

For over a week I have been trying to solve a printing issue in a macOS app I am writing using Swift and SwiftUI.
I need to print a view, which I have done by making it the main window but that does not work for the user. The data can come from a file or directly from user input so could be from 1 to 100 data sets.
Because I am printing the main window the application is unusable during the print process which is not acceptable.
The ideal solution would be to create the view off-screen then print the view. That way the user never sees it other than what comes out of the printer!
I have tried to find out how to print a view that is not the main window - no success, tried creating a second window managed to create the window but not print it!
No point in posting code as no idea which of the several ways I have tried could work, not even sure at this point if what I am trying to do is possible!
Please note this on Mac, not iPhone or iPad!
This worked for me, borrowed from the link in the comment from #Willeke. It involves converting to a bit map for printing.
let printInfo = NSPrintInfo()
let view = ContentView()
let contentRect = NSRect(x: 0, y: 0, width: 1080, height: 720) // these values will vary
let viewToPrint = NSHostingView(rootView: view)
viewToPrint.frame = contentRect
let bitMap = viewToPrint.bitmapImageRepForCachingDisplay(in: contentRect)!
viewToPrint.cacheDisplay(in: contentRect, to: bitMap)
let image = NSImage(size: bitMap.size)
image.addRepresentation(bitMap)
let imageView = NSImageView(frame: contentRect)
imageView.image = image
let printOperation = NSPrintOperation(view: imageView, printInfo: self.printInfo)
printOperation.showsPrintPanel = true
printOperation.showsProgressPanel = true
printOperation.run()

Set window size based on mac screen size using catalyst supported APIs

I am trying to get the application to be the size of the full screen using Catalyst supported APIs. I have tried using the UIScreen proeprty as well as the window property(below), but both have the problem where the window does not fill the full screen.
I have attached my code, but the window does not occupy the full screen size.
let windowRect = self.window?.frame
let windowWidth = windowRect?.size.width
let windowHeight = windowRect?.size.height
UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }.forEach { windowScene in
windowScene.sizeRestrictions?.minimumSize = CGSize(width: windowWidth! , height:windowHeight! )
windowScene.sizeRestrictions?.maximumSize = CGSize(width: windowWidth!, height: windowHeight!)
}

SpriteKit scene deformed after modal presentation swift

Could use some help troubleshooting an issue with a SpriteKit scene.
I have a scene that displays some coins in the main section of the app.
When I present a viewcontroller from the bottom I have no issue. Same for tab bar navigation, no issues.
Here is the view as it should always be displayed.
The issue comes only when I present a viewcontroller from the side.
When the new viewcontroller is dismissed, the scene works, but is distorted.
this is how it is displayed after a viewcontroller is displayed modally and later on dismissed.
EDIT: I forgot to mention that if I swipe vertically on the distorted scene, the distortion is fixed and all is good.
Here is some of the code in viewDidAppear of the viewcontroller.
Thanks for the help.
EDIT 2:
I just tested the app on a iPhone 5 using iOS 10 and the issue doesn't happen. Any chance this might be iOS 11 related?
func configureScene(_ completion: () -> Void) {
defer { completion() }
guard wScene == nil else { return }
let skView = SKView(frame: self.view.frame)
skView.isUserInteractionEnabled = false
skView.backgroundColor = .clear
wScene = WScene(size: view.frame.size)
wScene.backgroundColor = .clear
skView.presentScene(wScene)
view.insertSubview(skView, belowSubview: collectionView)
if let buttonsObstacle = doubleButton?.buttonsView {
let obstacleSize = CGSize.init(width: buttonsObstacle.frame.width, height: buttonsObstacle.frame.height)
obstacle = SKSpriteNode.init(color: .clear, size: obstacleSize)
guard let obstacle = obstacle else { return }
obstacle.name = WScene.obstacleNodeName
let convertedOrigin = view.convert(buttonsObstacle.center, from: buttonsObstacle.superview)
let skConvertedOrigin = skView.convert(convertedOrigin, to: wScene)
obstacle.position = skConvertedOrigin
obstacle.physicsBody = SKPhysicsBody(rectangleOf: obstacleSize)
obstacle.physicsBody?.allowsRotation = false
obstacle.physicsBody?.isDynamic = false
source.scrollHandler = { [weak self] (scrollView) in
guard let strongSelf = self else { return }
strongSelf.buttonsMoved(inView: skView, withScroll: scrollView)
}
wScene.addChild(obstacle)
presenter.loadData()
}
}
I solved my issue.
It was related to the new iOS 11 adjustedContentInset property.
My Coin SK scene was being moved by the scroll handler when the view appeared after a modal transition.
My solution is to disable the scrolling for the first 0.1 second after the view appears. In this way iOS 11 doesn't touch the coins anymore while users are able to scroll correctly because they interact with the view most of the time after at least 0.1 seconds.

Unable to make a button that will transition you to main menu with Spritekit Swift

I'm new to Swift and Spritekit and having trouble with implementing a button or imagebutton that will take you to the main menu from the GameScene. All I want to do is to make a button that will display a dialog that will tell you if you want to return to the main menu.
For example is there a way to make a dialog that will transition you to other scenes with the code below?
let skview = self.view as! GameSKView!
skview.score = score
let scene = MainMenuScene(size: self.size)
let tr = SKTransition.revealWithDirection(SKTransitionDirection.Down, duration: 1)
scene.scaleMode = SKSceneScaleMode.AspectFill
skview.presentScene(scene,transition: tr)
try this
func changeScene() {
let newScene = MainMenuScene(size: self.size)
let theTransition = SKTransition.revealWithDirection(SKTransitionDirection.Down, duration: 1)
newScene.scaleMode = .AspectFill
scene?.view?.presentScene(newScene, transition: theTransition)
}
Currently developing a button that works like a uibutton using spritekit. Here is what I have, it may be slightly overkill for what you want but here it is.https://github.com/marcJV/SKAToolKit/tree/swift?files=1
It will be pulled over to SKAToolKit when as we are porting it to swift. There is also an example project showing off how to use it. Also there is a lack of a proper readme at this point, but the example should have everything you need. This is using swift 2.0

Problems trying to create blurred background for modal view

I am trying to show a view modally. The view is shown as a "Cross Dissolve" "over full screen". I am passing the screen shot to the controller. I am then trying to crop the screenshot and retain only the part that would be under the view. This i am blurring and adding to the view.
The code works as far as blurring goes, but i have two problems.
1) The image is at double scale, which will be something to do with retina display, but i am never sure how to fix that.
2) the other is that, having tried everything I can think of, i cannot get the coordinate of the "canvas" in a coordinate system that helps me correctly crop the view.
I'd really appreciate help with this
thanks
karl
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let window = appDelegate.window!
let splitViewController = window.rootViewController as! UISplitViewController;
let cropFrame = UIView().convertRect(self.canvas.frame, toView: splitViewController.view)
let croppedScreenShotCG = CGImageCreateWithImageInRect(screenShot?.CGImage, cropFrame)
let croppedScreenShot = UIImage(CGImage:croppedScreenShotCG)
var blurEffect = UIBlurEffect(style: UIBlurEffectStyle.Light)
var blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = CGRectMake(0, 0, self.canvas.frame.width, self.canvas.frame.height)
let blurImageView = UIImageView(image:croppedScreenShot)
blurImageView.addSubview(blurEffectView)
let blurColorCast = UIView(frame: CGRectMake(0, 0, self.canvas.frame.width, self.canvas.frame.height))
blurColorCast.backgroundColor = UIColor.cloverColor10pc()
blurColorCast.alpha = 0.2
blurImageView.addSubview(blurColorCast)
self.canvas.addSubview(blurImageView)
self.canvas.sendSubviewToBack(blurImageView)
UIImageWriteToSavedPhotosAlbum(croppedScreenShot, nil, nil, nil)
}
I am getting the screen shot like this:
let layer = window.layer
let scale = UIScreen.mainScreen().scale
UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale);
layer.renderInContext(UIGraphicsGetCurrentContext())
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
Instead of using UIImage's CGImage: you can use imageWithCGImage:scale:orientation: which takes a scale parameter to account for retina screens.
See: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImage_Class/#//apple_ref/occ/clm/UIImage/imageWithCGImage:scale:orientation:
But personally I prefer to avoid doing anything in code, if there's a reasonable way to do it with storyboards.
Here's an example project that has a blur effect for the back of a modal presentation that doesn't use any code at all.
The only thing worth noting is that for the view controller that's being presented, the root view background color is set to clear (otherwise the view controller that's presenting it would be obscured).