Preview is not changing in SwiftUI - ios

I explicitely specified device name in preview provider but it is not changing the device in preview editor.
struct ContentView: View {
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world!")
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.previewDevice(PreviewDevice(rawValue: "iPhone 11"))
}
}

Have you downloaded the iPhone 11 simulator into your project? If it's not available in the device selection, it won't display by just setting the device in code. You need to have the simulator device installed as well.

Related

View background stretches over the safe area when using GeomtryReader

When having a view inside a GeomtryReader and setting the background to a color. It ignores the vertical safe area and stretches beyond it. Only when the view is at the vertical edges.
It doesn't only happen on Preview, it happens on actual device as well.
I am not sure if this is a bug or a normal behaviour of SwiftUI if so what am I doing wrong?
I have a very simple view that you can test with as follows:
import SwiftUI
struct TestView: View {
var body: some View {
GeometryReader { reader in
Text("TEST")
.background(Color.red)
}
}
}
struct TestView_Previews: PreviewProvider {
static var previews: some View {
TestView()
}
}
You can add it in a VStack and add a Spacer and you will see the same behaviour when it is at the bottom.
import SwiftUI
struct TestView: View {
var body: some View {
GeometryReader { reader in
VStack {
Spacer()
Text("TEST")
.background(Color.red)
}
}
}
}
struct TestView_Previews: PreviewProvider {
static var previews: some View {
TestView()
}
}
I can clip it by adding .clipped() to the Text and it will be removed but this sounds like a work around to me.
I stepped away from SwiftUI for a while so I do not remember if this is a normal behaviour or not. I did some research but couldn't find anything related to this.
I am using XCode 14.2 (14C18) and Swift swift-driver version: 1.62.15 Apple Swift version 5.7.2 (swiftlang-5.7.2.135.5 clang-1400.0.29.51)

SwiftUI: custom Font on MacOS

Goal: use a custom Font on SwiftUI, targeting MacOS.
Problem: On iOS, custom Font works fine in SwiftUI:
But on MacOS, it doesn't:
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world!")
.font(Font.custom("SourceCodePro-ExtraLight", size: 40))
Text("Hello, world!")
.font(Font.custom("LobsterTwo", size: 40))
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Tried: I made sure that both fonts are added to Info tab on corresponding iOS and MacOs targets:
Seems to be a problem with SwiftUI using UIFont under the hood, and a special NSFont would be needed...
Any help is much appreciated!
Solved by adding this line to the plist file, and a "." as the value

NavigationBar not showing when going to another tab in tabview

In my app when I navigate to another tab and scroll down the view and gets cut off and the navigation bar doesn't collapse as shown here:
I tried to put .edgesIgnoringSafeArea(.top) but then this happens:
When I press the home button the simulator and navigate back to the app the navigation bar will collapse when scrolling as intended. Is this a bug with Xcode? Currently I'm using XCode 11.4.1, testing on an iPhone 11 Pro Max simulator but the exact same result occurs on my physical iPhone 6s Plus.
EDIT: The code for the tab view is as follows:
import SwiftUI
struct MenuScreen: View {
#State private var selection = 0
var body: some View {
TabView(selection: $selection){
ItemsTab().tabItem{
Image(systemName: "phone.fill")
Text("Items")
}.tag(0)
TestTab().tabItem{
Image(systemName: "phone.fill")
Text("Test")
}.tag(1)
}
.navigationBarTitle("Menu")
// .edgesIgnoringSafeArea(.top)
.navigationBarItems(trailing: NavigationLink(destination:ProfileScreen()){Text("Profile")})
// .padding(.top,1)
.navigationViewStyle(DefaultNavigationViewStyle())
// .navigationBarHidden(true)
}
}
struct MenuScreen_Previews: PreviewProvider {
static var previews: some View {
MenuScreen()
}
}
The navigation view is wrapped inside a splash screen like so:
import SwiftUI
struct SplashScreen: View {
#State private var isActive = false
let content = ContentView()
var body: some View {
NavigationView{
VStack{
Text("Loading")
LoopingAnimation()
NavigationLink(destination: content,isActive: $isActive,label: {EmptyView()})
}.onAppear(perform: {
self.goToContentView(time:2.5)
}).navigationBarTitle("My app")
}
}
func goToContentView(time:Double){
DispatchQueue.main.asyncAfter(deadline: .now() + Double(time)){
self.isActive = true
}
}
}
struct SplashScreen_Previews: PreviewProvider {
static var previews: some View {
SplashScreen()
}
}
EDIT 2: I tried to put navigation views inside the tabview as shown here:
import SwiftUI
struct MenuScreen: View {
var body: some View {
TabView{
NavigationView{
ItemsTab().navigationBarTitle("Items")
}.tabItem{
Image(systemName: "house.fill")
Text("Items")
}
NavigationView{
TestTab().navigationBarTitle("Test")
}.tabItem{
Image(systemName: "phone.fill")
Text("Test")
}
}
.navigationBarHidden(true)
// .navigationBarBackButtonHidden(true)
.frame(alignment: .center)
// .edgesIgnoringSafeArea(.top)
.navigationBarItems(trailing: NavigationLink(destination:ProfileScreen()){Text("Profile")})
// .padding(.top)
.navigationViewStyle(DefaultNavigationViewStyle())
}
}
struct MenuScreen_Previews: PreviewProvider {
static var previews: some View {
MenuScreen()
}
}
But while it resulted in a collapsing navigation bar that worked even switching tabs the result looked like this:
Made the navigation bar stay collapsed in the tab screen similar to what happens when you navigate to other categories within a tab in the app store by setting .displayMode inside .navigationBarTitle to .inline
Screenshot:

