Use HotKey Library in SwiftUI - swiftui

I'm trying to use this library: soffes/HotKey in an SwiftUI Application for MacOS.
The author describes the usage as follows:
Set up Hotkey:
let hotKey = HotKey(key: .r, modifiers: [.command, .option])
set the keyDownHandler and get callbacks for when your hot key is pressed:
hotKey.keyDownHandler = {
print("Pressed at \(Date())")
}
My problem is that I don't know where I have to put the Handler. Any Ideas?

I ran into this same problem; I was initializing a hotkey inside my appDelegate's applicationDidFinishLaunching function. I had it declared locally and I think it was getting garbage collected.
The fix for me was to make a hotKey property on my appDelegate (although I'm sure you could do the same on any root view or scene if you aren't using an appDelegate) and assign my hotKey to it:
class AppDelegate: NSObject, NSApplicationDelegate {
var hotKey: HotKey?
func applicationDidFinishLaunching(_ aNotification: Notification) {
let hotKey = HotKey(key: .six, modifiers: [.command, .option])
hotKey.keyDownHandler = {
print("Got hotkey at \(Date())")
}
self.hotKey = hotKey
}
}

Okay so I figured it out.
The keyDownHandlerreally just defines what should happen when a hotkey is pressed so you can just put it into the .onAppear {} after your body View

Related

lottie animation causing app crash on device

I am using Lottie to display animations in application and I tried to use this animation
AnimationURL
LottieView -
struct LottieView: UIViewRepresentable {
var animationName: String
func makeUIView(context: UIViewRepresentableContext<LottieView>) -> UIView {
let view = UIView()
return view
}
func updateUIView(_ uiView: UIViewType, context: Context) {
let animationView = AnimationView()
let animation = Animation.named(animationName)
animationView.animation = animation
animationView.contentMode = .scaleAspectFit
animationView.backgroundBehavior = .pauseAndRestore
animationView.loopMode = .loop
animationView.translatesAutoresizingMaskIntoConstraints = false
uiView.addSubview(animationView)
NSLayoutConstraint.activate([
animationView.heightAnchor.constraint(equalTo: uiView.heightAnchor),
animationView.widthAnchor.constraint(equalTo: uiView.widthAnchor)
])
animationView.play()
}
}
But when I want to display animation, application crashes in AnimatorNode file from Lottie library in this function (Thread 1: EXC_BAD_ACCESS (code=2, address=0x16ce6bff0)):
func updateContents(_ frame: CGFloat, forceLocalUpdate: Bool) -> Bool {
guard isEnabled else {
return parentNode?.updateContents(frame, forceLocalUpdate: forceLocalUpdate) ?? false
}
}
When I opened View Hierarchy after app crash, I received this log -
Failed to unarchive request data with error: Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set. around line 1, column 0." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set. around line 1, column 0., NSJSONSerializationErrorIndex=0}
On simulator, animation is running normally, but when I build application on device, application is crashing on this animation. Is there any way to fix this and use this animation?
We ran into the same issue.
It doesn't depend on SwiftUI / UIKit thing.
On Simulator it works ok because your simulator has more memory than iPhone does. So maybe your animation.json is too hard for current version of Lottie-ios lib. Maybe its good idea to report them, that they should update implementation of lib on iOS side.
Thank you!

present SwiftUI view from a SKScene

Is it possible to present a SwiftUI view from a SpriteKit scene?
I have various sprites in the game scene. When certain one receive touch data I want a SwiftUI view to pop up.
In the past I have used something like this to present another UI view.
if bloqsLogo.contains(location) {
if instructionsOn == false {
let pop = InstructionsPopUp()
pop.tag = 104
self.view?.addSubview(pop)
instructionsOn = true
} else
if instructionsOn == true {
if let viewWithTag = self.view!.viewWithTag(104) {
viewWithTag.removeFromSuperview()
instructionsOn = false
}else{
print("nah")
}
}
}
My SKScene is an instance of another SwiftUI view and presented there. A good part of my GUI is done in SwiftUI. I am basically wanting to code as much of my App as I can in SwiftUI while keeping the physics and sprites in a SKScene. All of which is going rather well besides this!

