invalid mode 'kCFRunLoopCommonModes' provided to CFRunLoopRunSpecific - break on _CFRunLoopError_RunCalledWithInvalidMode to debugI get this warning when I tap either of the switches shown below. I've tried capturing the switch state in a var and using that to trigger the do/catch statement but no joy. I've even tried pulling the do/catch into separate functions and I still get the warning. Has anybody else run into this and how did you fix it?@IBAction func greetingFormat_Tapped(_ sender: UISwitch)
{
let theQuery = theTable_Settings.filter(settingID == 1)
if sender.isOn
{
do {
if try Database.shared.databaseConnection!.run(theQuery.update(greeting_Format <- "true")) > 0
{
greetingFormatLabel_Outlet.text = NSLocalizedString("HelloMrSmith_String", comment: "")
} else {
print("greeting format true not found")
}
} catch {
print("greeting format true update failed! Error: \(error)")
}
} else {
do {
if try Database.shared.databaseConnection!.run(theQuery.update(greeting_Format <- "false")) > 0
{
greetingFormatLabel_Outlet.text = NSLocalizedString("HiJoe_String", comment: "")
} else {
print("greeting format false not found")
}
} catch {
print("greeting format false update failed! Error: \(error)")
}
}
}@IBAction func nonrefundableSwitch_Tapped(_ sender: UISwitch)
{
let theQuery = theTable_Settings.filter(settingID == 1)
var itsOn: String = ""
if sender.isOn
{
itsOn = "true"
} else {
itsOn = "false"
}
if itsOn == "true"
{
do {
if try Database.shared.databaseConnection!.run(theQuery.update(nonRefundable_Bool <- "true")) > 0
{
depositDueLabel_Outlet.text = NSLocalizedString("nonRefunddepositisdue_String", comment: "")
} else {
print("nonRefundable true not found")
}
} catch {
print("nonRefundable true update failed! Error: \(error)")
}
} else {
do {
if try Database.shared.databaseConnection!.run(theQuery.update(nonRefundable_Bool <- "false")) > 0
{
depositDueLabel_Outlet.text = NSLocalizedString("depositisdue_String", comment: "")
} else {
print("nonRefundable false not found")
}
} catch {
print("nonRefundable false update failed! Error: \(error)")
}
}
}
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I have this code in the sceneDelegate of my app. I understand that .main is going to be deprecated. The warning says to use view?.window?.windowScene?.screen but there is no view in sceneDelegate. How can I change
let screenSize = UIScreen.main.fixedCoordinateSpace.bounds
to not use .main?
Thanks in advance.
When I execute a restore on my in-app purchase I'm getting a warning, however the restore is successfully executed. I think this is something new with Xcode 14.3. My test device is running iOS 16.4
This is the warning:
<SKPaymentQueue: 0x283708a80>: No observers found that respond to "paymentQueue:shouldAddStorePayment:forProduct:", will not check for purchase intents
It fires at this point in the code. If I comment out the first line, I don't get the warning however, the restore doesn't execute. Is anybody else seeing this or do I have something wrong in my code? I know it's only a warning but any help would be appreciated.
@IBAction func restoreButtonTapped(_ sender: UIBarButtonItem)
{
SKPaymentQueue.default().add(self)
SKPaymentQueue.default().restoreCompletedTransactions()
}
I've included the rest of the code just for a completeness.
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction])
{
for transaction in transactions
{
switch transaction.transactionState
{
case .purchasing:
//print("Purchase in progress...")
break
case .purchased:
//print("Purchase Successful")
SKPaymentQueue.default().finishTransaction(transaction)
//print("Transaction Complete")
// Hide the restore button
navigationItem.setRightBarButton(nil, animated: true)
//Set the BaseVerion in the Db to true
IAPHandler.set_BaseVersion_To_Purchased()
//Also hide the Purchase button
UIView.animate(withDuration: 1.0, animations: { [weak self] in
self?.purchaseButton.alpha = 0
}) { [weak self] (success) in
self?.selector_Top_Constraint.constant = 30
}
case .failed:
if let error = transaction.error
{
let errorDescription = error.localizedDescription
print("Transaction failed due to error: \(errorDescription)")
}
case .restored:
SKPaymentQueue.default().finishTransaction(transaction)
//print("Transaction Complete")
// Hide the restore button
navigationItem.setRightBarButton(nil, animated: true)
// Set the BaseVerion in the Db to true
IAPHandler.set_BaseVersion_To_Purchased()
// Also hide the Purchase button
UIView.animate(withDuration: 1.0, animations: { [weak self] in
self?.purchaseButton.alpha = 0
}) { [weak self] (success) in
self?.selector_Top_Constraint.constant = 30
}
case .deferred:
//print("Purchase Deferred")
break
@unknown default:
if let error = transaction.error
{
let errorDescription = error.localizedDescription
print("Transaction failed due to error: \(errorDescription)")
}
break
}
}
}
@IBAction func purchaseButtonTapped(_ sender: UIButton)
{
let theAlert = UIAlertController.init(title: K.Titles.pleaseChoose, message: nil, preferredStyle: .actionSheet)
let theCancleAction = UIAlertAction(title: K.Titles.cancel, style: .cancel)
let thePurchaseAction = UIAlertAction(title: K.DefaultList_Buttons.purchase_BaseVersion_Btn, style: .default) { [weak self] (action2) in
if SKPaymentQueue.canMakePayments()
{
// User can make payments
let paymentRequest = SKMutablePayment()
paymentRequest.productIdentifier = self!.base_Product_ID
SKPaymentQueue.default().add(self!)
SKPaymentQueue.default().add(paymentRequest)
} else {
// User cannot make payments
print("User cannot make payments")
}
}
theAlert.addAction(thePurchaseAction)
theAlert.addAction(theCancleAction)
theAlert.setValue(NSAttributedString(string: theAlert.title ?? "", attributes: [.font : UIFont.systemFont(ofSize: (gDefaultTextSize - 2), weight: UIFont.Weight.semibold)]), forKey: "attributedTitle")
let popOver = theAlert.popoverPresentationController
popOver?.sourceView = sender
popOver?.sourceRect = sender.bounds
popOver?.permittedArrowDirections = .any
present(theAlert, animated: true)
}
I have a number of apps which use a custom tab-bar for navigation. The tab-bar uses buttons with an ICON on top and text below. I have this working in Xcode 12.5 with an extension similar to those below. I wanted to see if I could convert to Xcode 13 and take advantage of the new button configurations. I was having some problems getting this to work properly so I did the following testing.
I created a new empty project in Xcode 12.5.1. Closed and re-opened the app in Xcode 13 and added two plain buttons. I didn’t change any of the attributes in the IB so they just have a blue button text. Then I attached one of the extensions below to each button. When the app opens in iSO 15 the buttons display the correct style. However, when either of the buttons is tapped the display reverts back to the text attributes of the button in the IB. So it’s blue, the text reads button and the text size changes back to the default. The ICON and the positioning remain unchanged.
If I create a new Xcode 13 project and do the exact same thing then everything working fine. Is anybody else seeing this? Is there something I need to change something in the extensions to make it work in pre 13 Xcode?
@available(iOS 15.0, *)
extension UIButton
{
func settings_MenuBtn()
{
self.configuration = .plain()
let imageConfig = UIImage.SymbolConfiguration(scale: .large)
self.configuration?.title = "Settings"
self.configuration?.attributedTitle?.foregroundColor = .white
self.configuration?.imagePlacement = .top
self.configuration?.titleAlignment = .center
self.configuration?.imagePadding = 6
self.configuration?.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)
self.configuration?.image = UIImage(systemName: "gearshape", withConfiguration: imageConfig)
self.configuration?.attributedTitle?.font = .systemFont(ofSize: gMenuTextSize, weight: .regular)
}
}
@available(iOS 15.0, *)
extension UIButton.Configuration
{
static func settings_MenuBtn2() -> UIButton.Configuration
{
let imageConfig = UIImage.SymbolConfiguration(scale: .large)
var config: UIButton.Configuration = .plain()
config.title = "Settings"
config.attributedTitle?.foregroundColor = .white
config.attributedTitle?.font = .systemFont(ofSize: gMenuTextSize, weight: .regular)
config.image = UIImage(systemName: "gearshape", withConfiguration: imageConfig)
config.imagePlacement = .top
config.titleAlignment = .center
config.imagePadding = 6
config.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)
return config
}
}
I have a textField which opens an alert. The textField is displayed in a custom popup.
The textFiled is hooked to Editing_Did_End, Editing_Did_Begin and Editing_Changed actions.
I'm running Xcode 13.4.1
In iOS 15.5 everything works fine.
In iOS 15.6.1 the Editing_Did_End action is fired as soon as the alert opens. This is causing me a lot of trouble.
In iOS 15.5 the Editing_Did_End action is not fired when the alert opens. This is how it has worked in the past.
I'm pretty sure this is a bug.
Has anybody else run into this?
I'd be happy to share my code but the thing is that it works perfectly in iOS 15.5 so I don't think there's a problem with my code.
If you are seeing the same thing please reply to this post.
The firing order was changed when tapping a textView or textField.
I first noticed this in iOS 15.6.1 on my physical device. If I send the app to a physical device running iOS 15.5 everything worked fine. Once I updated the device to iOS 15.6.1 or higher the change in firing order broke the ability to get the keyboard height when the textView was first tapped. It's happening on both iPad and iPhone.
In Xcode 13.4.1, iOS 15.5 and before. keyboardWillShow fired then textViewDidBeginEditing fired after. This allowed to get the keyboard height before the textView became active and thus move the textView up the proper amount.
In Xcode 14.0.1, or anything above iOS 15.5. textViewDidBeginEditing fires then keyboardWillShow fires after.
So if you're moving the textview up to clear the keyboard it won't work right anymore because you won't get the keyboard height until after the textView has become firstResponder.
The firing order was also changed for textFields.
I thought about hard-coding in the keyboard heights for each device but that really doesn't make sense. That and what if Apple changes the keyboard height.
I have filed a bug report but so far no response. If you're using notificationCenter to get the keyboard height please check if your app is broken too. If so, please file a bug report so we can get some traction. I have several apps I'm waiting to release and this is holding me up.
You can use the code below to check the before and after firing order. Keep in mind that the textView delegate needs to be the view.
In viewDidLoad I have this.
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
The selector for NotificationCenter.default.addObserver
// MARK: - get the keyboard height
@objc func keyboardWillShow(notification: NSNotification)
{
if let keyboardRectValue = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
{
print("keyboardHeight ran \(keyboardHeight)")
}
}
Then I have:
// MARK: - TextView Editing Begin.
func textViewDidBeginEditing(_ textView: UITextView)
{
print("textViewDidBeginEditing ran")
}
I'm setting up keyboard avoidance to a textview.
Objectives:
Use keyboardLayoutGuide.followsUndockedKeyboard
Allow for floating keyboard on iPad
Move the textView up to clear the keyboard when it's tapped
Move the textView back when the keyboard is hidden or when the textView is not firstResponder
View layout for testing:
Three controls.
A textField
A TextView
A UIView
The constraint on the bottom of the textView is 15 pts from the top of the UIView.
This constraint is set to a Priority of 750
The code I have works fine except when the iPad is rotated.
keyboardWillHideNotification fires when the rotation occurs even though the keyboard stays undocked.
This causes the textView to drop to its home position and then pop back up again. It's very goofy looking. The textView should hug the top of the keyboard.
I tried using textViewDidEndEditing instead of keyboardWillHide but that isn't much better.
Anybody have any ideas on making the textView hug the top of the keyboard when the iPad is rotated?
class ViewController: UIViewController, UITextViewDelegate
{
@IBOutlet weak var myTextView: UITextView!
private var buttomConstraint: NSLayoutConstraint!
override func viewDidLoad()
{
super.viewDidLoad()
myTextView.translatesAutoresizingMaskIntoConstraints = false
buttomConstraint = myTextView.bottomAnchor.constraint(equalTo: view.keyboardLayoutGuide.topAnchor)
view.keyboardLayoutGuide.followsUndockedKeyboard = true
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
hideKeyboard()
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
{
}
@objc func keyboardWillHide(notification: NSNotification)
{
print("Keyboard will hide")
if myTextView.isFirstResponder
{
UIView.animate(withDuration: 0.3) { [weak self] in
self?.buttomConstraint.isActive = false
self?.view.layoutIfNeeded()
}
} else {
print("Somethibg")
}
}
@objc func keyboardWillShow(notification: NSNotification)
{
if myTextView.isFirstResponder
{
UIView.animate(withDuration: 0.3) { [weak self] in
self?.buttomConstraint.isActive = true
self?.view.layoutIfNeeded()
}
} else {
buttomConstraint.isActive = false
}
}
func textViewDidBeginEditing(_ textView: UITextView)
{
// UIView.animate(withDuration: 0.3) { [weak self] in
// self?.buttomConstraint.isActive = true
// self?.view.layoutIfNeeded()
// }
}
func textViewDidEndEditing(_ textView: UITextView)
{
// UIView.animate(withDuration: 0.3) { [weak self] in
// self?.buttomConstraint.isActive = false
// self?.view.layoutIfNeeded()
// }
}
}
extension ViewController
{
// MARK: This dismisses the keyBoard when the view it tapped
func hideKeyboard()
{
let tap: UITapGestureRecognizer = UITapGestureRecognizer(
target: self,
action: #selector(ViewController.dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
@objc func dismissKeyboard()
{
view.endEditing(true)
}
}
I'm trying to control what happens when the view background is tapped.
The view has a field, a button and a list collectionView.
When the user enters a name into the field, the button is enabled and when the button is tapped the name from the field is saved into a list collectionView.
What I want to happen:
If the field isFirstResponder when the viewBackGround is tapped then I want the superView_Tapped() to be triggered.
If the collectionView is tapped it works fine.
If the view background is tapped it works fine.
When the view backGround is tapped the field text is cleared and sone other things take place. See superView_Tapped() below.
What actually happens:
The problem I'm having is that tapping the button also triggers the superView_Tapped().
So what happens is the field is emptied and a row is inserted into the collection view with no name.
The part of the reason is that the superView_Tapped() is fired first and then the button code fires after.
Is there a way to exclude the button tap from triggering the superView_Tapped()?
let tap = UITapGestureRecognizer(target: self, action: #selector(self.superView_Tapped))
tap.numberOfTapsRequired = 1
tap.delegate = self
tap.cancelsTouchesInView = false
self.view.addGestureRecognizer(tap)
@objc func superView_Tapped()
{
if insertFld.isFirstResponder
{
insertFld.resignFirstResponder()
insertFld.text = ""
insertButton.isEnabled = false
// print("They emptied the fld when editing", gItemID)
gItemID = 0
insertButton.filled_Red_Back(title: K.Titles.add_Btn)
theOriginal_Text = ""
}
}
@IBAction func insertButton_Tapped(_ sender: UIButton)
{
if current_Item_ID != 0
{
update()
} else {
insertRow()
}
}
func update()
{
let theItemName = insertFld.text
do {
try dbQueue_GRDB.write { db in
try db.execute(sql: "UPDATE " + theTable + " SET Item_Name = :item_Name WHERE ItemID = :id",
arguments: ["item_Name": theItemName, "id": current_Item_ID])
}
applySnapshot()
clean_Up()
if ModelData.getTheConfirmation_Bool()
{
sendConfirmationAlert(theTitle: "Updated", theMessage: nil, buttonTitle: K.Titles.ok)
}
} catch {
let theString = "\(error)"
if theString.contains("UNIQUE constraint failed")
{
sendConfirmationAlert(theTitle: K.Titles.itemAlreadyExists, theMessage: nil, buttonTitle: K.Titles.ok)
} else {
print("Updating list failed! \(VC_String) \(error)")
}
}
}
func insertRow()
{
let insertName = insertFld.text?.trimmingCharacters(in: .whitespaces)
do {
try dbQueue_GRDB.write { db in
try db.execute(sql: "INSERT INTO " + theTable + " (Item_Name,Practice,Training,Practice_Log) VALUES (?,?,?,?)",
arguments: [insertName,"false","",""])
}
if ModelData.getTheConfirmation_Bool()
{
sendConfirmationAlert(theTitle: "Row Created", theMessage: nil, buttonTitle: K.Titles.ok)
}
applySnapshot()
clean_Up()
} catch {
let theString = "\(error)"
if theString.contains("UNIQUE constraint failed")
{
sendConfirmationAlert(theTitle: K.Titles.itemAlreadyExists, theMessage: nil, buttonTitle: K.Titles.ok)
} else {
print("Inserting to list failed! \(VC_String) \(error)")
}
}
}
I have an app that was written in UIKit. It's too large, and it would be much too time consuming at this point to convert it to SwiftUI.
I want to incorporate the new limited contacts into this app. The way it's currently written everything works fine except for showing the limited contacts in the contact picker.
I have downloaded and gone though the Apple tutorial app but I'm having trouble thinking it through into UIKit. After a couple of hours I decided I need help.
I understand I need to pull the contact IDs of the contacts that are in the limited contacts list. Not sure how to do that or how to get it to display in the picker. Any help would be greatly appreciated.
func requestAccess(completionHandler: @escaping (_ accessGranted: Bool) -> Void)
{
switch CNContactStore.authorizationStatus(for: .contacts)
{
case .authorized:
completionHandler(true)
case .denied:
showSettingsAlert(completionHandler)
case .restricted, .notDetermined:
CNContactStore().requestAccess(for: .contacts) { granted, error in
if granted
{
completionHandler(true)
} else {
DispatchQueue.main.async { [weak self] in
self?.showSettingsAlert(completionHandler)
}
}
}
// iOS 18 only
case .limited:
completionHandler(true)
@unknown default: break
}
}
// A text field that displays the name of the chosen contact
@IBAction func contact_Fld_Tapped(_ sender: TextField_Designable)
{
sender.resignFirstResponder()
// The contact ID that is saved to the Db
getTheCurrentContactID()
let theAlert = UIAlertController(title: K.Titles.chooseAContact, message: nil, preferredStyle: .actionSheet)
// Create a new contact
let addContact = UIAlertAction(title: K.Titles.newContact, style: .default) { [weak self] _ in
self?.requestAccess { _ in
let openContact = CNContact()
let vc = CNContactViewController(forNewContact: openContact)
vc.delegate = self // this delegate CNContactViewControllerDelegate
DispatchQueue.main.async {
self?.present(UINavigationController(rootViewController: vc), animated: true)
}
}
}
let getContact = UIAlertAction(title: K.Titles.fromContacts, style: .default) { [weak self] _ in
self?.requestAccess { _ in
self?.contactPicker.delegate = self
DispatchQueue.main.async {
self?.present(self!.contactPicker, animated: true)
}
}
}
let editBtn = UIAlertAction(title: K.Titles.editContact, style: .default) { [weak self] _ in
self?.requestAccess { _ in
let store = CNContactStore()
var vc = CNContactViewController()
do {
let descriptor = CNContactViewController.descriptorForRequiredKeys()
let editContact = try store.unifiedContact(withIdentifier: self!.oldContactID, keysToFetch: [descriptor])
vc = CNContactViewController(for: editContact)
} catch {
print("Getting contact to edit failed: \(self!.VC_String) \(error)")
}
vc.delegate = self // delegate for CNContactViewControllerDelegate
self?.navigationController?.isNavigationBarHidden = false
self?.navigationController?.navigationItem.hidesBackButton = false
self?.navigationController?.pushViewController(vc, animated: true)
}
}
let cancel = UIAlertAction(title: K.Titles.cancel, style: .cancel) { _ in }
if oldContactID.isEmpty
{
editBtn.isEnabled = false
}
theAlert.addAction(getContact) // Select from contacts
theAlert.addAction(addContact) // Create new contact
theAlert.addAction(editBtn) // Edit this contact
theAlert.addAction(cancel)
let popOver = theAlert.popoverPresentationController
popOver?.sourceView = sender
popOver?.sourceRect = sender.bounds
popOver?.permittedArrowDirections = .any
present(theAlert,animated: true)
}
func requestAccess(completionHandler: @escaping (_ accessGranted: Bool) -> Void)
{
switch CNContactStore.authorizationStatus(for: .contacts)
{
case .authorized:
completionHandler(true)
case .denied:
showSettingsAlert(completionHandler)
case .restricted, .notDetermined:
CNContactStore().requestAccess(for: .contacts) { granted, error in
if granted
{
completionHandler(true)
} else {
DispatchQueue.main.async { [weak self] in
self?.showSettingsAlert(completionHandler)
}
}
}
// iOS 18 only
case .limited:
completionHandler(true)
@unknown default: break
}
}
// MARK: - Contact Picker Delegate
extension AddEdit_Quote_VC: CNContactPickerDelegate
{
func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact)
{
selectedContactID = contact.identifier
let company: String = contact.organizationName
let companyText = company == "" ? K.Titles.noCompanyName : contact.organizationName
contactNameFld_Outlet.text = CNContactFormatter.string(from: contact, style: .fullName)!
companyFld_Outlet.text = companyText
save_Array[0] = K.AppFacing.true_App
setSaveBtn_AEQuote()
}
}
extension AddEdit_Quote_VC: CNContactViewControllerDelegate
{
func contactViewController(_ viewController: CNContactViewController, shouldPerformDefaultActionFor property: CNContactProperty) -> Bool
{
return false
}
func contactViewController(_ viewController: CNContactViewController, didCompleteWith contact: CNContact?)
{
selectedContactID = contact?.identifier ?? ""
if selectedContactID != ""
{
let company: String = contact?.organizationName ?? ""
let companyText = company == "" ? K.Titles.noCompanyName : contact!.organizationName
contactNameFld_Outlet.text = CNContactFormatter.string(from: contact!, style: .fullName)
companyFld_Outlet.text = companyText
getTheCurrentContactID()
if selectedContactID != oldContactID
{
save_Array[0] = K.AppFacing.true_App
setSaveBtn_AEQuote()
}
}
dismiss(animated: true, completion: nil)
}
}
This is on an approved app that has an in-app purchase. It was released with hosting turned off which is correct. I did a rev to the app. In the rev I mindlessly changed the in-app purchase and turned hosting on. I thought I was working on a different app. Anyway, I have tried to set it back and turn hosting off but it won't let me save. Now, on the same IAP, I have two status. I thought about deleting the existing IAP and creating a new one but the option to delete is not available. I thought about adding a new IAP and using it but that does not get rid of the Waiting for Upload IAP. Has anybody seen something like this and know how to resolve it. Is there a way to get someone with system level authority to help? Thanks for the help in advance.
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect
Tags:
App Store Connect
In-App Purchase
I'm setting up auto layout constraints and I want the leading constraint of one of the controls on the view to be a fixed value on iPhone (CR) and equal to a % of the screen width for iPad. Can this be done in IB using the size inspector or does it need to be done programmatically? I've searched for documentation and looked at lots of videos but I was unable locate the information. If someone could provide a link to the documentation or share some sample code, I would be very grateful.
I my app I have four steppers and each has a related field. I have the stepValue of each stepper set to 0.1. The associated fields are editable, and I have them set to have a trailing 0 when editing ends.
Everything works fine. The stepper increments at 0.1 and populates the field. When the field edited ends it has a trailing 0. The problem is that the stepper does not have a trailing zero on the whole number.
So, with the stepper, I get 0.8, 0.9, and then 1 with no training 0, hen 1.1.
How can I make sure I have a trailing 0 with the whole numbers?
@IBAction func editing_Ended_Flds(_ sender: UITextField)
{
let stringValue: String = sender.text ?? ""
if let value = Double(stringValue)
{
sender.text = "\(String(format: "%.1f", value))"
}
}
@IBAction func editingChanged_Flds(_ sender: UITextField)
{
switch sender
{
case fade_In_Fld_Outlet:
fade_In_stepper_Outlet.value = Double(sender.text!) ?? 0.0
case fade_Out_Fld_Outlet:
fade_Out_stepper_Outlet.value = Double(sender.text!) ?? 0.0
case pause_Before_Fld_Outlet:
pause_Before_stepper_Outlet.value = Double(sender.text!) ?? 0.0
case pause_After_Fld_Outlet:
pause_After_stepper_Outlet.value = Double(sender.text!) ?? 0.0
default: break
}
}
@IBAction func stepper_Tapped(_ sender: UIStepper)
{
switch sender
{
case fade_In_stepper_Outlet:
fade_In_Fld_Outlet.text = Double(sender.value).formatted()
case fade_Out_stepper_Outlet:
fade_Out_Fld_Outlet.text = Double(sender.value).formatted()
case pause_Before_stepper_Outlet:
pause_Before_Fld_Outlet.text = Double(sender.value).formatted()
case pause_After_stepper_Outlet:
pause_After_Fld_Outlet.text = Double(sender.value).formatted()
default: break
}
}
I have a question regarding multiple in-app purchases. I want to release my app with one in-app purchase however, I want to add two more at a later release. Currently I have all three in-app purchases set up in the app, but only one is set on the prepare for submission screen under In-App Purchases and Subscriptions.
My question is, are these additional in-app purchases going to cause a problem with my initial release? Should I delete them and just add them later with the next rev?
I'm updating my apps to iOS 17 and in Xcode 14 this code worked perfectly. However, Xcode 15 decided it wasn't going to let it work anymore.
What I want to accomplish is to set the title of the button to be white and the icon to be blue. In other words, I want to control the color of both items separately.
I'd also like to know how to set the disabled color of the button using configurations.
I've tried using baseBackgroundColor and baseForegroundColor but it doesn't seem to make any difference.
In interface builder, the button is bone stock with no attributes except the title text. (system, plain, plain)
I've tried .plain(), .tinted(), .borderless() and commenting the line out but noting gives me what I need.
Any help would be greatly appreciated.
` extension UIButton
{
func settingsBtn_Attributes()
{
self.configuration = .plain()
self.configuration?.image = UIImage(systemName: K.Icons.settings, withConfiguration: UIImage.SymbolConfiguration(scale: .large))
self.configuration?.title = K.Tabbar_Names.settings
self.configuration?.attributedTitle?.foregroundColor = .white
self.configuration?.imagePlacement = .top
self.configuration?.titleAlignment = .center
self.configuration?.imagePadding = 6
self.configuration?.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)
self.configuration?.attributedTitle?.font = .systemFont(ofSize: gMenuTextSize, weight: .regular)
}
}`
I use the code below for a non-consumable in-app purchase in my apps. Has anybody worked out how to handle this without using any of the deprecated items?
SKPaymentQueue - deprecated,
SKPayment - deprecated,
SKProduct - deprecated,
transactionState - deprecated,
SKPaymentTransaction - deprecated,
finishTransaction - deprecated
func paymentQueue(_ queue: SKPaymentQueue, shouldAddStorePayment payment: SKPayment, for product: SKProduct) -> Bool
{
true
}
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction])
{
for transaction in transactions
{
switch transaction.transactionState
{
case .purchasing:
break
case .purchased:
SKPaymentQueue.default().finishTransaction(transaction)
// Hide the restore button
navigationItem.setRightBarButton(nil, animated: true)
// Set the ProVerion in the Db to true
IAPHandler.setProVersionToPurchased()
// Also hide the Purchase button
UIView.animate(withDuration: 1.0, animations: { [weak self] in
self?.purchaseBtn_Outlet.alpha = 0
}) { [weak self] (success) in
if self!.theDevice.isOneOf(K.Device_Groups.SE_3_iPhone8) {
self?.segControlTop_Constraint.constant = 10
} else if self!.theDevice.isPhone {
self?.segControlTop_Constraint.constant = 30
}
}
case .failed:
if let error = transaction.error
{
let errorDescription = error.localizedDescription
print("Transaction failed due to error: \(errorDescription)")
}
case .restored:
SKPaymentQueue.default().finishTransaction(transaction)
// Hide the restore button
navigationItem.setRightBarButton(nil, animated: true)
// Set the ProVerion in the Db to true
IAPHandler.setProVersionToPurchased()
// Also hide the Purchase button
UIView.animate(withDuration: 1.0, animations: { [weak self] in
self?.purchaseBtn_Outlet.alpha = 0
}) { [weak self] (success) in
if self!.theDevice.isOneOf(K.Device_Groups.SE_3_iPhone8) {
self?.segControlTop_Constraint.constant = 10
} else if self!.theDevice.isPhone {
self?.segControlTop_Constraint.constant = 30
}
}
case .deferred:
break
@unknown default:
if let error = transaction.error
{
let errorDescription = error.localizedDescription
print("Transaction failed due to error: \(errorDescription)")
}
break
}
}
}
// Sets the purchase to true in the Db
class IAPHandler: NSObject {
//Get the ProVersion Status
static func isProVersionPurchased() -> Bool
{
let VC_String = "IAPHandler"
var theStatus = false
do {
let settings = try Database.shared.databaseConnection!.read { db in
try My_Settings.fetchOne(db)
}
let theStatusText = settings?.ProVersion ?? "false"
theStatus = theStatusText == "true" ? true : false
} catch {
print("Getting the ProVersion Status failed! \(VC_String) \(error)")
}
return theStatus
}
// Set ProVersion to true.
static func setProVersionToPurchased()
{
let VC_String = "IAPHandler"
do {
try Database.shared.databaseConnection!.write { db in
try db.execute(sql: "UPDATE My_Settings SET ProVersion = :proVersion WHERE Settings_ID = :id",
arguments: ["proVersion": "true", "id": 1])
}
} catch {
print("Update set pro version, failed! \(VC_String)s \(error)")
}
}
}// End of class