I have a widget that opens my app via a custom url scheme (myapp:some-deep-link). In my app I have a handler setup like so:
var body: some Scene {
WindowGroup {
ContentView()
.onOpenURL(perform: { url in
//my code
}
}
}
In iOS 14 this works perfectly, in iOS 15 (Simulator) onOpenURL is not called at all. The app launches, but there is no call. I am wondering if this might be a simulator problem or a bug or something I am doing wrong. Any ideas?
Related
I am building an app with SwiftUI and would like to use requestReview() to display a review request popup. However, the popup is not displaying. From what I understand from the documentation, when the app is in development mode, the popup should display every time.
I've tested the app in the Xcode simulator and on a real device, I'm using Xcode 14.1. and the app builds without issue. (I'm also a SwiftUI newbie, I think I must be missing something obvious).
import SwiftUI
import StoreKit
struct DetailView: View {
#Environment(\.requestReview) var requestReview
#AppStorage("AppUsedCount") private var appUsedCount: Int = 0
var body: some View {
VStack {...}.onAppear{
let updatedAppUsedCount: Int = appUsedCount + 1
UserDefaults.standard.set(updatedAppUsedCount, forKey: "AppUsedCount")
if (appUsedCount > 5){
requestReview()
}
}
}
}
I also tested without the IF statement, but still no popup. appUsedCount updates as expected.
Thanks in advance!
I'm made an very basic iOS Widget Extension with (on iOS 16):
struct TotoView: View
var body: some View {
VStack {
Text("Toto")
.font(.headline)
}
}
}
struct TotoWidget: Widget {
var body: some WidgetConfiguration {
IntentConfiguration(kind: "myKind", intent: ViewTodayIntent.self, provider: TimelineProvider()) { entry in
TotoView(entry: entry)
}
.configurationDisplayName("Today work")
.description("Show today work sessions")
.supportedFamilies([.systemSmall, .systemMedium])
}
}
On the SwiftUI Canvas preview, I can see the "Toto" text.
BUT when I select the Widget Target and run in the simulator, I only have the placeholder in place of text. Any idea of why? Note that not only the text is replaced by placegholder but also an Image(systemName:)
I think the issue seems to be related by IntentConfiguration (as everything works fine with StaticConfiguration)
I'm on xCode 14.
In my Case it helped to change the Simulator. The Bug is still in my case on an iPhone 11 Simulator and on a real iPhone 11.
With other Simulators it works well.
Maybe its an issue with an iPhone 11.
I've found this strange behavior on ipad running ipados 14 (I've in both simulator and physical device installed 14.5, with 14.5.1 in the real one).
I need to show an icon badge with a number based on work made within the app, so there is no external push notification service involved in this.
I've set up a ViewModel that keep track of the number to show in the notification badge:
import Combine
import Foundation
class CounterViewModel: ObservableObject {
#Published private(set) var notificationCount = 42
func up() {
self.notificationCount += 1
}
func down() {
self.notificationCount -= 1
}
}
To publish this number on the notification badge on the app icon I'm using the .onAppear method of the contentView
struct ContentView: View {
#EnvironmentObject var counterViewModel: CounterViewModel
#State private var counterCancellable: AnyCancellable?
var body: some View {
Text("Hello World!")
.onAppear {
UNUserNotificationCenter.current().requestAuthorization(options: .badge) { _, error in
if error == nil {
self.counterCancellable = self.counterViewModel.$notificationCount.sink { count in
DispatchQueue.main.async {
UIApplication.shared.applicationIconBadgeNumber = count
}
}
}
}
}
}
}
Finally, the EnvironmentObject is set up on the app
struct IBreviaryApp: App {
#ObservedObject private var counterViewModel = CounterViewModel()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(self.counterViewModel)
}
}
}
so I can share on all the view involved in this count mechanism.
The problem: on the first run of the app, and only on the first one, after accepting the alert about authorising the notifications, when the app is put on background the badge within the icon is shown, but suddenly disappear. In the dock does not even show.
If I click the app (both on dock or on the "desktop") the badge appear in the animation that open the app.
If I scroll between the pages of installed applications and return to the one where my app is installed, the badge now is fixed. If I open another app, so the dock show this new app in the recent used app list, the badge appear here also (and stays this time).
Restarting the ipad or reinstalling the app fixes the problem, but itself remain for the first time you run the app.
EDIT: repo here: https://github.com/artecoop/badgebug
To actually make the problem arise, I needed to change the count number from another function.
EDIT 2:
Here's a video: https://youtu.be/tPWYRm5xFXI
As you may already see on the repo, to mimic another interaction, I've added a 5 second delay and then set 42 in the counter.
I'd like to port my existing UIKit App to use the new App API for iOS 14. (but still utilize the AppDelegate methods via UIApplicationDelegateAdaptor, however I would still like to support iOS 13. Is there a way I can set up so that if iOS 14, use the App as #main but if iOS 13 use AppDelegate as #UIApplicationMain? Even the below code won't compile as my minimum build target is iOS 13:
#available(iOS 14.0, *)
#main
struct HockeyTrackerApp: App {
// inject into SwiftUI life-cycle via adaptor !!!
#UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
HomeView()
}
}
}
I am developing an app that communicates between the watch and the iOS parent app. It sends data from the WatchKit extension to the parent application by opening it. I understand that openParentApplication:reply, when called, opens the iPhone application from the Apple Watch. After that, application:handleWatchKitExtension:reply is called in the app's delegate.
From there you can open a notification to the view controller with:
NSNotificationCenter.defaultCenter().postNotificationName(aName: String, object anObject: AnyObject?)
"aName" is what you can open up in the view conroller with:
NSNotificationCenter.defaultCenter().addObserver(self,
selector: Selector("handleWatchKitNotification:"),
name: "WatchKitSaysHello",
object: nil)
Here is my code for my interface controller in my WatchKit extension:
//
// InterfaceController.swift
// SendColors WatchKit Extension
//
// Created by Tommy on 12/30/14.
// Copyright (c) 2014 Tommy. All rights reserved.
//
import WatchKit
import Foundation
class InterfaceController: WKInterfaceController {
var ypo = false
override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
// Configure interface objects here.
}
#IBOutlet weak var redButton: WKInterfaceButton!
#IBOutlet weak var greenButton: WKInterfaceButton!
#IBOutlet weak var blueButton: WKInterfaceButton!
#IBAction func onRedButtonClick() {
if ypo {
openParentAppWithColor("Yellow")
}
else {
openParentAppWithColor("Red")
}
}
#IBOutlet weak var moreButton: WKInterfaceButton!
#IBAction func moreButtonClick() {
if !ypo {
ypo = true
redButton.setTitle("Yellow")
redButton.setColor(UIColor.yellowColor())
greenButton.setTitle("Purple")
greenButton.setColor(UIColor.purpleColor())
blueButton.setTitle("Orange")
blueButton.setColor(UIColor.orangeColor())
moreButton.setTitle("Back")
}
else {
ypo = false
redButton.setTitle("Red")
redButton.setColor(UIColor.redColor())
greenButton.setTitle("Green")
greenButton.setColor(UIColor.greenColor())
blueButton.setTitle("Blue")
blueButton.setColor(UIColor.blueColor())
moreButton.setTitle("More...")
}
}
#IBAction func onGreenButtonClick() {
if ypo {
openParentAppWithColor("Purple")
}
else {
openParentAppWithColor("Green")
}
}
#IBAction func onBlueButtonClick() {
if ypo {
openParentAppWithColor("Orange")
}
else {
openParentAppWithColor("Blue")
}
}
override func willActivate() {
// This method is called when watch view controller is about to be visible to user
super.willActivate()
}
override func didDeactivate() {
// This method is called when watch view controller is no longer visible
super.didDeactivate()
}
private func openParentAppWithColor(color: String) {
if ["color": color] != nil {
if !WKInterfaceController.openParentApplication(["color": color], reply: { (reply, error) -> Void in
println(reply)
}) {
println("ERROR")
}
}
}
}
My problem is that say for instance I clicked the red button on the watch simulator. The action would be called and in that action it calls openParentApplicationWithColor("Red") which would call WKInterfaceController.openParentApplication(["color": color], reply: { (reply, error) -> Void in }) What this is supposed to do is open the parent app on the simulator. It opens it in the background. I, therefore open it manually. When I open the app manually, the background is completely black. I suspect the problem is that I did not enable App Groups in the Capabilities tab. In order to do that, you need to be in the developer program. Should I join it to do this, or is there another problem? I am using Xcode 6.2 Beta 3. Thank you all in advance!
I have tested and can confirm that openParentApplication:reply: does not require App Groups to be enabled.
I understand that openParentApplication:reply, when called, opens the iPhone application from the Apple Watch.
This method opens the iPhone app in the background. In previous betas of Xcode 6.2 the app did open in the foreground, but this was not the intended behaviour and is not how the WatchKit Extension-iPhone app communication will work in the shipping version.
You can still launch the iPhone app in the foreground manually, but this isn't necessary unless you want to test the use case of both being used at once. At least with the API currently available, the iPhone app it can't be launched programmatically by the watch app to the foreground, and the watch app can't be launched programmatically by the iPhone app.
Once the app launches, you've reported the screen is still black when you expect it to change colour based on the message you've sent it. Is application:handleWatchKitExtension:reply: being called in the iPhone app? You will know it is definitely being called if you are receiving the reply block back for execution in your WatchKit Extension, which should be outputting something from your println(reply). If so, then the issue is with the code in the iPhone app to do something with the message you've passed to it. It would be useful to see your implementation of that method in your AppDelegate of the iPhone app. (Note if that method failed to call the reply block, it might still be receiving the message and you wouldn't get the reply, but then you would be seeing an error message about the reply not being received.)
Note that you won't see NSLog messages or get breakpoints in Xcode when running the Watch extension initially, but you can select Debug > Attach to process > [select your iPhone app under 'Likely targets'] and then you will get the logs and breakpoints of the iPhone app instead of the Watch app, while still being able to use the Watch app in the watch simulator. Most useful for debugging.
No, you no need to make group enable to use ole parent application. you can make a request to open parent IOS application and waiting a reply from IOS App without setting the group app. You only need to setting the group app when you want to share data between watchkit app and IOS app using NSUserDefauts with suite name.
I am using Xcode 6.2 Beta 5. Select Debug > Attach to process > [select your iPhone app under likely targets is not working. I see the NSLogs for Watch extension but not in iPhone app delegate and view controller of iPhone app.