I found the constant for that status code. It's errSecMissingEntitlement. Not sure what entitlement to which it's referring. Xcode won't sign the App Clip if I manually add the keychain-access-groups entitlement to the App Clip. The App Groups are already set up. I have the com.apple.developer.parent-application-identifiers entitlement added to the App Clip. I tried adding the com.apple.developer.associated-appclip-app-identifiers to the full app manually. Nothing changed. wtf.
Post
Replies
Boosts
Views
Activity
I forgot to mention that I also ensured the iOS Deployment Target for both App and App Clip was set to 15.4 to ensure keychain sharing was allowed.
Still looking for some help
Nope... I post it to the feedback assistant site. They asked for a test case project, which I gave them, and I haven't heard anything back.
For the first part of this thread, the goal was just more efficient code. The assumption is that this:
func outerWrapper<S>(arg1: Any, arg2: String = "ignore me") throws -> AsyncTask<S> {
return theAsyncFunc(arg1: arg1, arg2: arg2)
}
is more efficient than this:
func outerWrapper<S>(arg1: Any, arg2: String = "ignore me") async throws -> S {
return await theAsyncFunc(arg1: arg1, arg2: arg2)
}
Negligibly so, sure. But I actually care about the efficiency of my code. It also makes for fewer edits in the migration to concurrency. If the former is not allowed in swift, so be it. Not a big deal. Was just curious and wanted to advocate.
For the second side note, the overall Task is run in a method of an ObservableObject, which serves as one of my view models and which is triggered by some user interaction with SwiftUI. The added complication is that the class inherits some functionality from NSObject and conforms to a protocol that is common to most of the models in my project. So:
class MyViewModel: NSObject, LoadingProtocol, SomeObjcDelegate {
@Published var loading: Bool = false
.....
func businessLogic() {
loading = true
Task {
do {
let result = try await someAsyncFunc(....)
await MainActor.run {
self.swiftUIStateVar = result.someValue
}
} catch {
await MainActor.run {
self.errorToDisplay = error
}
} finally {
await MainActor.run {
self.loading = false
}
}
}
}
}
And I agree that doing everything in the main actor is ideal, which is what I kind of assumed would be the case. And, if I'm not mistaken, I would be able to add the @MainActor modifier to the class definition to make it so... except for the inheritance. And the modifier prevented the class from conforming to the protocol.
The await someAsyncFunc(....) is ultimately async because it makes a URLSession dataTask call. At run time, when it returned, I got a purple warning/error about the code not running on the main actor, and the UI didn't update. As written above, it seems to work. But I posted just because I'm still new to the api and maybe there's a better way given the constraints of my situation.
And my critique, then, with my limited perspective, is that it should be main actor by default, and the declaration I would like to add would mark whatever can be pushed off to other actors: something like await method() on someClassOfActor. Arguably, each method in the call stack from someAsyncFunc down to just before the actual dataTask is quick enough to run on the main actor. And every step processing the returned data back up the call stack is also probably quick enough. So that, at least in my case, main actor by default without extra decorators would be sufficient.
PromiseKit, the package from which I'm migrating, essentially operates this way, dispatching each callback on the main queue by default unless instructed otherwise.
Kind of a side note, as I play with this more, it looks like I'm going to do this a lot because my SwiftUI view models currently have an inheritance hierarchy, so that they can't be actors until the whole code base is overhauled.
Task {
do {
let result = try await someAsyncFunc(....)
await MainActor.run {
self.swiftUIStateVar = result.someValue
}
} catch {
await MainActor.run {
self.errorToDisplay = error
}
}
}
What am I missing? Is there or can there be a way to run the Task's body on the main thread but send off the awaited call to background threads, like how it would work with asyncio in python?
@eskimo ....my bad. AsyncTask is a proposal for what I'd like to see if it didn't already exist.. It's just a placeholder for some declaration that would let the compiler know that await outerWrapper() is syntactical ok. I guess I could also write it like:
func outerWrapper<S>(arg1: Any, arg2: String = "ignore me") async throws -> S {
return theAsyncFunc(arg1: arg1, arg2: arg2)
}
where it still just avoids using the await keyword. But, in my mind, if the async keyword is used in the function signature, it's an error not to await any asynchronous tasks it calls (which is a common mistake in JS).
I'm not really looking to convert the task at all. I'm more looking to skip an await call in a call stack when a given function, outerWrapper in this case, only needs to await once as part of (each of) its return statement(s). In this case, if we can ensure the caller of outerWrapper makes an await call, then the task from theAsyncFunc can propagated up the call stack, and outerWrapper doesn't technically do anything asynchronously in its own function body.
Another way I'm thinking about it is returning an async let:
func outerWrapper<S>(arg1: Any, arg2: String = "ignore me") -> SomeAsyncTaskThing<S> {
async let result = theAsyncFunc(arg1: arg1, arg2: arg2)
return result
}
But it sounds like each function in the call stack must be async and must await all the async functions it calls. I can imagine this makes managing the call stack easier for debug purposes. So I get it.
oh... then hopefully it's obvious that you'd want to write something like, await outerWrapper(...)
Having a similar issue. Each server refreshes the token every 50 minutes. We also tend to send a burst of like 10 notifications in parallel tasks (on one of the servers). It'll work fine for some amount of time until we randomly get back an InvalidProviderToken response for each parallel job. Or at least it seems to be spurious. It could be the result of us pushing updates to the servers, which causes the server process to restart and a new token to be generated outside of the usual schedule. In any case, in response to InvalidProviderToken, the affected server will invalidate the current token, wait for the next attempt to send a push notification, and regenerate a token before sending that batch.
It seems like this doesn't solve the problem. The next batch also often gets InvalidProviderToken.
At this point, we don't know how to proceed. Having just regenerated a token, the documentation implies that we shouldn't generate a new one. As such, we wait a couple of minutes before regenerating a new one, using the bad token in the mean time.
Nevertheless, we still end up getting the 429 occasionally, too.
What's the right algorithm for responding to these error codes???