Post

Replies

Boosts

Views

Activity

Reply to App Intents and Entities without schemas
Yeah they’re limited. I if you have an intent that conforms to a schema, you probably also need to have an entity that conforms to that intent’s input. Implement transferable on your entity so it can be created by whatever data the system has available. Then you hope that the system makes it and passes it to your intent. After that, “File feedback” is what they tell us. I really expected the schemas to evolve over two years from when they got announced, but it does not appear they did.
Jun ’26
Reply to Can I import images into my app with App Intent Schemas?
Photo Asset Entity: @available(anyAppleOS 27.0, *) @AppEntity(schema: .photos.asset) public struct ImageEntity: AppEntity, Sendable { public static let defaultQuery = PhotoEntityQuery() public let id: FileEntityIdentifier var creationDate: Date? var location: GeoToolbox.PlaceDescriptor? var assetType: ImageEntityAssetType? var isFavorite: Bool var isHidden: Bool var hasSuggestedEdits: Bool var aperture: Double? var exposure: Double? var saturation: Double? var warmth: Double? var filter: ImageEntityFilterType? var isPortraitModeEnabled: Bool? private var name: String? public var displayRepresentation: DisplayRepresentation { DisplayRepresentation( title: LocalizedStringResource(stringLiteral: name ?? "Photo"), image: .init(systemName: "photo") ) } init( id: FileEntityIdentifier, name: String?, creationDate: Date?, location: GeoToolbox.PlaceDescriptor? = nil, assetType: ImageEntityAssetType? = .photo, isFavorite: Bool = false, isHidden: Bool = false, hasSuggestedEdits: Bool = false, aperture: Double? = nil, exposure: Double? = nil, saturation: Double? = nil, warmth: Double? = nil, filter: ImageEntityFilterType? = nil, isPortraitModeEnabled: Bool? = nil ) { self.id = id self.name = name self.creationDate = creationDate self.location = location self.assetType = assetType self.isFavorite = isFavorite self.isHidden = isHidden self.hasSuggestedEdits = hasSuggestedEdits self.aperture = aperture self.exposure = exposure self.saturation = saturation self.warmth = warmth self.filter = filter self.isPortraitModeEnabled = isPortraitModeEnabled } var fileURL: URL? { get async throws { try await id.fileURL } } } @available(anyAppleOS 27.0, *) public struct PhotoEntityQuery: EntityStringQuery { enum Errors: Error { case unableToRetrieveURL } public init() {} public func entities(matching string: String) async throws -> [ImageEntity] { [] } public func entities(for identifiers: [ImageEntity.ID]) async throws -> [ImageEntity] { if identifiers.isEmpty { return [] } var results: [(index: Int, entity: ImageEntity)] = [] results.reserveCapacity(identifiers.count) await withTaskGroup(of: (Int, ImageEntity)?.self) { group in for (index, id) in identifiers.enumerated() { group.addTask { do { let entity = try await constructEntity(for: id) return (index, entity) } catch { return nil } } } for await result in group { if let result { results.append(result) } } } results.sort { $0.index < $1.index } return results.map(\.entity) } private func constructEntity(for id: ImageEntity.ID) async throws -> ImageEntity { guard let url = try await id.fileURL else { throw Errors.unableToRetrieveURL } let attributes = try? FileManager.default.attributesOfItem(atPath: url.path()) let creationDate = attributes?[.creationDate] as? Date let assetType: ImageEntityAssetType = url.conforms(toAny: [.movie, .video]) ? .video : .photo return ImageEntity( id: id, name: url.lastPathComponent, creationDate: creationDate, assetType: assetType ) } } Add to album entity: @available(anyAppleOS 27.0, *) @AppIntent(schema: .photos.addAssetsToAlbum) public struct CopyToAPPNAMEAppIntent: AppIntent { public static let allowedExecutionTargets: IntentExecutionTargets = [.main] public static let title: LocalizedStringResource = "Copy to APP NAME" public static let description = IntentDescription("Copies an image to a specified gallery or inbox of APP NAME.") public init() {} @Parameter(title: "Images", description: "Images to copy", inputConnectionBehavior: .default) public var assets: [ImageEntity] @Parameter(title: "Gallery", optionsProvider: GalleryOptionsProvider()) public var album: GalleryEntity @MainActor public func perform() async throws -> some IntentResult { guard !assets.isEmpty else { throw $assets.needsValueError("Which assets do you want to copy?") } let services = APPServices.default let sourceItemInterface = services.makeSourceItemInterface() var transferDestination: TransferLocation? = nil switch album.type { case .gallery(let uri): if let gallerySourceItem = sourceItemInterface.getSourceItemByManagedObjectURI(uri, context: services.coreDataController.viewContext), let destination = TransferLocation(sourceItem: gallerySourceItem) { transferDestination = destination } case .inbox(let url): transferDestination = TransferLocation.url(url) } guard let transferDestination else { throw $album.needsValueError("Gallery not valid. Choose another and try again.") } for asset in assets { guard let assetURL = try await asset.fileURL else { throw $assets.needsValueError("One of the selected assets is not valid. Choose another and try again.") } let transfer = FileURLTransfer(assetURL, to: transferDestination, transferType: .copy) let _: Void = try await withCheckedThrowingContinuation { continuation in transfer.transfer { possibleError in if let error = possibleError { continuation.resume(throwing: error) } else { continuation.resume() } } } } return .result() } }
Topic: App Intents SubTopic:
App Intents & Siri Q&A
Jun ’26
Reply to MagSafe 4 LED physics
It took Apple 4 years to fix a design flaw with macbook keyboards that could be made useless by small crumbs. Unless you get lawsuits or several high-traffic blog publications to advocate for this feature, it probably won‘t happen. Keep in mind that Apple sells other devices that indicate battery levels that employ a two color method. They won’t ship an imaginary MagSafe4 with three colors unless they’re prepared to update their entire hardware lineup to three colors for consistency.
Topic: Design SubTopic: General
Jun ’26
Reply to Please make Siri a real search engine
Hello. If you are unable to use your hands are but able to view the screen, consider exploring the accessibility technology called “voice control”. It allows you to navigate the entire device via voice commands. Some third party apps will have better support than others but if you “show numbers” you should be able to work around some of implementation deficiencies you run across. —- Note: Voice Control is very rigid in the commands it accepts and the descriptions of items on the UI. Apple has announced that this will change this fall when they release an so fueled update to voice control. There are also rumors of a far more capable Siri being available this far as well, but if that doesn’t happen you should still receive the voice control updates.
Jun ’26
Reply to App Intents and Entities without schemas
Yeah they’re limited. I if you have an intent that conforms to a schema, you probably also need to have an entity that conforms to that intent’s input. Implement transferable on your entity so it can be created by whatever data the system has available. Then you hope that the system makes it and passes it to your intent. After that, “File feedback” is what they tell us. I really expected the schemas to evolve over two years from when they got announced, but it does not appear they did.
Replies
Boosts
Views
Activity
Jun ’26
Reply to Push new views to sidebar when using NavigationPath
Speaking from memory: I believe there is a navigationSplitView initializer that lets you specify each of the three columns manually. Maybe try dropping NavigationStacks in each of those spots to have more navigation control over them? It’s still an odd navigation experience, though. You may need to make your own!
Topic: UI Frameworks SubTopic: SwiftUI
Replies
Boosts
Views
Activity
Jun ’26
Reply to Can I import images into my app with App Intent Schemas?
Photo Asset Entity: @available(anyAppleOS 27.0, *) @AppEntity(schema: .photos.asset) public struct ImageEntity: AppEntity, Sendable { public static let defaultQuery = PhotoEntityQuery() public let id: FileEntityIdentifier var creationDate: Date? var location: GeoToolbox.PlaceDescriptor? var assetType: ImageEntityAssetType? var isFavorite: Bool var isHidden: Bool var hasSuggestedEdits: Bool var aperture: Double? var exposure: Double? var saturation: Double? var warmth: Double? var filter: ImageEntityFilterType? var isPortraitModeEnabled: Bool? private var name: String? public var displayRepresentation: DisplayRepresentation { DisplayRepresentation( title: LocalizedStringResource(stringLiteral: name ?? "Photo"), image: .init(systemName: "photo") ) } init( id: FileEntityIdentifier, name: String?, creationDate: Date?, location: GeoToolbox.PlaceDescriptor? = nil, assetType: ImageEntityAssetType? = .photo, isFavorite: Bool = false, isHidden: Bool = false, hasSuggestedEdits: Bool = false, aperture: Double? = nil, exposure: Double? = nil, saturation: Double? = nil, warmth: Double? = nil, filter: ImageEntityFilterType? = nil, isPortraitModeEnabled: Bool? = nil ) { self.id = id self.name = name self.creationDate = creationDate self.location = location self.assetType = assetType self.isFavorite = isFavorite self.isHidden = isHidden self.hasSuggestedEdits = hasSuggestedEdits self.aperture = aperture self.exposure = exposure self.saturation = saturation self.warmth = warmth self.filter = filter self.isPortraitModeEnabled = isPortraitModeEnabled } var fileURL: URL? { get async throws { try await id.fileURL } } } @available(anyAppleOS 27.0, *) public struct PhotoEntityQuery: EntityStringQuery { enum Errors: Error { case unableToRetrieveURL } public init() {} public func entities(matching string: String) async throws -> [ImageEntity] { [] } public func entities(for identifiers: [ImageEntity.ID]) async throws -> [ImageEntity] { if identifiers.isEmpty { return [] } var results: [(index: Int, entity: ImageEntity)] = [] results.reserveCapacity(identifiers.count) await withTaskGroup(of: (Int, ImageEntity)?.self) { group in for (index, id) in identifiers.enumerated() { group.addTask { do { let entity = try await constructEntity(for: id) return (index, entity) } catch { return nil } } } for await result in group { if let result { results.append(result) } } } results.sort { $0.index < $1.index } return results.map(\.entity) } private func constructEntity(for id: ImageEntity.ID) async throws -> ImageEntity { guard let url = try await id.fileURL else { throw Errors.unableToRetrieveURL } let attributes = try? FileManager.default.attributesOfItem(atPath: url.path()) let creationDate = attributes?[.creationDate] as? Date let assetType: ImageEntityAssetType = url.conforms(toAny: [.movie, .video]) ? .video : .photo return ImageEntity( id: id, name: url.lastPathComponent, creationDate: creationDate, assetType: assetType ) } } Add to album entity: @available(anyAppleOS 27.0, *) @AppIntent(schema: .photos.addAssetsToAlbum) public struct CopyToAPPNAMEAppIntent: AppIntent { public static let allowedExecutionTargets: IntentExecutionTargets = [.main] public static let title: LocalizedStringResource = "Copy to APP NAME" public static let description = IntentDescription("Copies an image to a specified gallery or inbox of APP NAME.") public init() {} @Parameter(title: "Images", description: "Images to copy", inputConnectionBehavior: .default) public var assets: [ImageEntity] @Parameter(title: "Gallery", optionsProvider: GalleryOptionsProvider()) public var album: GalleryEntity @MainActor public func perform() async throws -> some IntentResult { guard !assets.isEmpty else { throw $assets.needsValueError("Which assets do you want to copy?") } let services = APPServices.default let sourceItemInterface = services.makeSourceItemInterface() var transferDestination: TransferLocation? = nil switch album.type { case .gallery(let uri): if let gallerySourceItem = sourceItemInterface.getSourceItemByManagedObjectURI(uri, context: services.coreDataController.viewContext), let destination = TransferLocation(sourceItem: gallerySourceItem) { transferDestination = destination } case .inbox(let url): transferDestination = TransferLocation.url(url) } guard let transferDestination else { throw $album.needsValueError("Gallery not valid. Choose another and try again.") } for asset in assets { guard let assetURL = try await asset.fileURL else { throw $assets.needsValueError("One of the selected assets is not valid. Choose another and try again.") } let transfer = FileURLTransfer(assetURL, to: transferDestination, transferType: .copy) let _: Void = try await withCheckedThrowingContinuation { continuation in transfer.transfer { possibleError in if let error = possibleError { continuation.resume(throwing: error) } else { continuation.resume() } } } } return .result() } }
Topic: App Intents SubTopic:
App Intents & Siri Q&A
Replies
Boosts
Views
Activity
Jun ’26
Reply to My app stuck in waitting for review for 47 days
What is this app about? Apple is known for ignoring things they are about to release a competing feature for, or things they just don’t like. Unfortunately without government intervention or a successful lawsuit, you’re kinda stuck. Maybe one day we’ll be able to release apps without the app store like on mac, or other countries with alternate stores.
Replies
Boosts
Views
Activity
Jun ’26
Reply to MagSafe 4 LED physics
It took Apple 4 years to fix a design flaw with macbook keyboards that could be made useless by small crumbs. Unless you get lawsuits or several high-traffic blog publications to advocate for this feature, it probably won‘t happen. Keep in mind that Apple sells other devices that indicate battery levels that employ a two color method. They won’t ship an imaginary MagSafe4 with three colors unless they’re prepared to update their entire hardware lineup to three colors for consistency.
Topic: Design SubTopic: General
Replies
Boosts
Views
Activity
Jun ’26
Reply to Please make Siri a real search engine
Hello. If you are unable to use your hands are but able to view the screen, consider exploring the accessibility technology called “voice control”. It allows you to navigate the entire device via voice commands. Some third party apps will have better support than others but if you “show numbers” you should be able to work around some of implementation deficiencies you run across. —- Note: Voice Control is very rigid in the commands it accepts and the descriptions of items on the UI. Apple has announced that this will change this fall when they release an so fueled update to voice control. There are also rumors of a far more capable Siri being available this far as well, but if that doesn’t happen you should still receive the voice control updates.
Replies
Boosts
Views
Activity
Jun ’26