SwiftUI+Swift+Xcode Quicklook
Quick reference for how to use various SwiftUI components, common Swift functions, and some Xcode general knowledge. Always updating…
Simulator Documents Directory
The documents directory, which is where you app’s content such as CoreData SQLite files live, can be located below. If you don’t know the Device Simulator ID, usually sorting by last modified shows you the latest simulator you interacted with.
/Users/<USER>/Library/Developer/CoreSimulator/Devices/<Device Simulator ID>/data/Containers/Data
AF Networking Framework Debug Response
.response(completionHandler: { data in
print(String(data: data.data!, encoding: .utf8))
})
Getting App Version+Build number
private var appVersion: String = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "Unknown"
private var appBuildNumber: String = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "Unknown"
Asking for App Store Review
Button(action: {
if let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene {
AppStore.requestReview(in: scene)
}
}, label: {
Text("Rate on the App Store")
})
Sheet Presentation Height
.sheet(isPresented: $showEditor, content: {
DetailView(customText: $customizedText)
.presentationDetents([.medium])
})
TextEditor Placeholder Workaround
ZStack {
if taskNote.taskBody.isEmpty {
Text("Note Content...")
TextEditor(text: .constant("Note content"))
.padding()
.disabled(true)
.foregroundStyle(.gray)
}
TextEditor(text: $taskNote.taskBody)
.padding()
.focused($editorFocused)
.opacity(taskNote.taskBody.isEmpty ? 0.25 : 1)
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
Spacer()
Button("Done"){
editorFocused = false
}
}
}
}
iOS Focused Text Done Button
@FocusState var editorFocused: Bool
TextEditor(text: $taskNote.taskBody)
.padding()
.focused($editorFocused)
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
Spacer()
Button("Done"){
editorFocused = false
}
}
}
Load JSON directly into Swift Class
private func loadCategoryJSON() {
// Load file from main Bundle
let url = Bundle.main.url(forResource: "CategoryData", withExtension: "json")!
let data = try! Data(contentsOf: url)
let decoder = JSONDecoder()
// Set the decoding Strategy so we can convert from "category_title" JSON key to "categoryTitle" Swift property
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let fileArray = try decoder.decode([ContentCategory].self, from: data)
if (fileArray.count > 0){
print(fileArray)
}else{
}
}catch {
print(error)
}
}
class ContentCategory: Decodable {
var categoryTitle: String
var categoryEmoji: String
}
Shared Instance
static let shared: APIManager = {
let manager = APIManager()
return manager
}()
App Storage
@AppStorage("username") var username: String = "Anonymous"
Popover
@State var showIndvFileSettings = false
Button("Settings") {
showIndvFileSettings.toggle()
}
.popover(isPresented: $showIndvFileSettings,arrowEdge: .trailing) {
VStack {
Text("Popover Content")
}
.padding()
}
File Importer/Selector
let allowedSelectionFileTypes: [UTType] = [.commaSeparatedText,.html]
@State var loadFilePresenting = false
Button("Load File") {
loadFilePresenting.toggle()
}.fileImporter(isPresented: $loadFilePresenting, allowedContentTypes: allowedSelectionFileTypes) { result in
switch result {
case .success(let url):
url.startAccessingSecurityScopedResource()
// Do something with selected URL
url.stopAccessingSecurityScopedResource()
case .failure(let error):
print(error)
}
}
.fileDialogDefaultDirectory(URL(filePath: "~/Library/Safari/Bookmarks.plist"))
Confirmation Alert
.confirmationDialog("Delete Confirmation", isPresented: $showDeleteConfirmation, actions: {
Button("Delete", role: .destructive) {
print("Action to Delete")
}
}, message: {
Text("Are you sure you want to delete this Item?")
})
Iterable Enum
enum StatusClasses: String, Codable, CaseIterable {
case Active = "Active"
case Pending = "Pending"
case Inactive = "Inactive"
case Archived = "Archived"
case InitialContact = "Initial Contact"
}
// Showing as List
Picker("Status", selection: $object.status) {
ForEach(StatusClasses.allCases, id: \.self) { status in
Text(status.rawValue)
.tag(status.rawValue)
}
}
Binding SwiftData Object
// Content View
ForEach(notes) { note in
NavigationLink {
EditorView(selectedNote: note)
}
}
// Editor View
@Bindable var selectedNote: Note
var body: some View {
VStack {
TextField("Title", $selectedNote.title)
}
}
Open URL in Safari
struct ContentView: View {
@Environment(\.openURL) private var openURL
var body: some View {
VStack {
Button("Open URL") {
openURL(URL(string:"https://nsmug.com")!)
}
}
}
}