Provide views, controls, and layout structures for declaring your app's user interface using SwiftUI.

SwiftUI Documentation

Posts under SwiftUI tag

2,392 Posts
Sort by:
Post marked as solved
3 Replies
468 Views
Hey guys I'm trying to follow along with the WWDC session titled "What's new with SwiftUI". They say it's possible to have the detail view of a NavigationSplitView be determined based on a state variable by using the following code: However, and I'm kinda going crazy here, this code does NOT work on iOS whatsoever, the view will remain the one determined by "default" Switch case. It works fine on macOS, but iOS (and iPadOS) simply will not change the detail view no matter what. I have tried working around it for hours but it seems to boil down to the view never being redrawn... has anyone tried this? Is this just a iOS bug??
Posted Last updated
.
Post marked as solved
1 Replies
60 Views
I don't know how to make this function to return base64encoded string of thumbnail in jpeg format.     let request = QLThumbnailGenerator         .Request(fileAt: fileURL, size: size, scale: scale,                  representationTypes: .lowQualityThumbnail)     QLThumbnailGenerator.shared.generateRepresentations(for: request)     { (thumbnail, type, error) in         DispatchQueue.main.async {             if thumbnail == nil || error != nil {                 // Handle the error case gracefully.             } else {                 // return the thumbnail as bas64 string. return ...             }         }     } }
Posted
by Rauli.
Last updated
.
Post not yet marked as solved
7 Replies
4.4k Views
I'm trying to introduce a very simple NavigationView that contains a view and has a .navigationTitle() modifier. import SwiftUI struct LandingPageView: View {   var body: some View {     NavigationView {       Text("Hello")         .navigationTitle("Hello World")     }   }       struct LandingPageView_Previews: PreviewProvider {     static var previews: some View {       LandingPageView()     }   } } I would expect the Text View to be created with Hello World as the title for that view. This is what I see, but with the following error: 2021-02-08 13:59:22.635449+0000 SupplyLine[63126:3757074] [LayoutConstraints] Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want.  Try this:  (1) look at each constraint and try to figure out which you don't expect;  (2) find the code that added the unwanted constraint or constraints and fix it.  (   "<NSLayoutConstraint:0x6000019a7390 'BIBTrailingCBLeading' H:[UIModernBarButton:0x7f8e15616be0]-(6)-[UIModernBarButton:0x7f8e15614460'Hello World']  (active)>",   "<NSLayoutConstraint:0x6000019a73e0 'CBTrailingTrailing' UIModernBarButton:0x7f8e15614460'Hello World'.trailing <= UIButtonBarButton:0x7f8e15613a90.trailing  (active)>",   "<NSLayoutConstraint:0x600001994690 'UINavstaticbuttonhorizposition' UIModernBarButton:0x7f8e15616be0.leading == UILayoutGuide:0x6000003801c0'UIViewLayoutMarginsGuide'.leading  (active)>",   "<NSLayoutConstraint:0x6000019946e0 'UINavItemContentGuide-leading' H:[UIButtonBarButton:0x7f8e15613a90]-(0)-[UILayoutGuide:0x6000003fc1c0'UINavigationBarItemContentLayoutGuide']  (active)>",   "<NSLayoutConstraint:0x6000019b3e30 'UINavItemContentGuide-trailing' UILayoutGuide:0x6000003fc1c0'UINavigationBarItemContentLayoutGuide'.trailing == UINavigationBarContentView:0x7f8e1570e330.trailing  (active)>",   "<NSLayoutConstraint:0x60000199f660 'UIView-Encapsulated-Layout-Width' _UINavigationBarContentView:0x7f8e1570e330.width == 0  (active)>",   "<NSLayoutConstraint:0x6000019abd90 'UIView-leftMargin-guide-constraint' H:|-(0)-UILayoutGuide:0x6000003801c0'UIViewLayoutMarginsGuide' - LTR  (active, names: '|':UINavigationBarContentView:0x7f8e1570e330 )>" ) Will attempt to recover by breaking constraint  <NSLayoutConstraint:0x6000019a7390 'BIBTrailingCBLeading' H:[UIModernBarButton:0x7f8e15616be0]-(6)-[UIModernBarButton:0x7f8e15614460'Hello World']  (active)> Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful. I do believe this issue is similar to https://stackoverflow.com/questions/65316497/swiftui-navigationview-navigationbartitle-layoutconstraints-issue however the discussion there seems inconclusive. Thanks!
Posted
by ellis246.
Last updated
.
Post not yet marked as solved
0 Replies
44 Views
Hi everyone ! It's about a week I'm trying to find a suitable command (not Navigation) in order to push a button and then have another window open for MacOS (not iOS). I have ContentView with "Some TEXT" and DetailView with "Another text" ContentView import SwiftUI struct ContentView: View {     var body: some View {                  VStack {             Text("Testing this") //First line text                 .navigationTitle("The program")                 .position(x: 200, y:20)             Button("Push me") {             }             }         .frame(width: 400.0, height: 200.0             } } in Content view I also made a button Button ("Push me") { // and here I need to write something in order to open DetailView } DetailView `import SwiftUI struct DetailView: View {     var body: some View {         VStack {                          Text("Test OK") //First line text                 .navigationTitle("The program")                           .position(x: 200, y:20)                      }                           .frame(width: 400.0, height: 200.0) } }` I am using swiftUI , and for now I need to solve this way. I know that through storyboard it could work much easier ... but I'm not looking for easy ways.
Posted
by Narius.
Last updated
.
Post marked as solved
4 Replies
97 Views
I'm using Xcode 13.4.1 and targeting iOS 15.0. I have aSwiftUI app that crashes as soon as you click a button that changes a variable from true to false: Button("Close Side by Side Mode") { mainScreenRecs.isViewingSideBySide = false } This is the only place where the variable is changed; everything else is just SwiftUI reading the variable to determine whether to show views or not, like this: var body: some View {         VStack(spacing: 0) {                 HStack {                     if mainScreenRecs.isViewingSideBySide {                         Text(catalogModel.title)                     } When I look at the debug stack, I can see that the previous modification says LayoutComputer.EngineDelegate.childGeometries(at:origin:), which makes me wonder if it's related to SwiftUI: I see this in the debug output, which has the additional note about AttributeGraph: cycle detected through attribute, another possible SwiftUI problem: I tried wrapping this code in DispatchQuery.main.async, like this: Button("Close Side by Side Mode") { DispatchQueue.main.async { mainScreenRecs.isViewingSideBySide = false } } but it didn't help. Is it possible this is a SwiftUI bug? I hate to think that because it leaves me stuck without a solution, but I can't figure out what else I could check or try.
Posted Last updated
.
Post not yet marked as solved
0 Replies
55 Views
I've implemented a Sign In With Apple as the front end, and Firebase as the backend. The objective is that the user would sign in, and the terminal would give the user's name and email. For some reason, it isn't working. Please take a look and tell me what I am missing to make it do what my goal is. import SwiftUI import Firebase import AuthenticationServices import FirebaseAuth import CryptoKit struct LoginView: View { @State private var isLoginMode = false @State private var email = "" @State private var password = "" @State private var address = "" @State private var resultOfAuth = "" @EnvironmentObject var userAuth: UserAuth @State var currentnonce: String? // Adapted from https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce private func randomNonceString(length: Int = 32) -> String { precondition(length > 0) let charset: [Character] = Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._") var result = "" var remainingLength = length while remainingLength > 0 { let randoms: [UInt8] = (0 ..< 16).map { _ in var random: UInt8 = 0 let errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random) if errorCode != errSecSuccess { fatalError( "Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)" ) } return random } randoms.forEach { random in if remainingLength == 0 { return } if random < charset.count { result.append(charset[Int(random)]) remainingLength -= 1 } } } return result } private func sha256(_ input: String) -> String { let inputData = Data(input.utf8) let hashedData = SHA256.hash(data: inputData) let hashString = hashedData.compactMap { String(format: "%02x", $0) }.joined() return hashString } var body: some View { NavigationView { SignInWithAppleButton( onRequest: { request in let nonce = randomNonceString() currentnonce = nonce request.requestedScopes = [.fullName, .email] request.nonce = sha256(nonce) let resultOfAuth = request.requestedScopes }, onCompletion: { result in switch result { case .success(let authResults): switch authResults.credential { case let appleIDCredential as ASAuthorizationAppleIDCredential: guard let nonce = currentnonce else { fatalError("Invalid state: A login callback was received, but no login request was sent.") } guard let appleIDToken = appleIDCredential.identityToken else { fatalError("Invalid state: A login callback was received, but no login request was sent.") } guard let idTokenString = String(data: appleIDToken, encoding: .utf8) else { print("Unable to serialize token string from data: \(appleIDToken.debugDescription)") return } let credential = OAuthProvider.credential(withProviderID: "apple.com",idToken: idTokenString,rawNonce: nonce) Auth.auth().signIn(with: credential) { (authResult, error) in if (error != nil) { // Error. If error.code == .MissingOrInvalidNonce, make sure // you're sending the SHA256-hashed nonce as a hex string with // your request to Apple. print(error?.localizedDescription as Any) return } print("signed in") print(resultOfAuth) self.userAuth.login() NavigationLink { HomeView() } label: { Text("Done") } } print("\(String(describing: Auth.auth().currentUser?.uid))") default: break } default: break } } ) .frame(width: 200, height: 45, alignment: .center) } } ```
Posted Last updated
.
Post not yet marked as solved
0 Replies
65 Views
I have a SwiftUI app where I can sign in via Apple Sign In using Firebase Auth. This works completely fine on iPad and iPhone. However when when running the app via catalyst on Mac, using Apple Sign In I get a crash with the following log. _AuthenticationServices_SwiftUI/SignInWithAppleButton.swift:303: Fatal error: Attempting to present ASAuthorizationController from a SwiftUI view not in a hierarchy. This should not be possible, please file feedback. 2022-07-13 19:31:29.368989+0100 appname[93200:13915263] _AuthenticationServices_SwiftUI/SignInWithAppleButton.swift:303: Fatal error: Attempting to present ASAuthorizationController from a SwiftUI view not in a hierarchy. This should not be possible, please file feedback. (lldb) I am not sure what is wrong, I have checked Apple Documentation and am struggling to find a fix. Apple Sign In Object: import SwiftUI import AuthenticationServices import CryptoKit @EnvironmentObject var store: Store struct SignInWithAppleButtonView: View { //Hashing function using CryptoKit private func sha256(_ input: String) -> String { let inputData = Data(input.utf8) let hashedData = SHA256.hash(data: inputData) let hashString = hashedData.compactMap { return String(format: "%02x", $0) }.joined() return hashString } // from https://firebase.google.com/docs/auth/ios/apple private func randomNonceString(length: Int = 32) -> String { precondition(length > 0) let charset: Array<Character> = Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._") var result = "" var remainingLength = length while remainingLength > 0 { let randoms: [UInt8] = (0 ..< 16).map { _ in var random: UInt8 = 0 let errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random) if errorCode != errSecSuccess { fatalError("Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)") } return random } randoms.forEach { random in if remainingLength == 0 { return } if random < charset.count { result.append(charset[Int(random)]) remainingLength -= 1 } } } return result } @State var currentNonce:String? var body: some View { SignInWithAppleButton(.signIn) { request in // You can change them if needed. let nonce = randomNonceString() currentNonce = nonce request.requestedScopes = [.fullName, .email] request.nonce = sha256(nonce) } onCompletion: { result in // Switch result switch result { // Auth Success case .success(let authResults): default: break } case .failure(let error): print("failure", error) } } .frame(maxWidth: .infinity) } Login import SwiftUI import AuthenticationServices import CryptoKit struct login: View { @EnvironmentObject var store: Store var body: some View { GeometryReader { geometry in ZStack(alignment: .bottom) { VStack(alignment: .center, spacing: 20) { SignInWithAppleButtonView() .signInWithAppleButtonStyle(.black) .environmentObject(store) } } } } } Handler class Store : ObservableObject { func signInWithAppleHandler(credential: OAuthCredential) { Auth.auth().signIn(with: credential) { (authResult, error) in if (error != nil) { // Error. If error.code == .MissingOrInvalidNonce, make sure // you're sending the SHA256-hashed nonce as a hex string with // your request to Apple. print(error?.localizedDescription as Any) return } print("Signed in") if let user = authResult?.user { // Fetch profile let db = Firestore.firestore() db.collection("users").document(user.uid).getDocument { [self] (document, error) in if let document = document, document.exists { //User exists now save that to current user _ = document.data().map(String.init(describing:)) ?? "nil" do { self.profile = try document.data(as: Profile.self) } catch { print("There was an error getting decoding Profile") } if self.profile != nil { self.userAuthState = .signedIn self.isNewUser = self.profile!.newUser self.loadProfileImageFromFirebase(uid: profile!.uid) } } else { // create profile firestoreManager.createProfile(uid: user.uid, email: user.email ?? "") fetchProfile(uid: user.uid) } } } } } } Apple Documentation: https://developer.apple.com/documentation/authenticationservices/signinwithapplebutton Firebase Documentation: https://firebase.google.com/docs/auth/ios/apple
Posted
by RileyDev.
Last updated
.
Post marked as solved
6 Replies
5.3k Views
I am trying to bind a Picker, but it's not working. I create a BindableObject, an instance of Settings, add it to the environment using environmentObject() in SceneDelegate, and address it in the View using @EnvironmentObjectstruct ContentView : View { var favoriteFoods = ["Tofu", "Seitan", "Nilla Wafers", "Avocado Toast"] @EnvironmentObject var settings : Settings // meanwhile, inside var body: some View ... Picker(selection: $settings.favoriteFoodChoice, label: Text("Favorite Food")){ ForEach(self.favoriteFoods.identified(by: \.self)){ food in Text(food) } }Here's what my Settings looks like:class Settings : BindableObject { var didChange = PassthroughSubject&lt;void,never&gt;() var favoriteFoodChoice:Int { willSet { print("Favorite Food Choice will be \(newValue)") didChange.send() print("Favorite Food Choice: \(favoriteFoodChoice)")// never changes when I select a different food. } didSet { print("Favorite Food Choice was \(oldValue)") didChange.send() print("Favorite Food Choice: \(favoriteFoodChoice)")// never changes when I select a different food. } } init(favoriteFoodChoice:Int) { self.favoriteFoodChoice = favoriteFoodChoice } convenience init(){ self.init(favoriteFoodChoice:0) } }When I change the selected food, I see output from print(), but favoriteFoodChoice stays the same. Isn't it supposed to change?? Or am I misunderstanding how binding works with Pickers?Any help would be appreciated!
Posted
by mprogers.
Last updated
.
Post not yet marked as solved
0 Replies
37 Views
Hi everybody, given the following case using SwiftUI: Button("testButton", action: noop) .accessibilityRepresentation{representation: { Slider(value: $sliderData.sliderValue) }) .accessibilityIdentifier("testSlider") I'm trying to control the slider using XCUITest via slider.adjust(toNormalizedSliderPosition: 0.2) and receive the following error message: Failed: Unable to get expected attributes for slider, found { "XC_kAXXCAttributeMaxScrubberPosition" = { X = 0; Y = 0; }; "XC_kAXXCAttributeMinScrubberPosition" = { X = 0; Y = 0; }; Similarly, print (slider.normalizedSliderPosition) leads to the error message "Failed to determine current position of slider "0 %". Is there a way to set and read the value of accessibilityRepresentation-Sliders with XCUITest? Thanks!
Posted
by sasro.
Last updated
.
Post marked as solved
4 Replies
95 Views
Hey ! Today I wish declare a variable in a structure but we need to declare a type and sometimes value is an Integer and sometimes is a String import Foundation struct PlayerData: Decodable {     var country: String     var name: String     var prestige: Int     var bank: Int     var rank: Int     var experiencePercent: Float     var stats: [PlayerStats] } struct PlayerStats: Decodable {     var name: String     var value: // here String or Int } thanks for your responses and have a nice day
Posted
by Trialenzo.
Last updated
.
Post not yet marked as solved
1 Replies
128 Views
So I have a navigationStack which has a NavigationLink that navigates to the next view. That view then has its own NavigationLink that navigate to a 3rd view. if the user clicks on the back button on the 3rd view (View3) to return to the previous view (View 2), it goes right back to the starting view (View 1). an one else have this issue or know how to fix? ios16b1 example below: View 1: NavigationStack {                 View2()                     .navigationTitle("View 2")             } View 2: List {        VStack (alignment: .leading) {                     NavigationLink("View 3", destination: {                         View3()                     }) } }
Posted
by ngb.
Last updated
.
Post not yet marked as solved
4 Replies
585 Views
I have Navigation links in my swift ui code, those work correctly in with XCode 13.1 and WatchOS 8.2, but now with the XCode 13.2 and WatchOs 8.3 those links just pop out automatically after opening the new view. It seems to work in some views and fail on others, I havent yet figured out what it the cause of this. This still works when I open same project in XCode 13.1 and WatchOS 8.2, or with XCode 13.2 and WatchOs8.0 simulator. So there seems to be something broken with lates WatchOs 8.3 simulator new version. (Havent test yet with real device)
Posted
by MapaX.
Last updated
.
Post not yet marked as solved
0 Replies
42 Views
Thank you for the tutorials. As a new comer to swiftui, I find the swiftui tutorial as the best, in my humble opinion. It is beautifully done, specially when the code changes is highlighted as one scrolls. As a beginner, I find the tutorial engaging. Seeing a project come to life is truly a high unlike any (lol), at least for a beginner like me. I have learned enough doing the tutorial and couldn't just stay silent without expressing my appreciation and gratitude for all that you have put in the tutorials. Thank you. Cheers.
Posted Last updated
.
Post not yet marked as solved
0 Replies
63 Views
I'm trying to add an item to the bottom of a List and then scroll that added item into view. I've made the following code that can be entered directly into a new iOS project in Xcode (14 beta 3) to replicate the problem (which is an exception after adding an item 3 times). I have tried many variations of the ID used in the "id" field of ForEach, the ".id" modifier on the text, as well as in the "scrollTo" method. Nothing works for me -- I get the same behavior no matter what I use: The first item scrolls into view as desired; the second item does not scroll; and the third item crashes. I've left in the code a ".onDelete" modifier because it literally takes 3 items added before the crash will occur. So, you could add 2 items, delete one of those, and then it would take two more adds (still for a total of 3 items in the List) to see the crash. I'm baffled. It doesn't seem to matter how many items I start the list with (4 in this case)... it is always the third addition that crashes. Any thoughts? Thanks for any help. struct ContentView: View {          @State var data = [1, 2, 3, 4]     @State var count = 4     var body: some View {         VStack {             ScrollViewReader { proxy in                 List {                     ForEach(data, id: \.self) { datum in                         Text("\(datum)")                             .id(datum)                     }                     .onDelete {                         data.remove(atOffsets: $0)                     }                 }                 .onChange(of: data) { _ in                     proxy.scrollTo(data.last)                 }             }             Button {                 count += 1                 data.append(count)             } label: {                 Text("Add")             }         }     } }
Posted
by Benjy1000.
Last updated
.
Post not yet marked as solved
3 Replies
183 Views
I'm trying to call the refresh function in the view model from the .refreshable in a view. I have tested it with an empty function in the viewModel and it causes a memory leak in this view struct TopicListView: View {   @StateObject private var viewModel: TopicListViewModel   @State private var boardId: String   @State private var boardName: String       init(dataFetchable: DataFetchable, boardId: String, boardName: String) {     self._viewModel = StateObject(wrappedValue: TopicListViewModel(dataFetchable: dataFetchable))     self.boardId = boardId     self.boardName = boardName   }       var body: some View {     List(viewModel.topics.indices, id: \.self) { index in       HStack {         TopicView(title: viewModel.topics[index].title, lastPostTime: viewModel.topics[index].lastPostTime, formatter: viewModel.dateFormatter)                   NavigationLink(destination: PostView(dataFetchable: viewModel.dataFetchable, title: viewModel.topics[index].title, topicId: viewModel.topics[index].id)) {                       EmptyView()         }         .frame(width: 0)         .opacity(0)       }       .onAppear {         if index == viewModel.topics.count-1 {           viewModel.page+=1           viewModel.fetchTopics(boardId)         }       }     }     .listStyle(.plain)     .navigationBarTitle(boardName)     .refreshable {       await viewModel.doNotThing()     }     .onAppear {       viewModel.boardId = boardId     }   } } However, the PostView which I have linked with a NavigationLink have no issue struct PostView: View {   @State private var title: String   @State private var topicId: String   @StateObject private var viewModel: PostViewModel       init(dataFetchable: DataFetchable, title: String, topicId: String) {     self._viewModel = StateObject(wrappedValue: PostViewModel(dataFetchable: dataFetchable))     self.topicId = topicId     self.title = title   }       var body: some View {     List(viewModel.posts, id: \.id) { item in       TextblockView(textBlock: item.textBlock)     }     .listStyle(.plain)     .navigationBarTitle(title)     .navigationBarTitleDisplayMode(.inline)     .refreshable {       await viewModel.doNotThing()     }     .onAppear(perform: {       viewModel.topicId = topicId     })         } } Here is the memory graph Any ideas how to fix it?
Posted Last updated
.
Post not yet marked as solved
5 Replies
1.2k Views
For context: I'm working on a score pad app, with the ability to have a column of PKCanvases, so you can just hand write things without them being scribbled into text. As part of my stress testing, I basically filled the grid with ~50 canvases, and it seems that after a certain amount of CanvasViews are added to the score pad, my M1 iPad Pro GPU is unable to keep up. Occasionally, a cell will just entirely render as magenta, and I will have dozens and dozens of Execution of the command buffer was aborted due to an error during execution. Insufficient Memory (IOAF code 8) logs thrown to the console. I honestly don't know where to go from here. I recognize that what I'm doing is almost definitely not what PencilKit was designed for, but I also know the API is relatively young. I can't tell if this is a bug that should be fixed by Apple, or entirely my fault and a sign that I need to redo the entire thing. I've attached a screenshot with the magenta cell, there's also another two cells where the pencil strokes are just thick black squares. I'd appreciate any advice or help, I can't even seem to find any way to detect and recover from this in my code, as trying to search for Metal errors gives me discussions about writing Metal apps, which this isn't. It's a pure SwiftUI app with some PencilKit canvases.
Posted
by pgelvinaz.
Last updated
.