Post

Replies

Boosts

Views

Activity

Reply to Issues with UserDefault boolean
As @MobileTen stated, never store passwords in UserDefaults. You need to use the Keychain. Also, I'm not sure why you need to store something called passcode-reset and passcode-set. The very fact that a password exists means it has been set, and if you're resetting a passcode, then that should be done as part of the journey for the user, not something that needs storing anywhere. In other words, if the user wants to reset their password, ask them for a new one, and save the new password to the keychain. There's no need to store in UDs that you're resetting the password. So, here's how to use the keychain: let userAccount: String = "AuthenticatedUser" let passwordKey: String = "SomeSortOfStringIdentifyingThisIsAPasswordForYourApp" // Choose a relevant value and never change it, as the password is stored against this value func getKeychainPasscode() -> String { return KeychainService.loadPassword(service: passwordKey, account: userAccount) ?? "" } // getKeychainPasscode() will tell you if a password is set. If it returns "" then it hasn't been set. func updatePasscode(_ value: String) { KeychainService.updatePassword(service: passwordKey, account: userAccount, data: value) } // Arguments for the keychain queries let kSecClassValue = NSString(format: kSecClass) let kSecAttrAccountValue = NSString(format: kSecAttrAccount) let kSecValueDataValue = NSString(format: kSecValueData) let kSecClassGenericPasswordValue = NSString(format: kSecClassGenericPassword) let kSecAttrServiceValue = NSString(format: kSecAttrService) let kSecMatchLimitValue = NSString(format: kSecMatchLimit) let kSecReturnDataValue = NSString(format: kSecReturnData) let kSecMatchLimitOneValue = NSString(format: kSecMatchLimitOne) public class KeychainService: NSObject { class func updatePassword(service: String, account: String, data: String) { if let dataFromString: Data = data.data(using: String.Encoding.utf8, allowLossyConversion: false) { // Instantiate a new default keychain query let keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, account], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue]) let status = SecItemUpdate(keychainQuery as CFDictionary, [kSecValueDataValue : dataFromString] as CFDictionary) if(status == errSecItemNotFound) { // No existing passcode, so just save the new one savePassword(service: service, account: account, data: data) } else { // Passcode exists, so delete it and save the new one removePassword(service: service, account: account) savePassword(service: service, account: account, data: data) } } } class func removePassword(service: String, account: String) { // Instantiate a new default keychain query let keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, account, kCFBooleanTrue ?? true], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecReturnDataValue]) // Delete any existing items let status = SecItemDelete(keychainQuery as CFDictionary) if(status != errSecSuccess) { if let err = SecCopyErrorMessageString(status, nil) { print("Remove failed: \(err)") } } } class func savePassword(service: String, account: String, data: String) { if let dataFromString = data.data(using: String.Encoding.utf8, allowLossyConversion: false) { // Instantiate a new default keychain query let keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, account, dataFromString], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecValueDataValue]) // Add the new keychain item let status = SecItemAdd(keychainQuery as CFDictionary, nil) // Always check the status if (status != errSecSuccess) { if let err = SecCopyErrorMessageString(status, nil) { print("Write failed: \(err)") } } } } class func loadPassword(service: String, account: String) -> String? { // Instantiate a new default keychain query // Tell the query to return a result // Limit our results to one item let keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, account, kCFBooleanTrue ?? true, kSecMatchLimitOneValue], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecReturnDataValue, kSecMatchLimitValue]) var dataTypeRef: AnyObject? // Search for the keychain items let status: OSStatus = SecItemCopyMatching(keychainQuery, &dataTypeRef) var contentsOfKeychain: String? if(status == errSecSuccess) { if let retrievedData = dataTypeRef as? Data { contentsOfKeychain = String(data: retrievedData, encoding: String.Encoding.utf8) } } return contentsOfKeychain } }
Topic: Design SubTopic: General Tags:
Nov ’24
Reply to Double-tap to activate a UITextField?
If single-tapping on a text field in your app can be calamitous I'd say your app isn't designed properly. You need to revisit the user experience. Also, since text fields exist across the entire OS and users expect them to be activated when they single-tap them, changing this just for your app will ruin a user's 'muscle memory' and give them a poor experience.
Topic: UI Frameworks SubTopic: UIKit Tags:
Nov ’24
Reply to iPhone Camera opening unexpectedly
You should probably raise this as a bug in the usual way. It won't really get progressed if it's only posted in these Developer Forums. You need to raise each issue you find separately at https://feedbackassistant.apple.com/ You can post the FB numbers here if you want, so that others can link to them.
Nov ’24
Reply to Mac os 15, breaking Citrix VPN
This page on Citrix's website doesn't mention macOS 15 as a supported version, so it seems you'll have to wait for Citrix to release a compatible version, and I'd suggest you contact them: https://docs.citrix.com/en-us/citrix-secure-private-access/service/spa-csa-for-client-server-apps.html
Oct ’24
Reply to Wind Compass swift UI
No problem. Just remember not to redraw the entire view when you change the degrees. You only need to change the rotationEffect of the compass marker arrow (and whatever text you put in the VStack) when the value changes.
Topic: Design SubTopic: General Tags:
Oct ’24
Reply to SwiftUI Lists down arrow handling broken
Do you have some code for your two examples? Maybe you're doing something wrong, and there's a different way of doing what you want to achieve?
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Nov ’24
Reply to Top Shelf and App Icon not appearing on tvOS 18.
You should probably raise this as a bug in the usual way. It won't really get progressed if it's only posted in these Developer Forums. You need to raise each issue you find separately at https://feedbackassistant.apple.com/ You can post the FB numbers here if you want, so that others can link to them.
Replies
Boosts
Views
Activity
Nov ’24
Reply to New iOS 18
Favourites is in the Pinned Collections. Just scroll down.
Topic: Design SubTopic: General Tags:
Replies
Boosts
Views
Activity
Nov ’24
Reply to Android Emulator "System UI Isn't Responding" Error on macOS Monterey
Have you tried asking the people who wrote Android Studio? How about asking on the forums for that application?
Replies
Boosts
Views
Activity
Nov ’24
Reply to Issues with UserDefault boolean
As @MobileTen stated, never store passwords in UserDefaults. You need to use the Keychain. Also, I'm not sure why you need to store something called passcode-reset and passcode-set. The very fact that a password exists means it has been set, and if you're resetting a passcode, then that should be done as part of the journey for the user, not something that needs storing anywhere. In other words, if the user wants to reset their password, ask them for a new one, and save the new password to the keychain. There's no need to store in UDs that you're resetting the password. So, here's how to use the keychain: let userAccount: String = "AuthenticatedUser" let passwordKey: String = "SomeSortOfStringIdentifyingThisIsAPasswordForYourApp" // Choose a relevant value and never change it, as the password is stored against this value func getKeychainPasscode() -> String { return KeychainService.loadPassword(service: passwordKey, account: userAccount) ?? "" } // getKeychainPasscode() will tell you if a password is set. If it returns "" then it hasn't been set. func updatePasscode(_ value: String) { KeychainService.updatePassword(service: passwordKey, account: userAccount, data: value) } // Arguments for the keychain queries let kSecClassValue = NSString(format: kSecClass) let kSecAttrAccountValue = NSString(format: kSecAttrAccount) let kSecValueDataValue = NSString(format: kSecValueData) let kSecClassGenericPasswordValue = NSString(format: kSecClassGenericPassword) let kSecAttrServiceValue = NSString(format: kSecAttrService) let kSecMatchLimitValue = NSString(format: kSecMatchLimit) let kSecReturnDataValue = NSString(format: kSecReturnData) let kSecMatchLimitOneValue = NSString(format: kSecMatchLimitOne) public class KeychainService: NSObject { class func updatePassword(service: String, account: String, data: String) { if let dataFromString: Data = data.data(using: String.Encoding.utf8, allowLossyConversion: false) { // Instantiate a new default keychain query let keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, account], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue]) let status = SecItemUpdate(keychainQuery as CFDictionary, [kSecValueDataValue : dataFromString] as CFDictionary) if(status == errSecItemNotFound) { // No existing passcode, so just save the new one savePassword(service: service, account: account, data: data) } else { // Passcode exists, so delete it and save the new one removePassword(service: service, account: account) savePassword(service: service, account: account, data: data) } } } class func removePassword(service: String, account: String) { // Instantiate a new default keychain query let keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, account, kCFBooleanTrue ?? true], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecReturnDataValue]) // Delete any existing items let status = SecItemDelete(keychainQuery as CFDictionary) if(status != errSecSuccess) { if let err = SecCopyErrorMessageString(status, nil) { print("Remove failed: \(err)") } } } class func savePassword(service: String, account: String, data: String) { if let dataFromString = data.data(using: String.Encoding.utf8, allowLossyConversion: false) { // Instantiate a new default keychain query let keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, account, dataFromString], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecValueDataValue]) // Add the new keychain item let status = SecItemAdd(keychainQuery as CFDictionary, nil) // Always check the status if (status != errSecSuccess) { if let err = SecCopyErrorMessageString(status, nil) { print("Write failed: \(err)") } } } } class func loadPassword(service: String, account: String) -> String? { // Instantiate a new default keychain query // Tell the query to return a result // Limit our results to one item let keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, account, kCFBooleanTrue ?? true, kSecMatchLimitOneValue], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecReturnDataValue, kSecMatchLimitValue]) var dataTypeRef: AnyObject? // Search for the keychain items let status: OSStatus = SecItemCopyMatching(keychainQuery, &dataTypeRef) var contentsOfKeychain: String? if(status == errSecSuccess) { if let retrievedData = dataTypeRef as? Data { contentsOfKeychain = String(data: retrievedData, encoding: String.Encoding.utf8) } } return contentsOfKeychain } }
Topic: Design SubTopic: General Tags:
Replies
Boosts
Views
Activity
Nov ’24
Reply to WhatsApp is not available for iPad 11 pro on App Store
You should probably get in touch with Meta. It's Meta who develop and release that app, not Apple, and certainly not the third-party developers who use these forums.
Replies
Boosts
Views
Activity
Nov ’24
Reply to The bad service by App Review Team
Cutting out the excessive nonsense in this post, what's your actual issue? Try and restrain yourself to a couple of sentences.
Replies
Boosts
Views
Activity
Nov ’24
Reply to Issue: The page goes blank and gets stuck after login.
What app are you talking about? How do you expect anyone to understand what you'r talking about when you don't provide even the most basic of info?
Replies
Boosts
Views
Activity
Nov ’24
Reply to Double-tap to activate a UITextField?
If single-tapping on a text field in your app can be calamitous I'd say your app isn't designed properly. You need to revisit the user experience. Also, since text fields exist across the entire OS and users expect them to be activated when they single-tap them, changing this just for your app will ruin a user's 'muscle memory' and give them a poor experience.
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
Boosts
Views
Activity
Nov ’24
Reply to Draining battery health so fast
These are the Developer Forums, where developers of apps for Apple's platforms ask each other for hints and tips on coding. Your question is more of a product support one, so I'd suggest you ask it over at the Apple Support Forums. Thanks.
Replies
Boosts
Views
Activity
Nov ’24
Reply to iPhone Camera opening unexpectedly
You should probably raise this as a bug in the usual way. It won't really get progressed if it's only posted in these Developer Forums. You need to raise each issue you find separately at https://feedbackassistant.apple.com/ You can post the FB numbers here if you want, so that others can link to them.
Replies
Boosts
Views
Activity
Nov ’24
Reply to The Right Side of my MacBook is Unclickable!
These are the Developer Forums, where developers of apps for Apple's platforms ask each other for hints and tips on coding. Your question is more of a product support one, so I'd suggest you ask it over at the Apple Support Forums. Thanks.
Replies
Boosts
Views
Activity
Oct ’24
Reply to Mac os 15, breaking Citrix VPN
This page on Citrix's website doesn't mention macOS 15 as a supported version, so it seems you'll have to wait for Citrix to release a compatible version, and I'd suggest you contact them: https://docs.citrix.com/en-us/citrix-secure-private-access/service/spa-csa-for-client-server-apps.html
Replies
Boosts
Views
Activity
Oct ’24
Reply to WhatsApp is incorrectly adding a number as suffix to device name in the list of Linked devices
Not really an issue for us third-party app developers. You should get in touch with WhatsApp.
Topic: Community SubTopic: Apple Developers Tags:
Replies
Boosts
Views
Activity
Oct ’24
Reply to Wind Compass swift UI
No problem. Just remember not to redraw the entire view when you change the degrees. You only need to change the rotationEffect of the compass marker arrow (and whatever text you put in the VStack) when the value changes.
Topic: Design SubTopic: General Tags:
Replies
Boosts
Views
Activity
Oct ’24