Setup: a SwiftUI List with NavigationLinks wrapped in a NavigationView. Tapping on the NavigationLink opens DeviceInfoView only 50% of the time. Environment: Simulator 13.2, Xcode 13.2.1. All works fine on a real device. Any insights? Thanks.
struct DeviceSearchView: View {
#StateObject private var viewModel = DeviceSearchViewModel()
var body: some View {
NavigationView {
Group {
switch viewModel.searchResults {
// ...
case let .success(results):
List(results, id: \.imei) { res in
NavigationLink(destination: DeviceInfoView(imei: res.imei)) {
Text("IMEI: \(res.imei)")
}
}
.listStyle(.insetGrouped)
.navigationTitle("Title")
}
}
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
HStack {
Image(systemName: "cpu")
Text("...").font(.headline)
}
}
}
.searchable(text: $viewModel.searchText, prompt: "IMEI").keyboardType(.numberPad)
}
}
}
...and in the viewModel:
#MainActor
final class DeviceSearchViewModel: ObservableObject {
#Published var searchResults: AsyncResult<[FindySearchResult]> = .empty
// etc...
Simulator -> Device -> Erase all content and settings... fixed it.
Related
I am consistently coming across this issue whenever I use .navigationBarTitleDisplayMode(.inline). Is there a problematic use of this method, or is there something incorrect about my code ?
How to reproduce error:
In the preview, hit the "list.bullet.rectangle.fill" and dismiss the dialog. Do it a second time and now Xcode crashes the Preview.
Xcode Version 14.2 (14C18)
import SwiftUI
struct PDFTableContentsView: View {
var body: some View {
Text("PDF Table Contents View")
.bold()
.underline()
}
}
struct PDFContentView: View {
#State private var showContents: Bool = false
var body: some View {
VStack {
Text(/*#START_MENU_TOKEN#*/"Hello, World!"/*#END_MENU_TOKEN#*/)
}
.navigationTitle("PDF Title")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button {
showContents.toggle()
} label: {
Image(systemName: "list.bullet.rectangle.fill")
}
}
}
.sheet(isPresented: $showContents) {
PDFTableContentsView()
}
}
}
struct PDFContentView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
PDFContentView()
}
}
}
Hello SO community 👋🏼
I'm trying to recreate NavigationBar from Contact tab Apple's Phone in my SwiftUI app.
I played around with .toolbar and modifications but really can't recreate it. I wanna replace TextField to SegmentPicker with saving all behavior of .navigationBarTitleDisplayMode(.inline). But don't know is it possible to use SwiftUI only to get it or need to dive into UIKit. I'm not the expert of UIKit and I will be glad for any help. I want use this NavBar in a exact screen in the app and if possible do not change my preferences of NavBar on other part of app. My code:
import SwiftUI
struct NavBar: View {
#State var pickerOptions: Int = 0
var body: some View {
NavigationView {
ScrollView(.vertical) {
VStack {
Text("Hello, World!")
}
}
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
SegmentPicker
}
ToolbarItem(placement: .navigationBarTrailing) {
Image(systemName: "plus")
}
ToolbarItem(placement: .navigationBarLeading) {
Text("Groups")
}
}
}
}
private var SegmentPicker: some View {
VStack {
Text("Contacts").font(.body.weight(.semibold))
Picker("Options", selection: $pickerOptions) {
Text("Cons").tag(0)
Text("Prons").tag(1)
}
.pickerStyle(.segmented)
.frame(width: 200)
}
}
}
In my app I add/remove a subview to/from a TabView based on some condition. I'd like to animate tab item addition/removal in tab bar. My experiment (see code below) shows it's not working. I read on the net that TabView support for animation is quite limited and some people rolled their own implementation. But just in case, is it possible to implement it?
import SwiftUI
struct ContentView: View {
#State var showBoth: Bool = false
var body: some View {
TabView {
Button("Test") {
withAnimation {
showBoth.toggle()
}
}
.tabItem {
Label("1", systemImage: "1.circle")
}
if showBoth {
Text("2")
.tabItem {
Label("2", systemImage: "2.circle")
}
.transition(.slide)
}
}
}
}
Note: moving transition() call to the Label passed to tabItem() doesn't work either.
As commented Apple wants the TabBar to stay unchanged throughout the App.
But you can simply implement your own Tabbar with full control:
struct ContentView: View {
#State private var currentTab = "One"
#State var showBoth: Bool = false
var body: some View {
VStack {
TabView(selection: $currentTab) {
// Tab 1.
VStack {
Button("Toggle 2. Tab") {
withAnimation {
showBoth.toggle()
}
}
} .tag("One")
// Tab 2.
VStack {
Text("Two")
} .tag("Two")
}
// custom Tabbar buttons
Divider()
HStack {
OwnTabBarButton("One", imageName: "1.circle")
if showBoth {
OwnTabBarButton("Two", imageName: "2.circle")
.transition(.scale)
}
}
}
}
func OwnTabBarButton(_ label: String, imageName: String) -> some View {
Button {
currentTab = label
} label: {
VStack {
Image(systemName: imageName)
Text(label)
}
}
.padding([.horizontal,.top])
}
}
Here is the full example:
import SwiftUI
struct ContentView: View {
var body: some View {
ScrollView {
HStack {
ForEach(1...3, id: \.self) { idx in
TextField("", text: .constant("text \(idx)"))
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Xcode version: 11.5
When I am resizing window app crashes with the following exception:
Assertion failure in -[_TtC7SwiftUIP33_A874FC5B9DB530D4375C25AE2AA39DF215HostingClipView setBoundsOrigin:], /AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-1894.40.150/AppKit.subproj/NSView.m:5646
Am I doing something wrong?
Update:
When I change number of TextFields to 4 resizing works fine.
Here is workaround. Fixed variant tested with Xcode 11.4 / macOS 10.15.4
struct CrashedContentView: View {
var body: some View {
GeometryReader { gp in
ScrollView {
HStack {
ForEach(1...3, id: \.self) { idx in
TextField("", text: .constant("text \(idx)"))
}
}.frame(width: gp.size.width)
}
}
}
}
I'm trying to create NavigationLink in MacBook touchBar with help of SwiftUI. Actually with my piece of code, the button is shown in touchbar, but unfortunately the link doesn't work.
NavigationView {
.touchBar {
NavigationLink(destination: BookView()) {
Text("GoToBook")
}
}
}
struct BookView: View {
var body: some View {
Text("Hello")
}
}
Try instead with Button in touchBar activating NavigationLink programmatically, like below
#State private var isActive = false
...
// below in body
NavigationView {
SomeView() // << your view here
.background(NavigationLink(destination: BookView(), isActive: $isActive) {
EmptyView()
} // hidden link
)
.touchBar {
Button("GoToBook") { self.isActive.toggle() } // activate link
}
}