I am trying to use the NSVisualEffectView in my project with SwiftUI. This is how I imported it:
struct VisualEffectView: NSViewRepresentable {
func makeNSView(context: Context) -> NSVisualEffectView {
let view = NSVisualEffectView()
view.blendingMode = .withinWindow
view.isEmphasized = true
view.material = .sidebar
return view
}
func updateNSView(_ nsView: NSVisualEffectView, context: Context) {
}
}
Then this is how I am using it
var body: some View {
ZStack {
Image("someImage")
SomeText()
.background(VisualEffectView())
}
}
Eventually, it showed up on the screen as a box grey box without translucent or blur. Anyone know what I am missing from the example above? Thank you for your help
Related
I'm reworking my app for SwiftUI 2.0 but have come across a problem when replicating what I could do with AppDelegate.
I'm using NSViewRepresentable to get access to NSWindow so I can remove the titlebar of the window (I know it's not in the guidelines but this will never be submitted). When removing .titled from styleMask, the app crashes.
struct WindowAccessor: NSViewRepresentable {
#Binding var window: NSWindow?
func makeNSView(context: Context) -> NSView {
let view = NSView()
DispatchQueue.main.async {
self.window = view.window
self.window?.isOpaque = false
self.window?.titlebarAppearsTransparent = true
self.window?.backgroundColor = NSColor.clear
self.window?.styleMask = [.fullSizeContentView]
self.window?.isMovableByWindowBackground = true
self.window?.backingType = .buffered
}
return view
}
func updateNSView(_ nsView: NSView, context: Context) {}
}
#main
struct MyApp_App: App {
#State private var window: NSWindow?
var body: some Scene {
WindowGroup {
ContentView().background(WindowAccessor(window: $window))
}
}
}
struct ContentView: View {
var body: some View {
Text("Hello, world!").padding().background(Color(NSColor.windowBackgroundColor))
}
}
When I run the app I get Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
All I'm trying to achieve with my app is a Menu Bar application that looks exactly like Spotlight. No dock icon, no title bar, all preferences to be handled by a popover or another window.
EDIT:
Is this something to do with the canBecomeKey property?
I am writing a small App for the Mac..
I need to disable to (Green Button) for full screen.
I am using SwiftUI App not AppKit App Delegate
Cant find how to disable the Full Screen Button for my app.
Any thoughts?
Because no one answered with a cleaner SwiftUI only version:
struct ContentView: View {
var body: some View {
HostingWindowFinder { window in
window?.standardWindowButton(.zoomButton)?.isHidden = true //this removes the green zoom button
}
Text("Hello world")
}
}
struct HostingWindowFinder: NSViewRepresentable {
var callback: (NSWindow?) -> ()
func makeNSView(context: Self.Context) -> NSView {
let view = NSView()
DispatchQueue.main.async { [weak view] in
self.callback(view?.window)
}
return view
}
func updateNSView(_ nsView: NSView, context: Context) {}
}
HostingWindowFinder concept taken from https://lostmoa.com/blog/ReadingTheCurrentWindowInANewSwiftUILifecycleApp/
I'm using a 3rd party library developed with UIKit. It's API needs a reference to a UIView.
How can I use this library inside SwiftUI? And how can I convert a SwiftUI view to a UIView?
I've tried creating a UIViewRepresentable like this:
struct SomeView: UIViewRepresentable {
let contentViewController: UIViewController
init<Content: View>(contentView: Content) {
self.contentViewController = UIHostingController(rootView: contentView)
}
func makeUIView(context: Context) -> UIKitView {
// Whatever I do here doesn't work. Frame is always 0
contentViewController.loadViewIfNeeded()
contentViewController.view.setNeedsDisplay()
contentViewController.view.layoutIfNeeded()
print(contentViewController.view.frame)
let uikitView = UIKitView()
uikitView.show(contentViewController.view)
return popover
}
func updateUIView(_ uiView: UIKitView, context: Context) {
}
}
I hope I'm wrong, but I have not been able to find a SwiftUI equivalent to an editable
UITextView. So, I built one using UIViewRepresentable. Populating both a SwiftUI Text
and my own view with the ObservableObject works - but updates made in my view are
not propagated to the ObservableObject. I must be missing something important with
the Binding concept. Any guidance would be appreciated.
import SwiftUI
import Combine
struct ContentView: View {
#ObservedObject var myOText: MyOText
var body: some View {
ScrollView {
VStack {
Text("This is a bound Text View")
.padding(.top, 10)
.font(.headline)
Text(myOText.inTheCourse)
.lineLimit(3)
.padding()
Text("This is a multi-line UITextView wrapper:")
.font(.headline)
MultilineTextView(myOText: myOText)
.frame(height: 100)
.padding()
Spacer()
}
}
}
}
struct MultilineTextView: UIViewRepresentable {
#ObservedObject var myOText: MyOText
func makeUIView(context: Context) -> UITextView {
let view = UITextView()
view.isScrollEnabled = true
view.isEditable = true
view.isUserInteractionEnabled = true
view.textAlignment = .center
view.font = UIFont(name: "Times New Roman", size: 20)
return view
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.text = myOText.inTheCourse
}
}
class MyOText: ObservableObject {
#Published var inTheCourse: String = "When in the Course of human events, it becomes necessary for one people to dissolve the political bands which have connected them ..."
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(myOText: MyOText())
}
}
Xcode Version 11.2 beta 2 (11B44), iOS 13.
Your multiline text view needs a coordinator to observe the text updates from UITextView
struct MultilineTextView: UIViewRepresentable {
#ObservedObject var myOText: MyOText
func makeUIView(context: Context) -> UITextView {
let view = UITextView()
view.isScrollEnabled = true
view.isEditable = true
view.isUserInteractionEnabled = true
view.textAlignment = .center
view.font = UIFont(name: "Times New Roman", size: 20)
view.delegate = context.coordinator
return view
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.text = myOText.inTheCourse
}
func makeCoordinator() -> MultilineTextView.Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UITextViewDelegate {
var control: MultilineTextView
init(_ control: MultilineTextView) {
self.control = control
}
func textViewDidChange(_ textView: UITextView) {
control.myOText.inTheCourse = textView.text
}
}
}
When I create a view in SwiftUI and render it in an Xcode preview, using PreviewLayout.sizeThatFits, the preview adjusts its size according to its content. When I import a UIKIt view using UIViewRepresentable, it appears with a full device-size frame.
Is there a way to make SwiftUI respect the intrinsicContentSize of UIView subclasses?
struct Label: UIViewRepresentable {
func makeUIView(context: UIViewRepresentableContext<Label>) -> UILabel {
return UILabel()
}
func updateUIView(_ uiView: UILabel, context: UIViewRepresentableContext<Label>) {
uiView.text = "Some text"
}
}
#if DEBUG
struct Label_Previews: PreviewProvider {
static var previews: some View {
Group {
Label().previewLayout(.sizeThatFits)
}
}
}
#endif
Add the following to your updateUIView function:
uiView.setContentHuggingPriority(.defaultHigh, for: .vertical)
uiView.setContentHuggingPriority(.defaultHigh, for: .horizontal)
You can also limit the UIViewRepresentable size from the SwiftUI side.
For this you can use fixedSize:
struct Label_Previews: PreviewProvider {
static var previews: some View {
Label()
.fixedSize()
.previewLayout(.sizeThatFits)
}
}
You can also fix the view size in one dimension only:
.fixedSize(horizontal: false, vertical: true)