SwiftUI changing environment object re-created observed object in same view

So, I have few steps, last one contains EnvironmentObject and ObservedObject. The issue is, when I try to modify EnvironmentObject (lane 68) it re-creates ObservedObject.
Can any one explain me why this happens? Any solution to keep my ObservedObject with original state?
As far as I know it possible to change ObservedObject to StateObject, but I am using iOS 13+ so... I need other solution.
Line 47 - body is reevaluated so new instance of ObservedStuff is created, so make it as property and pass it in, like
struct TestView_A: View {
...
private let model = ObservedStuff()
var body: some View {
NavigationLink(destination: TestView_B(viewModel: self.model) ...
}
}

SwiftUI TextField freezes when deleting first character

When specifying a minimumScaleFactor for a TextField in SwiftUI the TextField behaves normally while you enter text and reduces the font as specified when the content does not fit the TextView. However, if you start deleting characters everything works as usual until you delete the first character. Everything freezes.
At the beginning I though it was something in the way I was handling the variable that stores the text that in my application I have it as an ObservedObject. However, after debugging the frozen app I noticed that the code was circling around the drawing of the TextField over and over, function after function everything pointed to an error in the drawing of the object on the screen.
The following code illustrates the issue. The TextField works perfectly when you enter characters and delete them until you get to the first one. The it freezes.
import SwiftUI
struct ContentView: View {
#State var sensorNumber: String = ""
var body: some View {
TextField("WC0.000.000.000", text: $sensorNumber)
.padding(.all, 5.0)
.font(Font.custom("Helvetica", size:40.0))
.minimumScaleFactor(0.90)
}
}
The problem seems to be related to the interaction of the Custom Font. Obviously, my application is using custom fonts but here I just wanted to simplify the code.
This code does not fail if you don't use a custom font or if you don't specify a minimumScaleFactor. I have found a workaround that is not very elegant but it works until Apple fixes this bug:
import SwiftUI
struct ContentView: View {
#State var sensorNumber: String = ""
var body: some View {
TextField("WC0.000.000.000", text: $sensorNumber)
.padding(.all, 5.0)
.font(Font.custom("Helvetica", size:40.0))
.minimumScaleFactor(sensorNumber.count < 2 ? 1.0 : 0.90)
}
}
I am submitting a radar to Apple but looking for a better solution for the problem here.

Creating Hashtags in swift

I am new to swift. I am trying to create a view where you can create hashtags. There is a UITextfield in which you type the word to be converted. On press of 'enter' or '#', it should automatically convert to hashtags and display in labels which are further stored in an array format.
I tried many tutorials but none of them seem to work.
UITextField's have a delegate that is pretty handy.
A really simple implementation would be to use the textFieldShouldReturn delegate method, you can use this to detect when the return button is pressed.
Tell your view controller that it is going to adopt the protocol like this:
class ViewController:UIViewController, UITextFieldDelegate {
...
Then tell your textfield where to delegate it's events, if you are making the textfield inside the view controller then use self to reference the view controller like this:
let textField = UITextField()
textField.delegate = self // IMPORTANT
self.view.addSubView(textField)
Then inside your view controller implement the textFieldShouldReturn method like so:
class ViewController:UIViewController, UITextFieldDelegate {
...
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if let text = textField.text {
let hashtag = "#\(text)"
print("New hashtag is \(hashtag)")
}
return true // allows the default behaviour of return button, you can return false if you want the keyboard to remain on screen.
}
}
This solution does not account for the user entering more than one hashtag, nor does it remove white space etc.. you may need to think about formatting/validating this string before it is useable.
You may also want to consider looking at other existing questions that cover things like splitting strings and creating arrays.