Post

Replies

Boosts

Views

Activity

Saving Camera-Captured Picture to Photo with AVCaptureSession
How do you save a picture from the capture-screen with AVCaptureSession to Photo? My capture-screen looks like a square as show below. Yet I've ended up with an 1080 × 1920 image as shown below. I have an iPhone XR, and I always end up with 1080 × 1920 images. How come the aspect ration never changes? My code has the following lines import UIKit import AVFoundation class CaptureViewController: UIViewController, AVCapturePhotoCaptureDelegate { var captureSession: AVCaptureSession! var cameraDevices: AVCaptureDevice! var imagePhotoOutput: AVCapturePhotoOutput! enum CameraCase { case front case back } // MARK: - IBAction @IBAction func takePictureTapped(_ sender: UIButton) { snapPicture() } // MARK: - Life cycle override func viewDidLoad() { super.viewDidLoad() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) prepareCamera(cameraCase: .back) } // MARK: - Camera func prepareCamera(cameraCase: CameraCase) { /* removing existing layers */ if let sublayers = self.view.layer.sublayers { for sublayer in sublayers { if sublayer.isKind(of: AVCaptureVideoPreviewLayer.self) { sublayer.removeFromSuperlayer() } } } /* creating a capture session */ captureSession = AVCaptureSession() guard let device = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: cameraCase == .front ? .front : .back).devices.first else { return } let videoInput = try? AVCaptureDeviceInput(device: device) if captureSession.canAddInput(videoInput!) { captureSession.addInput(videoInput!) imagePhotoOutput = AVCapturePhotoOutput() // setting output destination captureSession.addOutput(imagePhotoOutput) // adding photo output to session } /* creating a capture layer */ let previewLayer: AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer.init(session: captureSession) previewLayer.frame = CGRect(x: 0.0, y: 200.0, width: view.frame.width, height: view.frame.height - 500.0) previewLayer.videoGravity = AVLayerVideoGravity.resize /* adding video capture layer to the view layer */ self.view.layer.addSublayer(previewLayer) /* starting capture session */ DispatchQueue.global(qos: .background).async { self.captureSession.startRunning() } } func snapPicture() { let settingsForMonitoring = AVCapturePhotoSettings() imagePhotoOutput?.capturePhoto(with: settingsForMonitoring, delegate: self as AVCapturePhotoCaptureDelegate) } // MARK: - Delegate methods func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { if error == nil { guard let imageData = photo.fileDataRepresentation() else { print("Error while generating image from photo capture data."); return } if let image = UIImage(data: imageData) { saveImage(image) } } } // MARK: - Saving an image to Photo Library func saveImage(_ image: UIImage) { UIImageWriteToSavedPhotosAlbum(image, self, #selector(image(_:didFinishSavingWithError: contextInfo:)), nil) } @objc func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) { if let error = error { print("An error has occurred: \(error.localizedDescription)") } else { print("Saved...") } } } Thanks.
2
0
1.6k
Dec ’22
Drawing a Pie without Path?
Drawing a pie isn't difficult if I do it with Path. import SwiftUI struct ContentView8: View { var body: some View { PieSlice(start: .degrees(-90), end: .degrees(120)) .fill(.pink) } } struct PieSlice: Shape { let start: Angle let end: Angle func path(in rect: CGRect) -> Path { var path = Path() let center = CGPoint(x: rect.midX, y: rect.midY) path.move(to: center) path.addArc(center: center, radius: rect.midX, startAngle: start, endAngle: end, clockwise: false) return path } } Actually, I want to animate this pie such that it will gradually deploy starting at -90 degrees. In the code above, I suppose I cannot animate the pie because the PieSlice guy isn't a View. Or can I? If I can't, is there an alternative way of drawing a pie so that I can animate it? Thanks a million. Señor Tomato Source Hostage Negotiator at Tomato Source Association of North America
2
0
605
Jul ’23
Sorting CoreData Records by Creation Date
I have followed a tutorial written by Hacking with Swift ( https://www.hackingwithswift.com/books/ios-swiftui/how-to-combine-core-data-and-swiftui) about Core Data in SwiftUI. The Entity name is Student. And it has two properties: name (String), id (UUID). And the following is my code. import SwiftUI struct CoreView: View { @Environment(\.managedObjectContext) var managedObject @FetchRequest(sortDescriptors: []) var students: FetchedResults<Student> var body: some View { VStack { List(students) { student in Text(student.name ?? "Unknown") } Button { let firstNames = ["Gary", "Harry", "Elane", "Ray", "Nancy", "Jim", "Susan"] let lastNames = ["Johns", "McNamara", "Potter", "Thompson", "Hampton"] if let selectedFirstName = firstNames.randomElement(), let selectedLastName = lastNames.randomElement() { let newStudent = Student(context: managedObject) newStudent.id = UUID() newStudent.name = "\(selectedFirstName) \(selectedLastName)" try? managedObject.save() } } label: { Text("Add") } } } } struct CoreView_Previews: PreviewProvider { static var previews: some View { CoreView() .environmentObject(DataController()) } } If I list all records and then add a new student to the list, the app will insert the last addition at a random row. I wonder if I can order these records by the creation date? Muchos thankos
2
0
1.3k
Jul ’23
Removing More?
I use the ForEach enumeration to list a View horizontally. And I get the following picture. So far, so good... If I select the 5th object or 6th one, something odd (< More) appears. I don't know where it comes from. I have never seen it before. How does it happen? I wonder how I can remove it? I have searched the net for a clue to no avail. I don't even know how to describe it. The following is my code. import SwiftUI struct ContentView: View { @State var selectedTab = 0 @State var addTapped = false @State var refresh = false @State var people = [ Person(name: "Alice", systemImage: "person.circle.fill"), Person(name: "Jane", systemImage: "person.circle.fill"), Person(name: "Dave", systemImage: "person.circle.fill"), Person(name: "Susan", systemImage: "person.circle.fill"), Person(name: "Robert", systemImage: "person.circle.fill"), Person(name: "Daniel", systemImage: "person.circle.fill") ] var body: some View { VStack(alignment: .leading, spacing: 0) { ScrollView(.horizontal) { HStack(spacing: 20) { ForEach(0..<people.count, id: \.self) { num in VStack { let person = people[num] Image(systemName: person.systemImage) .resizable() .aspectRatio(contentMode: .fit) .frame(height: 32) Text(person.name) .fixedSize() } .foregroundColor(selectedTab == num ? Color.blue : Color.gray) .onTapGesture { self.selectedTab = num } } } }.padding(.horizontal, 10) Spacer() .frame(height: 2) Rectangle().fill(.gray) .frame(height: 1) TabView(selection: $selectedTab) { ForEach(0..<people.count, id: \.self) { num in let person = people[num] Text(person.name) .tag(person.id) } } } } } struct Person: Identifiable { let id = UUID() let name: String let systemImage: String } Muchos thankos.
2
0
683
Aug ’23
Exporting a Document with FileDocument, Not Packaged
I'm trying to export a document file. It contains a codable struct named NoteGroup. struct NoteGroup: Codable { let id: UUID let name: String let createAt: Date let children: [NoteChild] init(id: UUID = .init(), name: String = "", createAt: Date = .init(), children: [NoteChild]) { self.id = id self.name = name self.createAt = createAt self.children = children } } , which contains another object named NoteChild. I have a FileDocument struct as follows. import SwiftUI import UniformTypeIdentifiers struct Document: FileDocument { var document: NoteGroup static var readableContentTypes = [UTType.frogType] init(document: NoteGroup = NoteGroup(children: [NoteChild(id: UUID(), name: "", createAt: Date())])) { self.document = document } init(configuration: ReadConfiguration) throws { self.init() } func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper { do { let data = try getDocumentData() let jsonFileWrapper = FileWrapper(regularFileWithContents: data) let filename = "Note.frog" jsonFileWrapper.filename = filename let fileWrapper = FileWrapper(directoryWithFileWrappers: [filename: jsonFileWrapper]) return fileWrapper } catch { throw error } } private func getDocumentData() throws -> Data { let encoder = JSONEncoder() do { let data = try encoder.encode(document) return data } catch { throw error } } } extension UTType { public static let frogType = UTType(exportedAs: "com.example.frog") } And I export a file like the following. import SwiftUI import UniformTypeIdentifiers struct ContentView: View { @State private var showingExporter = false @State var doc = Document() var body: some View { VStack { Button("Tap to export") { showingExporter.toggle() } .fileExporter( isPresented: $showingExporter, document: doc, contentType: .frogType ) { result in switch result { case .success(let file): print(file) case .failure(let error): print(error) } } }.onAppear { doc = Document(document: NoteGroup(id: UUID(), name: "Kyle", createAt: Date(), children: [NoteChild(id: UUID(), name: "Nancy", createAt: Date())])) } } } Well, I have read this topic. And I've watched this video about Uniform Type Identifiers. Thanks to the video, I am able to export a file. Yet, I end up with a folder (Frog.frog), not a packaged file. There is a JSON file in it, though. What am I doing wrong? It's for iOS. La vida no es facil. Muchos thankos.
2
0
964
Aug ’23
Picker with ForEach
I have a ForEach loop with Range that I use with Picker. I'm using Range because I want to set startYear and endYear when View appears. The following is my code. import SwiftUI struct ProviderCalendarView: View { @State private var startYear: Int = 2023 @State private var endYear: Int = 2034 @State private var selectedYear = 3 var body: some View { VStack { HStack { Picker(selection: $selectedYear) { ForEach((startYear...endYear), id: \.self) { year in Text("\(year)") } } label: { } } } } } And the compiler says the following. Picker: the selection "3" is invalid and does not have an associated tag, this will give undefined results. It's not a critical error. But how can I stop it? Thanks.
2
0
1.4k
Aug ’23
'unarchiveTopLevelObjectWithData' was deprecated Use unarchivedObject(ofClass:from:) instead
I have a macOS application with SwiftUI. I am saving a dictionary containing two custom classes with NSSavePanel. That's not a problem. import SwiftUI struct ContentView: View { var body: some View { ... } private func savePanel() -> URL? { let savePanel = NSSavePanel() savePanel.allowedContentTypes = [.myCustomeFileType] savePanel.canCreateDirectories = true savePanel.isExtensionHidden = false savePanel.title = "Saving..." savePanel.message = "Please select a path where to save a file." savePanel.nameFieldStringValue = "Untitled" return savePanel.runModal() == .OK ? savePanel.url : nil } private func fileSaveAs() { if let url = savePanel() { let models = colorViewModel.frameModels let borderModel = BorderModel(showBorder: true, colorIndex: 6, borderWeightIndex: 8) let dict = ["FrameModelArray": models, "BorderModel": borderModel] as [String : Any] NSKeyedArchiver.setClassName("FrameModel", for: FrameModel.self) NSKeyedArchiver.setClassName("BorderModel", for: BorderModel.self) do { let data = try NSKeyedArchiver.archivedData(withRootObject: dict, requiringSecureCoding: false) try data.write(to: url, options: .atomic) } catch { print("Errrrrr \(error.localizedDescription)") } } } } So my custom classes are FrameModel, BorderModel. I can unarchive a saved file with a deprecated type method as follows. private func fileOpen() { if let url = openPanel() { do { NSKeyedUnarchiver.setClass(FrameModel.self, forClassName: "FrameModel") NSKeyedUnarchiver.setClass(BorderModel.self, forClassName: "BorderModel") let data = try Data(contentsOf: url) if let someData = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) { if let dict = someData as? [String : Any] { if let frameModels = dict["FrameModelArray"] as? [FrameModel] { print("[FrameModel] read...") } if let borderModel = dict["BorderModel"] as? BorderModel { print("BorderModel read...") } } } } catch { print("Errrrrr \(error.localizedDescription)") } } } If I use unarchivedObject(ofClasses:from:), I can't unarchive my file. What am I doing wrong? Thanks. private func fileOpen() { if let url = openPanel() { do { NSKeyedUnarchiver.setClass(FrameModel.self, forClassName: "FrameModel") NSKeyedUnarchiver.setClass(BorderModel.self, forClassName: "BorderModel") let data = try Data(contentsOf: url) if let dictionary = try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [FrameModel.self, BorderModel.self], from: data) as? NSDictionary { print("Being read...") } else { print("Not read...") } } catch { print("Errrrrr \(error.localizedDescription)") } } }
2
0
1.9k
Sep ’23
How Come My WeatherKit Sample App Doesn't Work?
I have gone through several tutorials for WeatherKit. But my sample app doesn't return weather data. The following is a list of what I have. I've registered a Bundle ID for my sample app with the WeatherKit capability on. I've created a developer profile for my sample app. I've opened my Xcode project to make sure that the WeatherKit capability is enabled. I have run my sample app with an actual device. I have waited for more than 30 minutes for the service to kick in. It's been several days. The following is my code. import SwiftUI import CoreLocation import WeatherKit struct ContentView: View { @State var currentWeather: CurrentWeather? var body: some View { NavigationStack { List { Group { SampleCell(title: "Temperature", value: String(currentWeather?.apparentTemperature.value ?? 0.0) + "℃") SampleCell(title: "Cloud coverage", value: String(currentWeather?.cloudCover ?? 0.0)) SampleCell(title: "Weather condition", value: String(currentWeather?.condition.description ?? "")) SampleCell(title: "Dew point", value: String(currentWeather?.dewPoint.value ?? 0.0) + "℃") SampleCell(title: "Humidity", value: String(currentWeather?.humidity ?? 0.0)) SampleCell(title: "Pressure", value: String(currentWeather?.pressure.value ?? 0.0) + "mbar") SampleCell(title: "Pressure trend", value: String(currentWeather?.pressureTrend.description ?? "")) SampleCell(title: "Temperature", value: String(currentWeather?.temperature.value ?? 0.0) + "℃") SampleCell(title: "UV index", value: String(currentWeather?.uvIndex.value ?? 0)) SampleCell(title: "Visibility", value: String(currentWeather?.visibility.value ?? 0.0) + "m") } SampleCell(title: "Window direction", value: String(currentWeather?.wind.direction.value ?? 0.0) + "°") SampleCell(title: "Window speed", value: String(currentWeather?.wind.speed.value ?? 0.0) + "km/h") SampleCell(title: "Gust", value: String(currentWeather?.wind.gust?.value ?? 0.0) + "km/h") } .navigationTitle(Text("CurrentWeather")) .task { let service = WeatherService() let location = CLLocation( latitude: 35.467081, longitude: 139.620798 ) do { let weather = try await service.weather(for: location) currentWeather = weather.currentWeather } catch let error { print(error.localizedDescription) } } } } } struct SampleCell: View { var title: String var value: String var body: some View { VStack { HStack { Text(title) Spacer() Text(value) } } } } Yet, I constantly get the following warnings. 2023-11-29 09:33:46.504737+0900 WeatherCrazyMama[15279:9734572] [WeatherDataService] Aborting silent interpolation: no interpolator object; location=CLLocationCoordinate2D(latitude: 35.467081, longitude: 139.620798) 2023-11-29 09:33:47.900605+0900 WeatherCrazyMama[15279:9734577] [AuthService] Failed to generate jwt token for: com.apple.weatherkit.authservice with error: Error Domain=WeatherDaemon.WDSJWTAuthenticatorServiceListener.Errors Code=2 "(null)" 2023-11-29 09:33:47.989603+0900 WeatherCrazyMama[15279:9734572] [WeatherService] Encountered an error when fetching weather data subset; location=<+35.46708100,+139.62079800> +/- 0.00m (speed -1.00 mps / course -1.00) @ 2023/11/29 9:33:46 AM Japan Standard Time, error=WeatherDaemon.WDSJWTAuthenticatorServiceListener.Errors 2 Error Domain=WeatherDaemon.WDSJWTAuthenticatorServiceListener.Errors Code=2 "(null)" The operation couldn’t be completed. (WeatherDaemon.WDSJWTAuthenticatorServiceListener.Errors error 2.) What am I doing wrong? Thanks.
2
1
1.5k
Jan ’24
TextField with Custom Binding
I'm just playing with Combine, and I want to limit the number of letters that the text field can show. So I have the following lines of code. import SwiftUI struct ContentView: View { @State var messageText: String = "" var body: some View { let bindingMessage = Binding { messageText } set: { messageText = String($0.prefix(10)) print(String($0.prefix(10))) } Form { TextField("Message", text: bindingMessage) } } } I'm expecting that the text field will show only the first 10 letters. But, as the screenshot below indicates, it shows the entire string. What am I doing wrong? Muchos Thankos. It sounds basic. Ugghhh...
2
0
923
Jan ’24
Limiting the Number of Bool (True) Values
I have the following lines of code where I show a bunch of checkboxes, each of which can toggle between on and off with a tap. import SwiftUI struct ContentView: View { @State private var viewModel = ContentViewModel() var body: some View { VStack(alignment: .leading) { List { ForEach(viewModel.models, id: \.id) { model in CheckButtonView(id: model.id, text: model.name, isOn: model.isOn) { id, bool in updateDate(id: id, bool: bool) } } } } } func updateDate(id: String, bool: Bool) { for i in 0..<viewModel.models.count { let oldModel = viewModel.models[i] if oldModel.id == id { let newModel = Content(id: oldModel.id, name: oldModel.name, isOn: bool) viewModel.models.remove(at: i) viewModel.models.insert(newModel, at: i) break } } var count = 0 for i in 0..<viewModel.models.count { let model = viewModel.models[i] if model.isOn { count += 1 } } } } struct CheckButtonView: View { let id: String let text: String @State var isOn: Bool var callBack: (String, Bool) -> Void var body: some View { HStack { Button { isOn.toggle() callBack(id, isOn) } label: { Image(systemName: isOn ? "checkmark.square.fill" : "square") .resizable() .aspectRatio(contentMode: .fit) .frame(width: 18) .tint(!isOn ? .black : .blue) } Text(text) .font(.subheadline) Spacer() } .frame(maxWidth: .infinity) } } struct Content { let id: String let name: String let isOn: Bool } class ContentViewModel: ObservableObject { @Published var models = [Content]() @Published var canChange = true init() { models = [ Content(id: UUID().uuidString, name: "Jim", isOn: false), Content(id: UUID().uuidString, name: "Jenny", isOn: false), Content(id: UUID().uuidString, name: "Nancy", isOn: false), Content(id: UUID().uuidString, name: "Natalie", isOn: false) ] } } According to the picture above, I have two checkboxes that are turned on. Now, what I want to do is let the user turn on as many as two checkboxes only. Can someone think of a good way of doing that? Thanks.
2
0
375
Nov ’24
Not Showing FileOpen with Document-
I have developed several document-based (NSDocument) applications for macOS is Cocoa. Now, I'm playing with a document app project in SwiftUI. If I launch the application out of box, a file-select panel will open just as you see in TextEdit. (Please see the picture below) How do we prevent it from appearing? I would rather show a blank window, which in fact appears if I just press Command + N. Thanks.
2
0
93
Apr ’25
Clearing Change Count in FileDocument?
I'm playing with a simple document-based application with TextEditor for macOS. In Cocoa, NSViewController can call updateChangeCount(_:) to clear document changes in NSDocument. I wonder SwiftUI's View has access to the same function? Hopefully, I would like to manually set the change count to zero if the user clears text in TextEditor. I bet SwiftUI doesn't have it. Thanks. import SwiftUI struct ContentView: View { @Binding var document: SampleDocumentApp var body: some View { VStack { TextEditor(text: $document.text) .onChange(of: document.text) { _, _ in guard !document.text.isEmpty else { return } // clear change count // } } .frame(width: 360, height: 240) } }
2
0
57
Apr ’25
Opening a New Tab with Text in a Document-Based App
I have a sample document-based application for macOS. According to this article (https://jujodi.medium.com/adding-a-new-tab-keyboard-shortcut-to-a-swiftui-macos-application-56b5f389d2e6), you can create a new tab programmatically. It works. Now, my question is whether you can open a tab with some data. Is that possible under the SwiftUI framework? I could do it in Cocoa. Hopefully, we can do it in SwiftUI as well. Muchos thankos. import SwiftUI @main struct SomeApp: App { var body: some Scene { DocumentGroup(newDocument: SomeDocument()) { file in ContentView(document: file.$document) } } } import SwiftUI struct ContentView: View { @Binding var document: SomeDocument var body: some View { VStack { TextEditor(text: $document.text) Button { createNewTab() } label: { Text("New tab") .frame(width: 64) } } } } extension ContentView { private func createNewTab() { if let currentWindow = NSApp.keyWindow, let windowController = currentWindow.windowController { windowController.newWindowForTab(nil) if let newWindow = NSApp.keyWindow, currentWindow != newWindow { currentWindow.addTabbedWindow(newWindow, ordered: .above) } } } }
2
0
92
Apr ’25
Can You Debug a Widget on Actual Device?
I'm working on an iOS app with a Widget. I am able to display the Widget on the iPhone 16 Pro Simulator. It doesn't appear on iPad mini 6th gen., though. Anyway, I want to make sure that it works on an actual device. If I try to add the Widget to the Home Screen, I cannot find it in the search list on iPhone XR and iPad 9th gen. If I set the target to that of the widget, Xcode gives me the following error. SendProcessControlEvent:toPid: encountered an error: Error Domain=com.apple.dt.deviceprocesscontrolservice Code=8 "Failed to show Widget 'some bundle ID' error: … I hope that's not a sign of trouble. So how do you debug a Widget on an Actual Device? I've read some topics like this one here. Thanks.
2
0
97
May ’25