Explore the various UI frameworks available for building app interfaces. Discuss the use cases for different frameworks, share best practices, and get help with specific framework-related questions.

All subtopics
Posts under UI Frameworks topic

Post

Replies

Boosts

Views

Activity

UIDocumentPickerViewController
I'm upgrading my app from minVersion iOS 11 to iOS 12. My compiler says that UIDocumentMenuViewController with UIDocumentPickerViewController is deprecated, they recommend to use directly the last one. So I change the code. fileprivate func openDocumentPicker() { let documentPicker = UIDocumentPickerViewController( documentTypes: [ "com.adobe.pdf", "org.openxmlformats.wordprocessingml.document", // DOCX "com.microsoft.word.doc" // DOC ], in: .import ) documentPicker.delegate = self view.window?.rootViewController?.present(documentPicker, animated: true, completion: nil) } When I open the picker in iOS 17.2 simulator and under it is well shown, like a page sheet. But in iOS 18.0 and up at first it opens like a page sheet with no content but then it is displayed as a transparent window with no content. Is there any issue with this component and iOS 18? If I open the picker through UIDocumentMenuViewControllerDelegate in an iphone with iOS 18.2 it is well shown. Image in iOS 18.2 with the snippet The same snippet in iOS 17.2 (and expected in older ones)
Topic: UI Frameworks SubTopic: UIKit Tags:
0
0
359
Jan ’25
Crash when rendering CALayer using UIGraphicsImageRenderer on background thread
Hello! I’m experiencing a crash in my iOS/iPadOS app related to a CALayer rendering process. The crash occurs when attempting to render a UIImage on a background thread. The crashes are occurring in our production app, and while we can monitor them through Crashlytics, we are unable to reproduce the issue in our development environment. Relevant Code I have a custom view controller that handles rendering CALayers onto images. This method creates a CALayer on the main thread and then starts a detached task to render this CALayer into a UIImage. The whole idea is learnt from this StackOverflow post: https://stackoverflow.com/a/77834613/9202699 Here are key parts of my implementation: class MyViewController: UIViewController { @MainActor func renderToUIImage(size: CGSize, itemsToDraw: [MyDrawingItem], transform: CGAffineTransform) async -> UIImage? { // Create CALayer and add it to the view. CATransaction.begin() let customLayer = MyDrawingLayer() customLayer.setupContent(itemsToDraw: itemsToDraw) // Position the frame off-screen to it hidden. customLayer.frame = CGRect( origin: CGPoint(x: -100 - size.width, y: -100 - size.height), size: size) customLayer.masksToBounds = true customLayer.drawsAsynchronously = true view.layer.addSublayer(customLayer) CATransaction.commit() // Render CALayer to UIImage in background thread. let image = await Task.detached { customLayer.setNeedsDisplay() let renderer = UIGraphicsImageRenderer(size: size) let image = renderer.image { // CRASH happens on this line let cgContext = $0.cgContext cgContext.saveGState() cgContext.concatenate(transform) customLayer.render(in: cgContext) cgContext.restoreGState() } return image }.value // Remove the CALayer from the view. CATransaction.begin() customLayer.removeFromSuperlayer() CATransaction.commit() return image } } class MyDrawingLayer: CALayer { var itemsToDraw: [MyDrawingItem] = [] func setupContent(itemsToDraw: [MyDrawingItem]) { self.itemsToDraw = itemsToDraw } override func draw(in ctx: CGContext) { for item in itemsToDraw { // Render the item to the context (example pseudo-code). // All items are thread-safe to use. // Things to draw may include CGPath, CGImages, UIImages, NSAttributedString, etc. item.draw(in: ctx) } } } Crash Log The crash occurs at the following location: Crashed: com.apple.root.default-qos.cooperative 0 MyApp 0x5cb300 closure #1 in closure #1 in MyViewController.renderToUIImage(size: CGSize, itemsToDraw: [MyDrawingItem], transform: CGAffineTransform) + 4313002752 (<compiler-generated>:4313002752) 1 MyApp 0x5cb300 closure #1 in closure #1 in MyViewController.renderToUIImage(size: CGSize, itemsToDraw: [MyDrawingItem], transform: CGAffineTransform) + 4313002752 (<compiler-generated>:4313002752) 2 MyApp 0x1a4578 AnyModifier.modified(for:) + 4308649336 (<compiler-generated>:4308649336) 3 MyApp 0x7b4e64 thunk for @escaping @callee_guaranteed (@guaranteed UIGraphicsPDFRendererContext) -> () + 4315008612 (<compiler-generated>:4315008612) 4 UIKitCore 0x1489c0 -[UIGraphicsRenderer runDrawingActions:completionActions:format:error:] + 324 5 UIKitCore 0x14884c -[UIGraphicsRenderer runDrawingActions:completionActions:error:] + 92 6 UIKitCore 0x148778 -[UIGraphicsImageRenderer imageWithActions:] + 184 7 MyApp 0x5cb1c0 closure #1 in MyViewController.renderToUIImage(size: CGSize, itemsToDraw: [MyDrawingItem], transform: CGAffineTransform) + 100 (FileName.swift:100) 8 libswift_Concurrency.dylib 0x60f5c swift::runJobInEstablishedExecutorContext(swift::Job*) + 252 9 libswift_Concurrency.dylib 0x62514 swift_job_runImpl(swift::Job*, swift::SerialExecutorRef) + 144 10 libdispatch.dylib 0x15ec0 _dispatch_root_queue_drain + 392 11 libdispatch.dylib 0x166c4 _dispatch_worker_thread2 + 156 12 libsystem_pthread.dylib 0x3644 _pthread_wqthread + 228 13 libsystem_pthread.dylib 0x1474 start_wqthread + 8 Questions Is it safe to run UIGraphicsImageRenderer.image on the background thread? Given that I want to leverage GPU rendering, what are some best practices for rendering images off the main thread while ensuring stability? Are there alternatives to using UIGraphicsImageRenderer for background rendering that can still take advantage of GPU rendering? It is particularly interesting that the crash logs indicate the error may be related to UIGraphicsPDFRendererContext (crash log line number 3). It would be very helpful if someone could explain the connection between starting and drawing on a UIGraphicsImageRenderer and UIGraphicsPDFRendererContext. Any insights or guidance on this issue would be greatly appreciated. Thanks!!!
1
0
585
Feb ’25
Hide the TabBar while navigating between screens in Xcode Swift for iOS 16 or later.
Hey, I am developing my app in Swift using Xcode for iOS 16 or later. I want to implement the navigation behavior found in apps like WhatsApp or Instagram, where navigating from the feed to a user's profile keeps the tab bar visible. Then, when opening a chat from the profile, a new view appears, leaving the profile view behind along with the tab bar. I have this code as a base to achieve this, but when navigating from View 1 to View 2, it applies the effect that should only happen in View 3. I haven't been able to prevent View 2 from using this effect and limit it only to View 3. Can anyone help me??? import SwiftUI struct ContentView: View { @State private var path: [String] = [] // Controls the navigation stack in View1 var body: some View { NavigationStack(path: $path) { TabView { View1(path: $path) .tabItem { Label("View 1", systemImage: "1.circle") } View4() .tabItem { Label("View 4", systemImage: "4.circle") } } .navigationDestination(for: String.self) { value in if value == "View3" { View3(path: $path) // View3 outside the TabView } } } } } struct View1: View { @Binding var path: [String] var body: some View { VStack { Text("View 1 with TabBar") Button("Go to View 2") { path.append("View2") // Adds View2 to the stack } } .navigationDestination(for: String.self) { value in if value == "View2" { View2(path: $path) } } } } struct View2: View { @Binding var path: [String] var body: some View { VStack { Text("View 2 with TabBar") Button("Go to View 3 (Without TabBar)") { path.append("View3") // Adds View3 to the stack } } } } struct View3: View { @Binding var path: [String] var body: some View { VStack { Text("View 3 without TabBar") .font(.largeTitle) .padding() Button("Go Back") { path.removeLast() // Returns to View2 } } } } struct View4: View { var body: some View { Text("View 4 with TabBar") } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
2
0
292
Feb ’25
How to share 'back facing' iOS camera app at same time Eye Tracking app needs 'front facing' camera?
While using my xmas present of a new iPhone and iOS 18.2, I figured I'd try the Eye Tracker app. I've been working with clients successfully using Tobii and other existing eye trackers. In my limited tests, Apple has room for improvement. My main issue is with the camera app which cannot be used at the same time while using the Eye Tracker app. I get an error popup from Apple: Camera is use by another app The image below is from my app showing the popup message "Camera in use by another app", but the same error occurs on the installed camera app. This error is from Apple, not my app. For terminology: 'front' camera is the one pointing at the user (the selfi camera) while 'back' camera is the main one with multiple lenses. Eye tracking needs the 'front' camera. It seems when an app uses the camera, it takes over both the front and back facing cameras (since you might swap them). Thus another app, especially Eye Tracking, cannot use just the front facing camera at the same time. That limits use of Eye Tracking, in particular one cannot take pictures or click any buttons on an app that uses the camera. Anyone know of a way for an app to not take over both front and back cameras at the same time? If I can separate them, the Eye Tracker could use the front camera while the camera uses the back camera.
1
0
416
Jan ’25
Crash on Sequoia 15.2
Starting from Sequoia release 15.2 apps crash with following call stack, when adding static text controls. First call to [NSTextField setStringValue] causes following crash 0 libobjc.A.dylib 0x19f2f5820 objc_msgSend + 32 1 AppKit 0x1a3355460 -[NSCell _objectValue:forString:errorDescription:] + 144 2 AppKit 0x1a3355348 -[NSCell setStringValue:] + 48 3 AppKit 0x1a33af9fc -[NSControl setStringValue:] + 104 4 AppKit 0x1a3d1f190 -[NSTextField setStringValue:] + 52 It happens on specific MacBook Pro models(16 in MacBook Pro). Crash analysis found that isa pointer of the object was corrupted for the object NSCell. Enabled Zombies in debugging, not found any issue. Also tried address sanitizer. Since the issue started with a recent release of macOS, any changes in the Appkit in the recent releases trigger the crash? Any help/suggestions would be appreciated.
Topic: UI Frameworks SubTopic: AppKit
4
0
352
Feb ’25
[iOS, SwiftUI] Navigation Bar background is always hidden when navigation destination is TabView
Hello! I have a destination navigation which is TabVIew where each tab item is ScrollView. And when scrolling content of any of tab items is underneath navigation bar its background is always hidden. But at the same time tab bar background is toggled depending on scrolling content position. I expected it would work with TabView the same as with any other view. Is it supposed to work like that?
2
0
315
Feb ’25
SwiftUI Canvas Text - scale to fill rectangle
How do I draw a single line of text in a SwiftUI Canvas, scaled to fill a given rectangle? Example: Canvas { context, size in let r = CGRect(origin: CGPointZero, size: size); // Whole canvas let t = Text("Hello World"); context.draw(t, in: r); } Outside of Canvas I'd add .minimumScaleFactor(0) .lineLimit(1), and I guess set a large default font size, and I'd get the result I want. But inside Canvas, .minimumScaleFactor and .lineLimit don't seem to be available; they return some View, not Text, which can't be used in context.draw. (Is there a trick to make that work?) I have written the following to do this, but I think there must be an easier way to achieve this! Suggestions? extension GraphicsContext { mutating func draw_text_in_rect(string: String, rect: CGRect) { let text = Text(string) .font(.system(size: 25)); // The font size used here does matter, because e.g. letter spacing // varies with the font size. let resolved = resolve(text); let text_size = resolved.measure(in: CGSize(width: CGFloat.infinity, height: CGFloat.infinity)); let text_aspect = text_size.width / text_size.height; let fit_size = CGSize(width: min(rect.size.width, rect.size.height*text_aspect), height: min(rect.size.height, rect.size.width/text_aspect)); let fit_rect = CGRect(x: rect.origin.x + (rect.size.width-fit_size.width)/2, y: rect.origin.y + (rect.size.height-fit_size.height)/2, width: fit_size.width, height: fit_size.height); let scale = fit_size.width / text_size.width; // For debug: // var p = Path(); // p.addRect(fit_rect); // stroke(p, with: GraphicsContext.Shading.color(.red), lineWidth: 1); translateBy(x: fit_rect.minX, y: fit_rect.minY); scaleBy(x:scale, y:scale); draw(resolved, at: CGPointZero, anchor: UnitPoint.topLeading); transform = CGAffineTransformIdentity; } };
0
0
372
Jan ’25
Detect change to apps Screen Time Access
I'm creating an app which gamifies Screen Time reduction. I'm running into an issue with apples Screen Time setting where the user can disable my apps "Screen Time access" and get around losing the game. Is there a way to detect when this setting is disabled for my app? I've tried using AuthorizationCenter.shared.authorizationStatus but this didn't do the trick. Does anyone have an ideas?
0
0
413
Feb ’25
https://developer.apple.com/documentation/swiftui/tab/init(value:content:label:)
As per the documentation link, the Tab initializer in SwiftUI should allow supplying a custom view to the Label. However, the colors used within the Label view are not being honored as expected. I attempted to set custom colors in the Label, but they either default to system-defined styles or are ignored entirely. This behavior does not align with my understanding of how custom views should work in SwiftUI's Label. Am I missing a step or configuration here, or is this a bug in the current implementation? struct ContentView: View { @State private var activeTab: TabItem = .homeTab var body: some View { TabView(selection: $activeTab) { ForEach(TabItem.allCases) { tabItem in Tab(value: tabItem) { getView(for: tabItem) } label: { VStack(spacing: 0) { MainTabButtonView( selected: activeTab == tabItem, tabItem: tabItem ) Text(tabItem.title) } } } } } } private extension ContentView { @ViewBuilder func getView(for tabItem: TabItem) -> some View { switch tabItem { case .homeTab: Text("Home") case .searchTab: Text("Search") case .profileTab: Text("Profile") case .moreTab: Text("More") } } } #Preview { ContentView() } enum TabItem: String, Identifiable, Hashable, CaseIterable { case homeTab case searchTab case profileTab case moreTab var tabImage: String { switch self { case .homeTab: "house" case .searchTab: "magnifying-glass" case .profileTab: "biographic" case .moreTab: "hamburger-menu" } } var title: String { switch self { case .homeTab: "Home" case .searchTab: "Search" case .profileTab: "Profile" case .moreTab: "More" } } var id: String { rawValue } } struct MainTabButtonView: View { private let selected: Bool private let tabItem: TabItem init( selected: Bool, tabItem: TabItem ) { self.selected = selected self.tabItem = tabItem } var body: some View { Image(tabItem.tabImage) .renderingMode(.template) .resizable() .aspectRatio(contentMode: .fill) .frame(width: 30, height: 30) .foregroundStyle( selected ? Color.green : Color.orange ) } } Expected Behavior: The custom colors applied within the Label should render as defined. Actual Behavior: The colors are overridden or ignored, defaulting to the system-defined styles. Environment: Xcode Version: Xcode 16.2 iOS: 18.2 Swift Version: Swift 6
2
0
351
Jan ’25
searchable issue on iOS 18
Starting with iOS 18, the behavior of searchable and searchSuggestions differs from previous versions. In iOS 17.5, searchSuggestions remained visible even after selecting an item and navigating away. However, in iOS 18, searchSuggestions are dismissed after navigation. Is there a way to keep searchSuggestions visible after navigation, as in iOS 17.5? struct ContentView: View { @State private var query = "" var body: some View { NavigationStack { Color.red .searchable(text: $query) .searchSuggestions { NavigationLink("Element") { Color.blue } } } } } iOS 18.1 iOS 17.5
2
0
448
Jan ’25
Can't join current Group Activity on macOS (maybe some launch services thing?)
I'm testing using Group Activities and having no trouble iOS<->iOS or starting an activity on macOS and joining via iOS. However, when I start an activity and then try to join it from another macOS client, the starting side joins the session just fine, but the receiving side acts like I don't have the required app, even when it is already running. I see the active SharePlay icon in the menu bar, and the Current Activity is shown, but instead of an "Open" button there is a "MyApp Required" string and a "View" button that goes to the App Store. (Where the app is not available yet, as expected, since I'm still working on it.) There is no GroupSession started on that Mac yet, obviously. I'm looking for any hints to help debug what is going on. How does Group Activities find the app for the activity on macOS and how can I figure out why it isn't finding mine? Thanks!
0
0
332
Feb ’25
How to remove margins around built-in views?
I want to have my own background and foreground colors for some views and I am having a bit of trouble. I cannot figure out how to remove the margins around some built-in views. One example is below. The ScrollView portion is always black or white, depending on whether I am I dark mode or not. I've added various colors and borders to see what is going on below. I've also tried adding the modifiers to the Scroll View rather than the TextEditor and it doesn't work at all. If I don't have the .frame modifier on the ScrollView, the TextEditor moves to the top of its frame for some reason. I've played with .contentMargins, .edgeInsets, etc. with no luck How do I get the TextEditor to fill the entire ScrollView without the margin? Thanks! import SwiftUI struct TextEditorView: View { @Binding var editString: String var numberOfLines: Int var lineHeight: CGFloat { UIFont.preferredFont(forTextStyle: .body).lineHeight } var viewHeight: CGFloat { lineHeight * CGFloat(numberOfLines) + 8 } var body: some View { ScrollView([.vertical], showsIndicators: true) { TextEditor(text: $editString) .border(Color.red, width: 5) .foregroundStyle(.yellow) .background(.blue) .frame(minHeight:viewHeight, maxHeight: viewHeight) .scrollContentBackground(.hidden) } .frame(minHeight:viewHeight, maxHeight: viewHeight) } }
0
0
198
Jan ’25
Rectangle change size by swipe
Hi,, How can I make a rectangle become taller as I swipe down on my trackpad?" struct BlueRectangleView: View { var body: some View { VStack { Rectangle() .fill(Color.blue) .frame(width: 200, height: 100) .cornerRadius(10) .shadow(radius: 5) .padding() } .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color.white) } } struct BlueRectangleView_Previews: PreviewProvider { static var previews: some View { BlueRectangleView() } }
2
0
284
Jan ’25
SwiftUI - Drag gesture blocks scroll gesture only on iPhone 11
I'm pretty new to Swift and SwiftUI. I'm making my first app for sorting a gallery with some extra features. I was using my own iPhone for testing and just started testing my app on other Apple products. Everything works fine on iPad Air M1, iPhone 15 Pro, iPhone 15 Pro Max, iPhone 13, iPhone XS (Simulator), and iPhone 11 Pro (Simulator). However, when I tried to show my app to a family member with an iPhone 11, I came across an issue. Issue Description: My app takes all photos from iPhone's native gallery, then you can sort it by some spesific filters and delete pictures. It just looks like the native gallery. (I can add photos later if needed) You can just scroll the gallery by swiping up and down. You can press the select button and start selecting pictures to delete. I recently added a drag-to-select-multiple-pictures feature. This makes it feel more like the native iOS experience, eliminating the need to tap each picture individually. However, on the iPhone 11, the moment you open the app, you can't scroll. Scrolling is completely locked. You can still select pictures by tapping or dragging, so it's not a touch area issue. The same issue persists on the iPhone 11 simulator. And I think I found the problematic part in my (sadly messy) ContentView.swift file; ScrollView { RefreshControl(coordinateSpace: .named("refresh")) { await viewModel.refreshMediaItems() } LazyVGrid(columns: gridColumns, spacing: UIDevice.current.userInterfaceIdiom == .pad ? 12 : 4) { let items = viewModel.filteredItems(typeFilter: mediaTypeFilter, specialFilter: specialFilter) ForEach(Array(zip(items.indices, items)), id: \.1.id) { index, item in MediaThumbnailView( item: item, isSelected: selectedItems.contains(item.id), viewModel: viewModel, onLongPress: { if !isSelectionMode { toggleSelectionMode() selectedItems.insert(item.id) } }, onTap: { if isSelectionMode { toggleSelection(item: item) } else { viewModel.selectItem(item) } } ) .aspectRatio(1, contentMode: .fit) .background( GeometryReader { geometry in let frame = geometry.frame(in: .named("grid")) Color.clear.preference( key: ItemBoundsPreferenceKey.self, value: [ItemBounds(id: item.id, bounds: frame, index: index)] ) } ) } } .padding(.horizontal, 2) .coordinateSpace(name: "grid") .onPreferenceChange(ItemBoundsPreferenceKey.self) { bounds in itemBounds = Dictionary(uniqueKeysWithValues: bounds.map { ($0.id, $0) }) itemIndices = Dictionary(uniqueKeysWithValues: bounds.map { ($0.id, $0.index) }) } .gesture( DragGesture(minimumDistance: 0) .onChanged { gesture in if isSelectionMode { let location = gesture.location if !isDragging { startDragging(at: location, in: itemBounds) } updateSelection(at: location, in: itemBounds) } } .onEnded { _ in endDragging() } ) } .coordinateSpace(name: "refresh") } you can see the .gesture(.... part. I realised that this DragGesture and ScrollView blocks each other (somehow only on iPhone 11) highPriorityGesture also won't work. When I change it with simultaneousGesture, scroll starts to work again. BUT - since it's simultaneous, when multiple selection mode is activated, when I'm dragging my finger gallery also starts to scroll and it becomes a very unpleasant experience. After this issue I realised on native gallery iOS locks scroll when you are dragging for multiple selection and just when you release your finger you can scroll again even if the multiple selection mode is active. I tried a million things, asked claude, chatgpt etc. etc. Found some similar issues on stackoverflow but they were all related to iOS 18, not spesific to an iPhone. My app works fine on iOS 18 (15 Pro Max) iOS 18 drag gesture blocks scrollview Here are the some of the things I've tried: using highPriorityGesture and simultenousgesture together, tried to lock the scroll briefly while dragging, implement much complicated versions of these things with the help of claude, try to check if isSelectionMode is true or not All of them broke other things/won't work. Probably there's something pretty simple that I'm just missing; but iPhone 11 being the single problematic device confuses me. I don't want to mess too much with my already fragile logic.
1
0
801
Jan ’25
Playground SwiftUI on iPad wont save .png image using fileExporter.
The SwiftUI Playground code below demonstrates that a .jpeg image can be read and written to the iOS file system. While, a.png image can only be read; the writing request appears to be ignored. Can anyone please tell me how to code to save a .png image using SwiftUI to the iOS file system. Code: import SwiftUI import UniformTypeIdentifiers /* (Copied from Playground 'Help' menu popup.) UIImage Summary An object that manages image data in your app. You use image objects to represent image data of all kinds, and the UIImage class is capable of managing data for all image formats supported by the underlying platform. Image objects are immutable, so you always create them from existing image data, such as an image file on disk or programmatically created image data. An image object may contain a single image or a sequence of images for use in an animation. You can use image objects in several different ways: Assign an image to a UIImageView object to display the image in your interface. Use an image to customize system controls such as buttons, sliders, and segmented controls. Draw an image directly into a view or other graphics context. Pass an image to other APIs that might require image data. Although image objects support all platform-native image formats, it’s recommended that you use PNG or JPEG files for most images in your app. Image objects are optimized for reading and displaying both formats, and those formats offer better performance than most other image formats. Because the PNG format is lossless, it’s especially recommended for the images you use in your app’s interface. Declaration class UIImage : NSObject UIImage Class Reference */ @main struct MyApp: App { var body: some Scene { WindowGroup { ContentView() } } } struct ImageFileDoc: FileDocument { static var readableContentTypes = [UTType.jpeg, UTType.png] static var writableContentTypes = [UTType.jpeg, UTType.png] var someUIImage: UIImage = UIImage() init(initialImage: UIImage = UIImage()) { self.someUIImage = initialImage } init(configuration: ReadConfiguration) throws { guard let data = configuration.file.regularFileContents, let some = UIImage(data: data) else { throw CocoaError(.fileReadCorruptFile) } self.someUIImage = some } func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper { switch configuration.contentType { case UTType.png: if let data = self.someUIImage.pngData() { return .init(regularFileWithContents: data) } case UTType.jpeg: if let data = self.someUIImage.jpegData(compressionQuality: 1.0) { return .init(regularFileWithContents: data) } default: break } throw CocoaError(.fileWriteUnknown) } } struct ContentView: View { @State private var showingExporterPNG = false @State private var showingExporterJPG = false @State private var showingImporter = false @State var message = "Hello, World!" @State var document: ImageFileDoc = ImageFileDoc() @State var documentExtension = "" var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundColor(.accentColor) Text(message) Button("export") { if documentExtension == "png" { message += ", showingExporterPNG is true." showingExporterPNG = true } if documentExtension == "jpeg" { message += ", showingExporterJPG is true." showingExporterJPG = true } } .padding(20) .border(.white, width: 2.0) .disabled(documentExtension == "") Button("import") { showingImporter = true } .padding(20) .border(.white, width: 2.0) Image(uiImage: document.someUIImage) .resizable() .padding() .frame(width: 300, height: 300) } // exporter .png .fileExporter(isPresented: $showingExporterPNG, document: document, contentType: UTType.png) { result in switch result { case .success(let url): message += ", .\(documentExtension) Saved to \(url.lastPathComponent)" case .failure(let error): message += ", Some error saving file: " + error.localizedDescription } } // exporter .jpeg .fileExporter(isPresented: $showingExporterJPG, document: document, contentType: UTType.jpeg) { result in switch result { case .success(let url): message += ", .\(documentExtension) Saved to \(url.lastPathComponent)" case .failure(let error): message += ", Some error saving file: " + error.localizedDescription } } // importer .fileImporter(isPresented: $showingImporter, allowedContentTypes: [.png, .jpeg]) { result in switch result { case .failure(let error): message += ", Some error reading file: " + error.localizedDescription case .success(let url): let gotAccess = url.startAccessingSecurityScopedResource() if !gotAccess { message += ", Unable to Access \(url.lastPathComponent)" return } documentExtension = url.pathExtension guard let fileContents = try? Data(contentsOf: url) else { message += ",\n\nUnable to read file: \(url.lastPathComponent)\n\n" url.stopAccessingSecurityScopedResource() return } url.stopAccessingSecurityScopedResource() message += ", Read file: \(url.lastPathComponent)" message += ", path extension is '\(documentExtension)'." if let uiImage = UIImage(data: fileContents) { self.document.someUIImage = uiImage }else{ message += ", File Content is not an Image." } } } } }
0
0
354
Feb ’25