iOS SwiftUI: NavigationLink in macOS simulator does not work

The Problem:
The NavigationLinks in the macOS version of the SwiftUI app don't work properly.
In my case is a MasterDetailNavigationView.
What I've tried
I have the problem running the app with the macOS simulator, and also running the archived application.
I still have the problem with a brand new project with the sample code below:
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
VStack(alignment: .center, spacing: 10) {
NavigationLink(destination: Text("View One")) {
Text("ONE")
}
NavigationLink(destination: Text("View Two")) {
Text("TWO")
}
Spacer()
}
Text("Hello, World!")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
How to reproduce the problem:
Copy and paste the above code in a new SwiftUI project. Enable the macOS tick the the target settings. And the run on the macOS emulator.
Versions:
macOS: 10.15.4 (19E266)
Xcode: 11.4 (11E146)

SwiftUI: unwanted split view on iPad

Problem: a view on Pad shows up with unwanted split view.
My current setup is:
Catalina OSX beta 5 +
Xcode 11 Beta 5
Here is the code I used, with a Navigation View and a Navigation Title:
import SwiftUI
struct SwiftUIView: View {
var body: some View {
NavigationView {
Text("Search")
.navigationBarTitle(Text("Search"))
}
}
}
#if DEBUG
struct SwiftUIView_Previews: PreviewProvider {
static var previews: some View {
SwiftUIView()
}
}
#endif
When simulated on iPad (both physical device and preview) instead of a full screen view, I get this split screen view:
If I have just a view, with no NavigationView, I get a full screen view:
import SwiftUI
struct SwiftUIView: View {
var body: some View {
Text("Hello World!")
}
}
#if DEBUG
struct SwiftUIView_Previews: PreviewProvider {
static var previews: some View {
SwiftUIView()
}
}
#endif
How can I make a NavigationView full screen (not split screen) on iPad?
Update July 2022
Using NavigationStack instead of NavigationView should display as the main view as you would expect on iPad:
NavigationStack {
Text("Hello world!")
}
*In newer versions, the navigationViewStyle modifier has been deprecated.
Original answer:
You can apply the .navigationViewStyle(.stack) modifier to the NavigationView.
...
NavigationView {
Text("Hello world!")
}
.navigationViewStyle(.stack)
...
Edit: Below, I am answering Alexandre's questions from his comment:
Why full view is not the default for iPad? That's just a choice made by Apple...
Why this modifier goes outside of NavigationView closure, while the Navigation Title goes inside... Maybe this gives clarification: https://stackoverflow.com/a/57400873/11432719
To use this split style for iPad but remove for iPhone:
extension View{
func phoneOnlyStackNavigationView() ->some View {
if UIDevice.current.userInterfaceIdiom == .phone{
return AnyView(self.navigationViewStyle(StackNavigationViewStyle()))
} else {
return AnyView(self)
}
}
}

Resources