Hi all,
I want to create an application with SwiftUI that either
Quits when the last window is closed, or
Allows one window only. That is, the New Window command is greyed out when a window is already open. I don't hold much hope for this one, not in pure swiftUI, because the commands builder doesn't allow logic.
I am pretty sure this used to be a simple configuration on the Mac, this would be my best hope.
Hello! I'm working with the UIHostingConfiguration and would like to set a Toolbar for a TextField which I placed in the content. I've tried to set ToolbarRole and Toolbar Visibility. Unfortunately, it doesn't work. Here's my example code:
Cell:
cell.configurationUpdateHandler = { (cell, state) in
cell.contentConfiguration = UIHostingConfiguration {
RowView(item: item)
}
}
View:
@ObservedObject var item: Movie
var body: some View {
TextField("Title", text: $item.title)
.toolbar(content: {
ToolbarItem(placement: .keyboard) {
Button("Confirm", action: {})
}
})
.toolbar(.visible, in: .automatic)
}
}
Post not yet marked as solved
I'm trying to use a different version of view modifier when a view is inserted and when its being removed. However combining .asymmetric and .modifier transitions don't quite work as expected.
Here's a test that attempts to print out the combination of states the view transitions between:
struct TransitionPrinting: ViewModifier {
var isInsertion: Bool
var isActive: Bool
func body(content: Content) -> some View {
content
.onAppear {
print("isInsertion", isInsertion, "isActive", isActive)
}
}
}
struct ContentView: View {
@State var toggled = false
var body: some View {
VStack {
Toggle("Toggle", isOn: $toggled)
if toggled {
Text("Hello, world!")
.transition(
.asymmetric(
insertion: .modifier(
active: TransitionPrinting(isInsertion: true, isActive: true),
identity: TransitionPrinting(isInsertion: true, isActive: false)
),
removal: .modifier(
active: TransitionPrinting(isInsertion: false, isActive: true),
identity: TransitionPrinting(isInsertion: false, isActive: false)
)
)
)
}
Spacer()
}
.padding()
}
}
When the above is run, I only see the following in the simulator (with 2 of the states missing):
isInsertion true isActive true
isInsertion false isActive false
What's wrong here?
Post not yet marked as solved
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.
Post not yet marked as solved
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)
}
}
```
Post not yet marked as solved
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
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 ...
}
}
}
}
Post not yet marked as solved
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!
Post not yet marked as solved
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.
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
Post not yet marked as solved
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")
}
}
}
}
Post not yet marked as solved
Error Code: error build: Command CompileSwift failed with a nonzero exit code
My Code:
.backgroundTask(.appRefresh("checkValidity")) {
// scheduleAppRefresh()
// checkRecords()
}
Post not yet marked as solved
So basically we are using custom TabBar and wondering how we gonna handle focus.
As I tried to focusSection but it is not working while going down, Basically we have a horizontal list but it always focuses on 2nd Item rather than the first one.
Post not yet marked as solved
I'm seeing that the new type-based WindowGroup initializers (i.e. WindowGroup(for: MyType.self) { ... }) are available on macOS, but not iPadOS. The WWDC sessions seemed to imply that this API was available on iPadOS as well. Am I mistaken or is it expected to become available in a later beta?
Post not yet marked as solved
I'm currently trying to save a selected image in core data as a type data, but I'm getting an error in the persistence file marked with a comment. I've included my code and any questions I will gladly answer. Thanks for any help!
Content View:
import SwiftUI
import PhotosUI
struct ContentView: View {
@ObservedObject var persistence = PersistenceController.shared
@State var selectedItems: [PhotosPickerItem] = []
@State var data: Data?
var body: some View {
NavigationView{
VStack{
Spacer()
VStack{
Spacer()
if let data = data, let uiimage = UIImage(data: data) {
Image(uiImage: uiimage)
.resizable()
.scaledToFit()
.frame(width: 250, height: 500)
}
Spacer()
}
Spacer()
PhotosPicker(selection: $selectedItems, maxSelectionCount: 1, matching: .images){
Text("Pick Photo")
}
.onChange(of: selectedItems){ newValue in
guard let item = selectedItems.first else{
return
}
item.loadTransferable(type: Data.self){ result in
switch result {
case .success(let data):
if let data = data{
self.data = data
} else {
print("Data is nil")
}
case .failure(let failure):
fatalError("\(failure)")
}
}
}
Spacer()
}
.navigationBarItems(trailing: addButton)
}
}
var addButton: some View {
Button(action: {
guard let item = selectedItems.first else{
return
}
item.loadTransferable(type: Data.self){ result in
switch result {
case .success(let data):
if let data = data{
persistence.addObject(image: data)
} else {
print("Data is nil")
}
case .failure(let failure):
fatalError("\(failure)")
}
}
}){
Text("Add Image").bold()
}
}
}
Persistence:
import Foundation
import CoreData
class PersistenceController: ObservableObject {
static let shared = PersistenceController()
let container: NSPersistentContainer
init(inMemory: Bool = false) {
container = NSPersistentContainer(name: "ReciPlanner")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
container.viewContext.automaticallyMergesChangesFromParent = true
}
func addObject(image: Data){
let context = container.viewContext
let object = Object(context: context) //Error: Thread 7: "An NSManagedObject of class 'Object' must have a valid NSEntityDescription."
object.item = image
}
func contextSave() {
let context = container.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
print("**** ERROR: Unable to save context \(error)")
}
}
}
}
Data Model:
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.
Post not yet marked as solved
I have a View that consists of a NavigationView. I set its style to .stack using .navigationViewStyle to force the 'stacked' modal look when appropriate (I am displaying it modally from UIKit using a UIHostingController).
This works fine but I need the view to detect if it's actually shown using the stacked look or not at runtime (on an iPhone in landscape mode, it will be displayed as full screen and I need to add a Close/Dismiss button in that specific case).
Suggestions?
Post not yet marked as solved
I navigating to tabview from content view. For this i am using navigationview link in content view.
In the four tabs first tab contains scrollview. While scrolling the view i am getting navigation bar on top and it is applying to all tabs.
if land on first tab and if i switch to third tab without scroll and scroll in third tab, i am not getting navigation bar and i return to first tab, then also i am not getting navigation bar.
Can you please let me know how to resolve this. How to maintain navigation bar consistent
Post not yet marked as solved
Hi,
I am using tabbar with four tabs. While switching tabs i am updating tabar item images with fill colors. It is working fine. But i have a requirement in first tab is, when click on button in first tab, i have to switch to second tab and i have to update non selected image to selected image. While in this process to switch tabs. I am getting crash with xpc invalid connection issue.
Can you please let me know how to resolve this.
Post not yet marked as solved
I am currently running Xcode Version 14.0 beta (14A5228q) creating a Multiplatform app. I wanted to include a LaunchScreen so added a Launch Screen Storyboard to my project. To the the app to see it I went under Target for my app, General, and under App Icons and Launch Screen I set the Launch Screen File to my storyboard.
This works perfectly when I run the app on iOS; however, when I run it on macOS I get an error:Launch Screen.storyboard error build: iOS storyboards do not support target device type "Mac".
I see there's no way to differentiate between macOS and iOS with the file and there's only one target. Does anyone know a way to make the storyboard only launch when running the iOS app (and iPadOS) and not be seen when running macOS?
Thanks