Hello,
In the documentation for an ARView we see a diagram that shows that all Entity's are connected via AnchorEntity's to the Scene:
https://developer.apple.com/documentation/realitykit/arview
What happens when we are using a RealityView? Here the documentation suggests we direclty add Entity's:
https://developer.apple.com/documentation/realitykit/realityview/
Three questions:
Do we need to add Entitys to an AnchorEntity first and add this via content.add(...)?
Is an Entity ignored by physics engine if attached via an Anchor?
If both the AnchorEntity and an attached Entity is added via content.add(...), does is its anchor's position ignored?
Post
Replies
Boosts
Views
Activity
Does anyone have any guidance / experience using TriggerVolumes to detect collision rather than the Physics engine in Reality Kit.
Aside from not participating the physics engine are there any other downside or upsides to using them?
I'm trying to detect when two entities collide. The following code shows a very basic set-up. How do I get the upperSphere to move? If I set its physicsBody.mode to .dynamic it moves with gravity (and the collision is reported), but when in kinematic mode it doesn't respond to the impulse:
struct CollisionView: View {
@State var subscriptions: [EventSubscription] = []
var body: some View {
RealityView { content in
let upperSphere = ModelEntity(mesh: .generateSphere(radius: 0.04))
let lowerSphere = ModelEntity(mesh: .generateSphere(radius: 0.04))
upperSphere.position = [0, 2, -2]
upperSphere.physicsBody = .init()
upperSphere.physicsBody?.mode = .kinematic
upperSphere.physicsMotion = PhysicsMotionComponent()
upperSphere.generateCollisionShapes(recursive: false)
lowerSphere.position = [0, 1, -2]
lowerSphere.physicsBody = .init()
lowerSphere.physicsBody?.mode = .static
lowerSphere.generateCollisionShapes(recursive: false)
let sub = content.subscribe(to: CollisionEvents.Began.self, on: nil) { _ in print("Collision!") }
subscriptions.append(sub)
content.add(upperSphere)
content.add(lowerSphere)
Task {
try? await Task.sleep(for: .seconds(2))
print("Impulse applied")
upperSphere.applyLinearImpulse([0, -1, 0], relativeTo: nil)
}
}
}
}
Xcode is not not picking up when I make changes to my unit test files when running tests. The only way is to clean the whole project and rebuild again. Any ideas why?
I recently tried Xcode cloud and this behaviour started after removing that option
How does one add Codable conformance to a class that needs to be isolated to the MainActor?
For example, the following code gives compiler errors:
@MainActor final class MyClass: Codable {
var value: Int
enum CodingKeys: String, CodingKey {
case value
}
init(from decoder: Decoder) throws { // <-- Compiler error: Initializer 'init(from:)' isolated to global actor 'MainActor' can not satisfy corresponding requirement from protocol 'Decodable'
let data = try decoder.container(keyedBy: CodingKeys.self)
self.value = try data.decode(Int.self, forKey: .value)
}
func encode(to encoder: Encoder) throws { // <-- Compiler error: Instance method 'encode(to:)' isolated to global actor 'MainActor' can not satisfy corresponding requirement from protocol 'Encodable'
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(value, forKey: .value)
}
}
I'm definitely struggling to get my head around actors and @MainActor at the moment!
I am building a tokeniser, and would like to hold this as a struct, passing in a locale during initiation.
Here's the gist of what I would want to write:
struct Tokeniser {
private let locale: Locale
private let integerRegex: Regex
init(locale: Locale) {
self.locale: Locale
self.integerRegex = Regex {
Capture {
.localizedInteger(locale: locale)
} transform: {
Token.number($0)
}
}
}
func parse(text: String) -> Token {
if let match = try integerRegex.firstMatch(in: text) {
//... other code here
}
}
\\...other code here
}
As Regex is generic the compiler suggests to set the integerRegex's type to Regex<Any>, but this triggers another set of compiler issues that I have not been able to figure out what the type should be. So then I tried to write something like this (inspired by SwiftUI):
var integerRegex: some Regex {
Capture {
.localizedInteger(locale: locale)
} transform: {
Token.number($0)
}
}
But again, the compiler prompts me to enter Regex.
The only way I have to be able to get the struct to compiler is to create lazy variables, which then have the side effect that I have to mark my functions as mutable, which have downstream issues when they are called from with SwiftUI structs.
lazy var integerRegex = Regex {
Capture {
.localizedInteger(locale: locale)
}
}
mutating func parse(text: String) -> Token {
if let match = try integerRegex.firstMatch(in: text) {
}
}
How can I code this?
Given that type UUID is a struct I thought it would be Sendable. But the compiler generates a warning:
struct S: Sendable {
var int: Int
var id: UUID // <-- Stored property 'id' of 'Sendable'-conforming struct 'S' has non-sendable type 'UUID'
}
I'm developing across two Macs: one Apple Silicon and an Intel laptop (used for performance and compatibility testing).
I've been testing my StoreKit2 implementation, and have come across a couple of issues.
From time to time something appears to become corrupted, and StoreKit2 says it has a 'connection' issue. Deleting the folder com.apple.storekitagent, which a sub folder Octane, restarting the machine appears to fix this.
The second issue I cannot appear to resolve. I have needed to change the App Bundle ID. I did this whilst developing on the M2 Mac without problem. But now when I try and run back on the Intel Mac I am getting a set of unfinished transactions which I can either process, nor delete (they are not appearing in Xcode's StoreKit debug window. I've tried deleting the folder com.apple.storekitagent, and restarting the machine, but to no avail.
Note if I reset back to my original App Bundle ID then all works as before.
Here is a sample of errors I am receiving:
Error finishing transaction 110: Error Domain=ASDErrorDomain Code=500 "Unhandled exception" UserInfo={NSUnderlyingError=0x600001863cf0 {Error Domain=AMSErrorDomain Code=301 "Invalid Status Code" UserInfo={NSLocalizedDescription=Invalid Status Code, AMSURL=http://localhost:49242/WebObjects/MZFinance.woa/wa/inAppTransactionDone?REDACTED, AMSStatusCode=404, AMSServerPayload={
error = "Transaction not found";
}, NSLocalizedFailureReason=The response has an invalid status code}}, storefront-country-code=USA, client-environment-type=XcodeTest(file:///Users/peggers/Library/Caches/com.apple.storekitagent/Octane/com.bristolbaycodefactory.photo-organista/), AMSServerErrorCode=0, NSLocalizedFailureReason=An unknown error occurred, NSLocalizedDescription=Unhandled exception}
Any further ideas on how to reset or solve this issue?
I'm writing a photo management app where the document stores the location of folders (in which image files reside). These are added by the user, and saved as security scoped bookmarks. All this appeared to be working.
However, I tested a use-case where the user starts working on one machine where they add a folder, which resides on an external drive. This works, as long as they remain the on the same machine.
However, if they move to another machine, plug in the external drive and then load up the document it fails to resolve the bookmark, throws the following error:
Error Domain=NSCocoaErrorDomain Code=259 "The file couldn’t be opened because it isn’t in the correct format."
For completeness here is the code to resolve the bookmark:
do {
let url = try URL(
resolvingBookmarkData: data,
options: Self.bookmarkResolutionOptions,
relativeTo: nil,
bookmarkDataIsStale: &isStale
)
} catch {
print(error)
/// ... error handling code here
}
Do I therefore assume that I cannot achieve this, and will have to ask the user to re-authorise this folder on the second machine?
When I run my code with TSAN enabled I am getting an EXC_BAD_ACCESS exception thrown.
I am seeing the following error in debug navigator:
#0 0x0000000104becb44 in __tsan::ThreadClock::release(__tsan::DenseSlabAllocCache*, __tsan::SyncClock*) ()
The stack trace is not in my code.
Without TSAN I am seeing the following in the console:
(Fig) signalled err=-16993
Anybody seen this before?
This is under the new Beta 6 Xcode running under Ventura 13.0 Beta (22A5331f), on an M1 Mac.
Assuming I have defined a global actor:
@globalActor actor MyActor {
static let shared = MyActor()
}
And I have a class, in which a couple of methods need to act under this:
class MyClass {
@MyActor func doSomething(undoManager: UndoManager) {
// Do something here
undoManager?.registerUndo(withTarget: self) {
$0.reverseSomething(undoManager: UndoManager)
}
}
@MyActor func reverseSomething(undoManager: UndoManager) {
// Do the reverse of something here
print(\(Thread.isMainThread) /// Prints true when called from undo stack
undoManager?.registerUndo(withTarget: self) {
$0.doSomething(undoManager: UndoManager)
}
}
}
Assume the code gets called from a SwiftUI view:
struct MyView: View {
@Environment(\.undoManager) private var undoManager: UndoManager?
let myObject: MyClass
var body: some View {
Button("Do something") { myObject.doSomething(undoManager: undoManager) }
}
}
Note that when the action is undone the 'reversing' func it is called on the MainThread. Is the correct way to prevent this to wrap the undo action in a task? As in:
@MyActor func reverseSomething(undoManager: UndoManager) {
// Do the reverse of something here
print(\(Thread.isMainThread) /// Prints true
undoManager?.registerUndo(withTarget: self) {
Task { $0.doSomething(undoManager: UndoManager) }
}
}
The XCODE TSAN thread analyser is throwing up a threading issue:
Data race in generic specialization <Foundation.UUID> of Swift._NativeSet.insertNew(_: __owned τ_0_0, at: Swift._HashTable.Bucket, isUnique: Swift.Bool) -> () at 0x10a16b300
This only occurs in a release build, and its Data race in generic specialization that has my attention.
It pin-points the addID function. But I cannot see the issue. Here is the relevant code snippet:
final class IDBox {
let syncQueue = DispatchQueue(label: "IDBox\(UUID().uuidString)", attributes: .concurrent)
private var _box: Set<UUID>
init() {
self._box = []
}
var box: Set<UUID> {
syncQueue.sync {
self._box
}
}
func addID(_ id: UUID) {
syncQueue.async(flags: .barrier) {
self._box.insert(id)
}
}
}
I'm getting a lot of output on the console as I run a MacOS based SwiftUI app I'm developing, for example:
2021-12-08 12:40:14.439565+0000 SpDriveApp[6801:159299] [] [0x7fe6e7830820] CVCGDisplayLink::setCurrentDisplay: 1892262333
2021-12-08 12:40:14.439785+0000 SpDriveApp[6801:159299] [] [0x7fe6e7830800] CVDisplayLinkCreateWithCGDisplays count: 1 [displayID[0]: 0x70c9a1bd] [CVCGDisplayLink: 0x7fe6e7830820]
2021-12-08 12:40:14.439827+0000 SpDriveApp[6801:159299] [] [0x7fe6e7830800] CVDisplayLinkStart
2021-12-08 12:40:14.439853+0000 SpDriveApp[6801:159299] [] [0x7fe6e7830820] CVDisplayLink::start
2021-12-08 12:40:14.439993+0000 SpDriveApp[6801:182706] [] [0x60000f698460] CVXTime::reset
Has anyone else seen this? Have I accidentally switched on a diagnostic tool, or is there something else I am doing wrong?
I am writing an App with both Mac and iPad versions that saves its state to a file. The user can store the file in their iCloud and open it both on the Mac and iPad simultaneously. If an update is made on either device the other will update their state to match.
This has been achieved using an NSFilePresenter / NSFileCoordinator approach. Both platforms are using identical code.
At present when I make a change on the iPad, a few moments later the Mac updates as expected.
However, this does not happen the other way around. If I update the data on the Mac the iPad never appears to receive an update.
I've tried this on the simulator also. I get similar behaviour, but can get the iPad to update it I use the simulator's Sync With iCloud function.
Any ideas of what I may be doing wrong - as clearly the code works in one direction!
I'm writing a function where a directory and its descendants are scanned to produce a list of files. The function is part of a class, FileScanner. Here's a simplified version of the function:
func scanFolder(_ folderURL: URL) async {
// Set up configuration for directory search, varies based on need to search sub directories
let resourceKeysArray: [URLResourceKey] = [.nameKey, .isDirectoryKey, .fileResourceTypeKey, .creationDateKey, .contentModificationDateKey, .contentTypeKey]
let resourceKeysSet = Set<URLResourceKey>(resourceKeysArray)
let options = FileManager.DirectoryEnumerationOptions(arrayLiteral: [.skipsHiddenFiles, .skipsPackageDescendants])
if let enumerator = FileManager.default.enumerator(at: folderURL, includingPropertiesForKeys: resourceKeysArray, options: options) {
await folderScanStatus.markRunning()
while
await !folderScanStatus.cancelled,
let fileURL = enumerator.nextObject() as? URL
{
print("\(id) found \(fileURL.path)") // Logging for debug purposes
foundFiles.append(fileURL)
}
}
}
The code is async, as it has to call some async functions (I've left a couple in for illustration.)
The user can have multiple scans in process simultaneously. For each one a new FileScanner is created, and de-inited once the scan has completed - the results are copied across elsewhere. scanFolder is called from within a Task:
Task { await scanFolder(someURL) }
I am finding that if two of these processes run at once, they can actually interfere with each other - i.e. one can scan the directory of the other.
I added some logging to highlight the issue. The log line shows the ID of the scanner, and the file it has found. In this run there were two scanners:
EDF43558-608E-47A4-81E5-97B9707B1D0F, scanning /Volumes/Back-up A/
982EC712-D79E-4785-A1BA-3B53F85967F0, scanning /Users/TEST/
And here's some extracts from the log showing them working as expected:
982EC712-D79E-4785-A1BA-3B53F85967F0 found /Users/TEST/Files/R_24_04-04.txt
EDF43558-608E-47A4-81E5-97B9707B1D0F found /Volumes/Back-up A/180704f01.txt
And here's an example showing Scanner 982EC712-D79E-4785-A1BA-3B53F85967F0 finding a file that the other one also picked up:
982EC712-D79E-4785-A1BA-3B53F85967F0 found /Volumes/Back-up A/19839f92.txt
:
EDF43558-608E-47A4-81E5-97B9707B1D0F found /Volumes/Back-up A/19839f92.txt
Any ideas why this is happening? I was under the impression FileManager was thread safe?