-
doesn't have a target for net7.0-ios ios-arm64
If you get this error:
/usr/local/share/dotnet/sdk/7.0.306/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(5,5): Error NETSDK1047: Assets file ‘/…/obj/project.assets.json' doesn't have a target for 'net7.0-ios/ios-arm64'. Ensure that restore has run and that you have included 'net7.0-ios' in the TargetFrameworks for your project. You may also need to include 'ios-arm64' in your project's RuntimeIdentifiers. (NETSDK1047) (…)
In Visual Studio open the command prompt and enter
dotnet restore -r ios-arm64
From https://github.com/xamarin/xamarin-macios/issues/14753#issuecomment-1105360239
-
If your C++ files are not compiling when adding them to Xcode
Check that when you import the containing folder you select
Create groups
rather thanCreate folder references
in the import dialog -
Using C++ from Swift in Xcode 15 beta One
Make sure you don’t have
objective-c
andobjective-c++
selected underBuild-Settings Apple-Clang Module Verifier - Options for the C++ framework
- justobjective-c++
Also ensure your C++ “.hpp” file is set to
publc
in the target membership for the file properties if you can’t#import
with an errorfile not found
-
When I archive a project in Xcode it shows the wrong version. Why might that be?
Answer here
For a watch-only app, select the iOS target and update the value in Build Settings -> Versioning -> Marketing Version.
-
Using a Toggle in a MenuBar app
Also launching an app on system startup
import SwiftUI import ServiceManagement import Combine @main struct WatchControl_MacApp: App { @ObservedObject var menuState = LaunchOnStartupState.shared var body: some Scene { MenuBarExtra("WatchControl", image: "Image") { Toggle(isOn: $menuState.launchOnLogin) { Text("Launch on startup") } .toggleStyle(.checkbox) Divider() Button("Quit") { NSApplication.shared.terminate(nil) }.keyboardShortcut("q") } } } class LaunchOnStartupState : ObservableObject { static var shared = LaunchOnStartupState() @Published var launchOnLogin = SMAppService.mainApp.status == .enabled var cancelable: AnyCancellable? private init() { cancelable = $launchOnLogin.sink { newValue in do { if newValue { print(“Calling SMAppService.mainApp.register()") try SMAppService.mainApp.register() } else { print(“Calling SMAppService.mainApp.unregister()") try SMAppService.mainApp.unregister() } } catch { print(“Error \(newValue ? "" : "un")registering for startup: \(error)") } } } }
-
Encrypting and decrypting using a symetric key
Largely generated from ChatGPT
import Foundation import CommonCrypto class CryptUtils { static func encrypt(data: Data, key: String) -> Data? { let keyLength = kCCKeySizeAES128 let keyData = paddedKeyData(for: key, keyLength: keyLength) let bufferSize = data.count + kCCBlockSizeAES128 var buffer = Data(count: bufferSize) var numBytesEncrypted: Int = 0 let cryptStatus = keyData.withUnsafeBytes { keyBytes -> CCCryptorStatus in data.withUnsafeBytes { dataBytes -> CCCryptorStatus in buffer.withUnsafeMutableBytes { bufferBytes -> CCCryptorStatus in return CCCrypt( CCOperation(kCCEncrypt), CCAlgorithm(kCCAlgorithmAES), CCOptions(kCCOptionPKCS7Padding), keyBytes.baseAddress, keyLength, nil, // Use ECB mode (no Initialization Vector) dataBytes.baseAddress, data.count, bufferBytes.baseAddress, bufferSize, &numBytesEncrypted ) } } } if cryptStatus == kCCSuccess { buffer.count = numBytesEncrypted return buffer } else { print("Error: Failed to encrypt data") return nil } } static func decrypt(data: Data, key: String) -> Data? { let keyLength = kCCKeySizeAES128 let keyData = paddedKeyData(for: key, keyLength: keyLength) let bufferSize = data.count + kCCBlockSizeAES128 var buffer = Data(count: bufferSize) var numBytesDecrypted: Int = 0 let cryptStatus = keyData.withUnsafeBytes { keyBytes -> CCCryptorStatus in data.withUnsafeBytes { dataBytes -> CCCryptorStatus in buffer.withUnsafeMutableBytes { bufferBytes -> CCCryptorStatus in return CCCrypt( CCOperation(kCCDecrypt), CCAlgorithm(kCCAlgorithmAES), CCOptions(kCCOptionPKCS7Padding), keyBytes.baseAddress, keyLength, nil, // Use ECB mode (no Initialization Vector) dataBytes.baseAddress, data.count, bufferBytes.baseAddress, bufferSize, &numBytesDecrypted ) } } } if cryptStatus == kCCSuccess { buffer.count = numBytesDecrypted return buffer } else { print("Error: Failed to decrypt data") return nil } } private static func paddedKeyData(for key: String, keyLength: Int) -> Data { let keyData = key.data(using: .utf8)! let paddedKeyData = NSMutableData(length: keyLength)! keyData.withUnsafeBytes { (keyBytes: UnsafeRawBufferPointer) in if let baseAddress = keyBytes.baseAddress { paddedKeyData.replaceBytes(in: NSRange(location: 0, length: min(keyData.count, keyLength)), withBytes: baseAddress) } } return paddedKeyData as Data } }
-
Displaying a SwiftUI view from a MenuBar only app
import AppKit import SwiftUI struct MyAlertView: View { var body: some View { VStack { Text("This is a SwiftUI view in an alert.") Button("OK") { // Handle button action } } .frame(width: 300, height: 200) } } func activateApp() { let myApp = NSRunningApplication.current myApp.activate(options: .activateIgnoringOtherApps) } func showAlertWithSwiftUIView() { let panel = NSPanel(contentRect: NSRect(x: 0, y: 0, width: 300, height: 200), styleMask: [.titled, .closable, .fullSizeContentView], backing: .buffered, defer: false) panel.title = "Alert" panel.center() activateApp() panel.makeKeyAndOrderFront(nil) let hostingView = NSHostingView(rootView: MyAlertView(isPresented: .init(get: { panel.isVisible }, set: { isVisible in if !isVisible { panel.orderOut(nil) } }))) panel.contentView = hostingView }
-
Including changes in memory when querying core data
let context = PersistenceController.shared.container.viewContext return try context.performAndWait { let fetchRequest = DbResource.fetchRequest() fetchRequest.includesPendingChanges = true fetchRequest.predicate = NSPredicate(format: "bodyHash == %@", bodyHash) return try context.fetch(fetchRequest).first }
-
Extending an optional Double to convert it to an NSNumber
extension Optional where Wrapped == Double { var asNSNumber : NSNumber? { if let val = self { return NSNumber(floatLiteral: val) } else { return nil } } }
-
Custom Error with localizedDescription
enum EncyptError: LocalizedError { case error(String) public var errorDescription: String? { switch self { case .error(let message): return message } } }
-
Converting an audio (PCM) CMSampleBuffer to a Data instance
Assumes you set up your AVCaptureAudioDataOutput something like this (the key assumption is the bit depth):
let audioOutput = AVCaptureAudioDataOutput() audioOutput.audioSettings = [ AVFormatIDKey: kAudioFormatLinearPCM, AVNumberOfChannelsKey: 1, AVSampleRateKey: 16000.0, AVLinearPCMBitDepthKey: 16, AVLinearPCMIsBigEndianKey: false, AVLinearPCMIsFloatKey: false, AVLinearPCMIsNonInterleaved: false ]
This is the
setSampleBufferDelegate
delegate:func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { let byteCount = sampleBuffer.numSamples * sampleBuffer.sampleSize(at: 0) do { let unsafeRawPointer = UnsafeMutableRawPointer.allocate(byteCount: byteCount, alignment: 0) let pcmBufferPointer = UnsafeMutablePointer<AudioBufferList>.allocate(capacity: 1) pcmBufferPointer.initialize(to: AudioBufferList(mNumberBuffers: 1, mBuffers: AudioBuffer(mNumberChannels: 1, mDataByteSize: UInt32(byteCount), mData: unsafeRawPointer))) try sampleBuffer.copyPCMData(fromRange: 0..<sampleBuffer.numSamples, into: pcmBufferPointer) let data = Data(bytes: unsafeRawPointer, count: byteCount) // Do something with the data } catch { logE("Error converting buffer: \(error.localizedDescription)") }
You will likely not want to allocate the buffer on each callback.
-
Overriding default Help menu in SwiftUI Mac App
import SwiftUI @main struct AppleWatchAlexaApp: App { var body: some Scene { WindowGroup { ContentView() .resizedonMacOS(widthPercent: 1) } .commands { CommandGroup(replacing: .help) { NavigationLink("Voice in a Can Help", destination: WebView(url: URL(string: "https://voiceinacan.com/ios-faq/")!) ) } } } }
-
Date as yyyymmddhhss
extension Date { var yyymmddhhss: String { let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyMMddhhmmss" return dateFormatter.string(from: self) } }
-
'Unable to present. Please file a bug.' with multiple NavigationLinks
This is a known issue but the workaround of adding an empty
NavigationLink
didn’t work for me.On my Mac app when I have multiple NavigationLinks I get
Unable to present. Please file a bug.
when I tap on more than one.My hacky solution is to create a
NavigationButton
that replaces theNavigationLink
struct NavigationButton<Destination>: View where Destination: View { let text: String let destination: Destination @State var showing = false init(_ text: String, destination: Destination) { self.text = text self.destination = destination } var body: some View { ZStack { if showing { NavigationLink(text, destination: destination, isActive: $showing) .opacity(0) } Button(text) { showing = true } } } }
-
Decoding a JWT in Swift
Surprised it isn’t built-in. I’ve used JWTDecode.swift to decode tokens:
guard let jwt = try? decode(jwt: token), let expires = jwt.expiresAt else { print("Can't decode jwt") return }
-
if or guard on enum with a parameter instead of using a switch
Using an
if
or aguard
instead of aswitch
guard case let .onLogin(account) = gigyaEvent, let uid = account.UID else { return }
-
Enabling Core Data Encryption in Swift
From https://stackoverflow.com/a/65525585/3390
container = NSPersistentContainer(name: "Model") container.persistentStoreDescriptions.first!.setOption(FileProtectionType.complete as NSObject, forKey: NSPersistentStoreFileProtectionKey) container.loadPersistentStores(completionHandler: { (storeDescription, error) in
-
Sharing files
Use
share
func from https://stackoverflow.com/a/59515229/3390 -
Creating ZIP files in Swift
I’ve used ZIPFoundation
let archive = Archive(accessMode: .create) // Create it in memory // Add a file try archive?.addEntry(with: "export/photos/\(photo_id)", fileURL: filename) // Add string as a file try archive?.addEntry(with: "export/data.csv", type: .file, uncompressedSize: UInt32(output.count)) { position, size in return output.data(using: .utf8)! } // Write ZIP as a file if let data = archive?.data { let exportFile = FileManager.default.temporaryDirectory.appendingPathComponent("export.zip") print("Path: \(exportFile.path)") try data.write(to: exportFile) }
-
Add hours from one date to another date
let date = Calendar.current.date(byAdding: DateComponents(hour: Calendar.current.component(.hour, from: otherDate)), to: thisDate)
-
Delete all local git branches except main
git for-each-ref --format '%(refname:short)' refs/heads | grep -v main | xargs git branch -D
-
Recording a simulator video
xcrun simctl io booted recordVideo --force --codec h264 fred.mov
-
Stop iPad Split View in SwiftUI
Set
navigationViewStyle
toStackNavigationViewStyle
NavigationView { TheTabView() } .navigationViewStyle(StackNavigationViewStyle())
-
Launching processes in Swift
Launching multiple commands in Swift
do { try writePost() let add = Process() add.currentDirectoryPath = root add.executableURL = URL(fileURLWithPath: git) add.arguments = ["add", "."] try add.run() let commit = Process() commit.currentDirectoryPath = root commit.executableURL = URL(fileURLWithPath: git) commit.arguments = ["commit","-m", "\"title\""] try commit.run() commit.waitUntilExit() let push = Process() push.currentDirectoryPath = root push.executableURL = URL(fileURLWithPath: git) push.arguments = ["push"] try push.run() push.waitUntilExit() } catch { errorMessage = "Error: \(error)" }
-
XCTest can't tap SwiftUI Toggle
Using
tap
on a SwiftUIToggle
wasn’t working for me:let app = XCUIApplication() let sw = app.switches["My SwiftUI Toggle"] XCTAssert(sw.value as! String == "0") sw.tap() XCTAssert(sw.value as! String == "1")
The above fails. I think this is because tapping the label part of the Toggle does nothing. Instead, I try to tap the switch part of it, which works:
let app = XCUIApplication() let sw = app.switches["My SwiftUI Toggle"] XCTAssert(sw.value as! String == "0") sw.coordinate(withNormalizedOffset: CGVector.zero).withOffset(CGVector(dx: sw.frame.width - 10, dy: sw.frame.height / 2)).tap() XCTAssert(sw.value as! String == "1")
Now it works - I tap in the vertical center, on the right side of the switch, minus ten points.
-
Formatting a single swift date field in JSON
You want to use one encoding strategy overall to encode JSON dates, but one particular field needs to be formatted using a different formatting?
Normally you’d set the encoding strategy for the whole encoding:
let encoder = JSONEncoder() encoder.dateEncodingStrategy = .millisecondsSince1970 // or iso8601 encoder.encode(myObject)
But what if deep down in the structure or class, one date field needs to be formatted a different way, such as the
timeStamp
field here?struct GeolocationState: EventBase { let timestamp: Date let coordinate: Coordinate let altitude: Altitude? let heading: Heading? let speed: Speed? }
My solution is to wrap the date in my own struct, and then I can control the encoding for that:
struct GeolocationState: EventBase { let timestamp: ISO8601Date let coordinate: Coordinate let altitude: Altitude? let heading: Heading? let speed: Speed? } struct ISO8601Date: Encodable { static let formatter = ISO8601DateFormatter() let date: Date init(_ date: Date) { self.date = date } enum CodingKeys: CodingKey { case date } func encode(to encoder: Encoder ) throws { var container = encoder.singleValueContainer() try container.encode(ISO8601FormattedDate.formatter.string(from: date)) } }
-
Detecting when state variable changes
I tried using
willSet
ordidSet
on an@State
variable, but it didn’t work@State var consumed: Bool = false { didSet { print("never called") } }
Instead what works is to use the
onChange
event:Toggle("My toggle", isOn: $consumed) .onChange(of: self.consumed) { v in print("is called") }
-
isActive not working to go back when three levels deep
In my app I am using
NavigationLink.isActive
to programatically go back by setting a bound variable tofalse
. I was doing this several levels deep, and although I could initially go back, once I pushed several views onto the stack, and then went back, I found the back button stopped working on one of the pages.I also noticed this error:
2021-01-13 18:02:26.660739+0100 Resolute[6210:333764] [Assert] displayModeButtonItem is internally managed and not exposed for DoubleColumn style. Returning an empty, disconnected UIBarButtonItem to fulfill the non-null contract.
This Stack Overflow page suggested setting the
navigationViewStyle
toStackNavigationViewStyle
:NavigationView { ... } .navigationViewStyle(StackNavigationViewStyle())
This both got rid of the error, and the back button started working (setting the
isActive
bound variable tofalse
) -
VS Code Regex to duplicate the text on each line
Replace
(.*)
with$1 $1
-
Adding days/weeks/months to dates
let today = Date() let date = Calendar.current.date(byAdding: .day, value: 7, to: today)!
-
Converting an object to a raw pointer and back
To a pointer
let rawPointer = unsafeBitCast(anObject, to: UnsafeMutableRawPointer.self)
… and back
let anObject = Unmanaged<TheClassObjectsClass>.fromOpaque(UnsafeRawPointer(rawPointer)).takeUnretainedValue()
-
A failed attempt to get an AVAsset from a data uri
This is my attempt. It doesn’t work. The best workaround is to write the data to file first
var base64 = data.base64EncodedString(options: []) base64 = base64.replacingOccurrences(of: "=", with: "") base64 = base64.replacingOccurrences(of: "+", with: "-") base64 = base64.replacingOccurrences(of: "/", with: "_") let dataURL = URL(string: "data:audio/mpeg;base64,\(base64)")! let asset = AVAsset(url: dataURL) let millis = Int(CMTimeGetSeconds(asset.duration)*1000) // Returns zero
-
When JSON encoding a Double there are too many decimal places
If you are trying to generate JSON and a double is encoded with loads of decimal places and weird “1” at the end, like this:
struct Coordinate: Encodable { let latitudeInDegrees: Double let longitudeInDegrees: Double let accuracyInMeters: Double } let coordinate = Coordinate(latitudeInDegrees: 37.785834, longitudeInDegrees: -122.406417, accuracyInMeters: 5)
Generates JSON:
{ "coordinate" : { "accuracyInMeters" : 5, "latitudeInDegrees" : 37.785834000000001, "longitudeInDegrees" : -122.406417 } }
Change the type from
Double
toDecimal
:struct Coordinate: Encodable { let latitudeInDegrees: Decimal let longitudeInDegrees: Decimal let accuracyInMeters: Decimal }
-
Making JSON have both sorted keys and pretty printed
let encoder = JSONEncoder() encoder.outputFormatting = JSONEncoder.OutputFormatting([.prettyPrinted, .sortedKeys])
-
Adding a framework to a test target
I wanted to add the AnyCodable to both my iOS project, and the test project that tests it.
When I added it to just my iOS project I got the error
Undefined symbol: nominal type descriptor for AnyCodable.AnyCodable
when trying to run tests.My solution was to remove the framework, and then re-add it, this time specifying the test target as the target into which the framework should be added.
Once I did that, I was
then
able to go to my iOS project’s target, and in theGeneral
pane, scroll down toFrameworks, Libraries, and Embedded Content
and add it there. -
Swift does not preserve field order when encoding json
Converting code from .NET to Swift I’ve discovered that Swift does not preserve the order in which fields are declared when encoding JSON.
There is a bug about it: https://bugs.swift.org/browse/SR-7992
Support forums are full of people saying the order should not matter, but the reality is that some servers, over which we have no control, require a specific ordering, and it would be nice if Swift supported specifying or even preserving the field order when encoding JSON.
My solution, in a very limited situation, was to use string interpolation to insert my values into a pre-encoded JSON string which had the correct ordering.
-
Indexing into a string
// [3] = (key = "Content-Type", value = "multipart/related; boundary=------abcde123; type=application/json") let boundaryKey = "boundary=" guard let contentType = headers["Content-Type"] else { logE("opened", "No content type header)") return } let contentTypeParts = contentType.split(separator: ";").map {$0.trimmingCharacters(in: .whitespaces) } guard let boundaryPart = contentTypeParts.first(where: { $0.starts(with: boundaryKey)}) else { logE("opened", "Can't find boundary in \(contentType)") return } let boundary = String(boundaryPart[boundaryPart.index(boundaryPart.startIndex, offsetBy: boundaryKey.count)...])
-
Adding a font to a SwiftUI app
Download and unzip the font, for example from https://fonts.google.com/specimen/Poppins
Drag the
.ttf
(for examplePoppins-Bold.ttf
) file into your Xcode project, perhaps in a folder calledFonts
and ensure that it is included in your project’s target (select it and verifyTarget Membership
in the file properties).Edit your
info.plist
and add a top levelFonts provided by application
node, and then a childItem 0
node with a value of the name of your font, for examplePoppins-Bold.ttf
.Use the font in your app:
Text("hello") .font(.custom("Poppins-Bold", size: 48))
-
SwiftUI Radial Gradient with hex
background: linear-gradient(197.54deg, #D0A0C3 0%, #D94E42 52.73%, #FAEF64 100%);
struct Hello: View { var body: some View { VStack() { Text("hello") } .frame(maxWidth: .infinity, maxHeight: .infinity) .foregroundColor(.white) .background(LinearGradient(gradient: Gradient(colors: [ Color(red: 0xD0/255.0, green: 0xA0/255.0, blue: 0xC3/255.0), Color(red: 0xD9/255.0, green: 0x4E/255.0, blue: 0x42/255.0), Color(red: 0xFA/255.0, green: 0xEF/255.0, blue: 0x64/255.0), ]), startPoint: .topTrailing, endPoint: .bottomLeading)) } }
-
Opening a URL
Button("How?") { UIApplication.shared.open(URL(string: "https://support.garmin.com/en-US/?faq=lK5FPB9iPF5PXFkIpFlFPA")!) }
-
Multiple Sheets not working in SwiftUI
You don’t use multiple sheets … instead use a single sheet with an enum. https://stackoverflow.com/a/63181811/3390
@State var activeSheet: ActiveSheet? = .showGarminExplanation enum ActiveSheet: Identifiable { case fitbitLogin, showGarminExplanation, showXaiomiExplanation, showOuraExplanation var id: Int { hashValue } } ... .sheet(item: $activeSheet) { item in switch item { case .fitbitLogin: SafariView(url: fitbit.url!) case .showGarminExplanation: GarminExplanationView() case .showXaiomiExplanation: GarminExplanationView() case .showOuraExplanation: GarminExplanationView() } }
-
RadioGroupPickerStyle not found
The reason you can’t find
RadioGroupPickerStyle
on in your SwiftUI iOS app is that it is only available on macOS -
SwiftUI navigating
var body: some View { NavigationView { VStack { Spacer() Image("someimage") .resizable() .aspectRatio(contentMode: .fit) Spacer() } .navigationBarTitle("Welcome!") .navigationBarItems(trailing: NavigationLink("Next", destination: AnotherView(), isActive: $moveNext) ) .onAppear(perform: { DispatchQueue.main.asyncAfter(deadline: .now() + 2) { withAnimation { self.moveNext = true } } }) } }
-
Swift Localization
- Open Project properties and under
Localizations
addFrench
toBase
andEnglish-Development Language
- Add a new file called
Localizable.strings
using theNew File
dialog and filtering toStrings File
- Right-click the new file, select
Show File Inspector
and underLocalization
check bothEnglish
andFrench
- Two sub-files under
Localizable.strings
should have appeared
To preview a language in SwiftUI
struct HomeView_Previews: PreviewProvider { static var previews: some View { HomeView() .environment(\.locale, .init(identifier: "fr")) } }
- Open Project properties and under
-
Rounding the rectangle of a view background
VStack { Label("text", systemImage: "pills.fill") .foregroundColor(.orange) .font(.title3) } .background(RoundedRectangle(cornerRadius: 25.0).foregroundColor(.orange).opacity(0.05))
-
Averaging a collection of values in Swift
let averageMinutesAsleep = itemsToConsider.reduce(0) { $0 + $1.minutesAsleep} / itemsToConsider.count
-
Interval in seconds between two dates in Swift
let seconds = Int(Date().timeIntervalSince(expires))
-
Swift date in user defaults
let expires = defaults.object(forKey: defaultsTokenExpiresName) as? Date
-
Switching between open tabs in Xcode
Next Tab:
Command-{
which isCommand-Shift-[
Prevous Tab:Command-{
which isCommand-Shift-]
-
Using the keychain from Swift
Based on a blog post I wrote on Sharing tokens between iOS, macOS and watchOS app using the iCloud KeyChain which is I am sure based on something else.
import os import Foundation class KeyStore { func store(name: String, token : String) { let data = token.data(using: .utf8)! let addquery: [String: Any] = [kSecClass as String: kSecClassGenericPassword as String, kSecAttrAccount as String: name, kSecValueData as String: data ] SecItemDelete(addquery as CFDictionary) let status : OSStatus = SecItemAdd(addquery as CFDictionary, nil) guard status == errSecSuccess else { os_log("store: whoops") return } } func clear(name: String) { let addquery: [String: Any] = [kSecClass as String: kSecClassGenericPassword as String, kSecAttrAccount as String: name ] SecItemDelete(addquery as CFDictionary) } func retrieve(name: String) -> String? { let getquery: [String: Any] = [kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: name, kSecReturnData as String: kCFBooleanTrue!, kSecMatchLimit as String : kSecMatchLimitOne ] var item: CFTypeRef? let status = SecItemCopyMatching(getquery as CFDictionary, &item) guard status == errSecSuccess else { os_log("keyStore.retrieve SecItemCopyMatching error \(status)") return nil } guard let data = item as? Data? else { os_log("keyStore.retrieve not data") return nil } return String(data: data!, encoding: String.Encoding.utf8) } }
-
Bolding text in SwiftUI
Text("normal text ") + Text("bold text").bold() + Text(" normal text")
-
A VS Code Snippet to create Jekyll blog post frontmatter
"entry": { "scope": "markdown", "prefix": "en", "body": [ "---", "layout: post", "title: \"${1:title}\"", "date: $CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE $CURRENT_HOUR:$CURRENT_MINUTE:$CURRENT_SECOND +0100", "---", "${2:body}" ], "description": "post" }
Create/update a root-level
settings.json
to enable tab-completion:{ "editor.tabCompletion": "on" }
-
Stopping SwiftUI Text from being clipped
Text("You've been getting an average of 7 hours and 23 minutes of sleep each night over the last month, which is great. Keep it up!") .fixedSize(horizontal: false, vertical: true) .padding()
From Reddit
-
Changing the currently selected SwiftUI TabView tab
struct OnboardingWizardView: View { @State var selectedTab = 0 var body: some View { TabView(selection: $selectedTab) { Page1().tag(0) Page2().tag(1) }.tabViewStyle(PageTabViewStyle()) .onAppear(perform: { DispatchQueue.main.asyncAfter(deadline: .now() + 2) { withAnimation { self.selectedTab = 1 } } }) } }
-
Delaying execution of code in SwiftUI
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { self.showProgress = false }
-
VS Code Mac keyboard shortcut to stage changes
Ctrl-Shift-G
-
Making a SwiftUI Text fill the frame
Text("Welcome") .font(.largeTitle) .frame(maxWidth: .infinity, maxHeight: .infinity)
-
Resuming Xcode SwiftUI live preview
To resume Xcode SwiftUI Live Preview press
Option-Command-P
-
Royalty free images for use in apps
Royalty free images for use in apps: https://unsplash.com/
-
Carousel view/multiple pages in SwiftUI
To create a carousel view in SwiftUI, with multiple pages, use the
TabView
with.tabViewSyle
set toPageTabViewStyle
-
Mac Screenshot
To open the screenshot utility:
Shift Command 5
Saves to
Downloads
-
Getting a # component from a URL
From https://stackoverflow.com/a/57933248/3390
func HandleCallback(url: URL) { var components = URLComponents() components.query = url.fragment accessToken = components.queryItems?.first(where: { $0.name == "access_token"})?.value }
-
Formatting and delta dates in Swift
let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" let today = dateFormatter.string(from: Date()) let monthAgo = dateFormatter.string(from: NSCalendar.current.date(byAdding: .month, value: -1, to: NSDate() as Date)!)
-
SwiftUI Separator
The SwiftUI separator is called a divider
-
Formatting numbers in SwiftUI
Text("\(food.loggedFood.amount, specifier: "%.1f") \(food.loggedFood.unit.plural)")
-
A generic Swift REST call/decode function with a type as a parameter
Pass the type of a generic parameter using
T.Type
var cancellables = [AnyCancellable]() fileprivate func GetData<T>(url: URL, token: String, resultType: T.Type, callback: @escaping (T) -> Void) where T:Codable { var request = URLRequest(url: url) request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization") URLSession.shared.dataTaskPublisher(for: request) .tryMap() { element -> Data in // let s = String(data: element.data, encoding: .utf8) // print(s) guard let httpResponse = element.response as? HTTPURLResponse, httpResponse.statusCode == 200 else { throw URLError(.badServerResponse) } return element.data } .decode(type: resultType, decoder: self.decoder) .receive(on: DispatchQueue.main) .sink(receiveCompletion: { v in print(v) }, receiveValue: { v in callback(v) }) .store(in: &self.cancellables) }
-
Widening Jekyll content area
If your
minima
Jekyll page width is too narrow, copy the_sass
folder from your Jekyll installation to your web site folder, and then editminima.scss
to update the width:// Width of the content area $content-width: 2048px !default;
You can find out where
minima
is installed usingbundle info --path minima
-
Launching Jekyll
When trying to serve your site using
jekyll
and you get an error like this:jekyll serve ... /Library/Ruby/Gems/2.6.0/gems/bundler-2.1.4/lib/bundler/spec_set.rb:86:in `block in materialize': Could not find public_suffix-4.0.6 in any of the sources (Bundler::GemNotFound)
don’t forget you need to use
bundle exec jekyll serve
subscribe via RSS