How to use method from protocol extension in Swift

Issue #524 /// Any task that uses command line public protocol UsesCommandLine: AnyObject { var program: String { get } var arguments: Set<String> { get set } } public extension UsesCommandLine { func run() throws { let command = "\(program) \(arguments.joined(separator: " "))" Log.command(command) _ = try Process().run(command: command) } } class Build: UsesCommandLine { public func run() throws { arguments.insert("build") try (self as UsesCommandLine).run() } }

November 30, 2019 · 1 min · 67 words · Khoa

How to organize dependencies in Swift Package Manager

Issue #523 In Puma I want to make build tools for iOS and Android, which should share some common infrastructure. So we can organize dependencies like. Puma -> PumaAndroid, PumaiOS -> PumaCore -> xcbeautify, Files, Colorizer // swift-tools-version:5.1 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( name: "Puma", platforms: [.macOS("10.15")], products: [ .library(name: "Puma", targets: ["Puma"]) ], dependencies: [ ....

November 30, 2019 · 1 min · 145 words · Khoa

How to provide configurations in Swift

Issue #522 Sometimes ago I created Puma, which is a thin wrapper around Xcode commandline tools, for example xcodebuild There’s lots of arguments to pass in xcodebuild, and there are many tasks like build, test and archive that all uses this command. Use Options struct to encapsulate parameters To avoid passing many parameters into a class, I tend to make an Options struct to encapsulate all passing parameters. I also use composition, where Build....

November 30, 2019 · 3 min · 615 words · Khoa

How to use SurveyMonkey in React Native

Issue #521 #import <React/RCTBridgeModule.h> @interface RNSurveyManager : NSObject <RCTBridgeModule> @end #import "RNSurveyManager.h" #import <React/RCTLog.h> #import <SurveyMonkeyiOSSDK/SurveyMonkeyiOSSDK.h> @interface RNSurveyManager()<SMFeedbackDelegate> @property (nonatomic, strong) SMFeedbackViewController * feedbackController; @end @implementation RNSurveyManager - (instancetype)init { self = [super init]; if (self) { self.feedbackController = [[SMFeedbackViewController alloc] initWithSurvey:@"VV8X5QA"]; self.feedbackController.delegate = self; } return self; } + (BOOL)requiresMainQueueSetup { return YES; } - (dispatch_queue_t)methodQueue { return dispatch_get_main_queue(); } RCT_EXPORT_MODULE(SurveyManager); - (void)respondentDidEndSurvey:(SMRespondent *)respondent error:(NSError *)error { NSLog(@"respondent %@ error %@", respondent, error); } RCT_EXPORT_METHOD(show:(RCTResponseSenderBlock)callback) { [UIApplication....

November 29, 2019 · 1 min · 111 words · Khoa

How to allow unnotarized app to run on macOS Catalina

Issue #520 Remove quarantine xattr -d com.apple.quarantine /Applications/Flipper.app

November 28, 2019 · 1 min · 8 words · Khoa

How to use flipper

Issue #519 Run the app https://github.com/facebook/flipper https://facebook.github.io/watchman/docs/install.html#installing-on-os-x-via-homebrew brew install watchman git clone https://github.com/facebook/flipper.git cd flipper yarn yarn start

November 27, 2019 · 1 min · 18 words · Khoa

How to test UserDefaults in iOS

Issue #518 let userDefaults = UserDefaults(suiteName: suiteName) userDefaults.removePersistentDomain(forName: suiteName) https://developer.apple.com/documentation/foundation/userdefaults/1417339-removepersistentdomain Calling this method is equivalent to initializing a user defaults object with init(suiteName:) passing domainName, and calling the removeObject(forKey:) method on each of its keys. Read more https://www.swiftbysundell.com/articles/the-power-of-userdefaults-in-swift/ http://dscoder.com/defaults.html https://medium.com/swift-india/userdefaults-under-the-hood-457461c8d262

November 25, 2019 · 1 min · 40 words · Khoa

How to use ForEach with ScrollView in SwiftUI

Issue #517 Use ScrollView -> VStack -> ForEach -> Content struct SearchScreen: View { @State var searchObjects: [SearchObject] = [ SearchObject(name: "By name", search: { CountryManager.shared.search(byName: $0) }), SearchObject(name: "By calling code", search: { CountryManager.shared.search(byCallingCode: $0) }), SearchObject(name: "By domain", search: { CountryManager.shared.search(byDomain: $0) }), SearchObject(name: "By language", search: { CountryManager.shared.search(byLanguage: $0) }) ] var body: some View { ScrollView { VStack(alignment: .leading) { ForEach(searchObjects.enumerated().map({ $0 }), id: \.element.name, content: { index, searchObject in VStack(alignment: ....

November 22, 2019 · 1 min · 91 words · Khoa

How to modify data inside array in SwiftUI

Issue #516 Suppose we have an array of SearchObject, and user can enter search query into text property. class SearchObject: ObservableObject { let name: String let search: (String) -> [Country] var text: String = "" init(name: String, search: @escaping (String) -> [Country]) { self.name = name self.search = search } } Although SearchObject is class, when we use ForEach, the changes to passed object won’t be reflected in our array and there is no reload trigger, we need to point to object in array directly, like...

November 22, 2019 · 1 min · 168 words · Khoa

How to use index in SwiftUI list

Issue #515 Use enumerated and id: \.element.name struct CountriesView: View { let countries: [Country] var body: some View { let withIndex = countries.enumerated().map({ $0 }) return List(withIndex, id: \.element.name) { index, country in NavigationLink( destination: CountryView(country: country), label: { VStack(alignment: .leading) { Text(country.name) .styleMultiline() } .paddingVertically() } ) } } }

November 22, 2019 · 1 min · 51 words · Khoa

How to setup multiple git accounts for GitHub and Bitbucket

Issue #514 Generate SSH keys ssh-keygen -t rsa -C "onmyway133@gmail.com" -f "id_rsa_github" ssh-keygen -t rsa -C "onmyway133bitbucket@gmail.com" -f "id_rsa_bitbucket" pbcopy < ~/.ssh/id_rsa_github.pub pbcopy < ~/.ssh/id_rsa_bitbucket.pub ssh-add -D ssh-add id_rsa_github ssh-add id_rsa_bitbucket vim ~/.ssh/config #Github (personal) Host gh HostName github.com User git IdentityFile ~/.ssh/id_rsa_github #Bitbucket (work) Host bb HostName bitbucket.org User git IdentityFile ~/.ssh/id_rsa_bitbucket Config git config --global user.email "onmyway133@gmail.com" git config --local user.email "onmyway133bitbucket@gmail.com" Read more https://medium.com/avocoders/github-and-bitbucket-accounts-in-a-same-pc-5f8c67fd89d2 https://www.atlassian.com/git/tutorials/setting-up-a-repository/git-config Updated at 2020-10-04 06:52:07

November 22, 2019 · 1 min · 72 words · Khoa

How to use objectWillChange in Combine

Issue #513 A publisher that emits before the object has changed Use workaround DispatchQueue to wait another run loop to access newValue .onReceive(store.objectWillChange, perform: { DispatchQueue.main.async { self.reload() } }) func reload() { self.isFavorite = store.isFavorite(country: country) } Read more https://forums.swift.org/t/combine-observableobject-in-uikit/28433 https://twitter.com/luka_bernardi/status/1155944329363349504

November 21, 2019 · 1 min · 42 words · Khoa

How to enable z and zsh-autosuggestions on zsh

Issue #512 https://github.com/zsh-users/zsh-autosuggestions/blob/master/INSTALL.md https://github.com/robbyrussell/oh-my-zsh/tree/master/plugins/z git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions vim ~/.zsh.rc /plugins plugins=( git z zsh-autosuggestions ) source ~/.zshrc

November 19, 2019 · 1 min · 18 words · Khoa

How to show list with section in SwiftUI

Issue #511 struct CountriesView: View { let groups: [Group] init(countries: [Country]) { self.groups = CountryManager.shared.groups(countries: countries) } var body: some View { List { ForEach(groups) { group in Section( header: Text(group.initial) .foregroundColor(Color.yellow) .styleTitle(), content: { ForEach(group.countries) { country in CountryRow(country: country) } } ) } } } }

November 16, 2019 · 1 min · 48 words · Khoa

How to group array by property in Swift

Issue #510 Use Dictionary(grouping:by:) func groups(countries: [Country]) -> [Group] { let dictionary = Dictionary(grouping: countries, by: { String($0.name.prefix(1)) }) let groups = dictionary .map({ (key: String, value: [Country]) -> Group in return Group(initial: key, countries: value) }) .sorted(by: { $0.initial < $1.initial }) return groups }

November 16, 2019 · 1 min · 46 words · Khoa

How to make full width list row in SwiftUI

Issue #508 We need to use frame(minWidth: 0, maxWidth: .infinity, alignment: .leading). Note that order is important, and padding should be first, and background after frame to apply color to the entire frame struct BooksScreen: View { @ObservedObject var viewModel: BooksViewModel var body: some View { List { ForEach(viewModel.books) { book in RowView(vault: book) } } .listStyle(GroupedListStyle()) } } private struct RowView: View { let book: Book var body: some View { VStack(alignment: ....

November 14, 2019 · 1 min · 94 words · Khoa

How to make full screen TabView in SwiftUI

Issue #507 View extends to the bottom, but not to the notch. We need to add .edgesIgnoringSafeArea(.top) to our TabView to tell TabView to extend all the way to the top. Note that if we use edgesIgnoringSafeArea(.all) then TabView ’s bar will be dragged very down and broken. struct MainScreen: View { init() { UITabBar.appearance().backgroundColor = R.color.barBackground UITableView.appearance().backgroundColor = .clear UITableViewCell.appearance().backgroundColor = .clear UITableView.appearance().tableFooterView = UIView() } var body: some View { ZStack { R....

November 14, 2019 · 1 min · 104 words · Khoa

How to map error in Combine

Issue #506 When a function expects AnyPublisher<[Book], Error> but in mock, we have Just func getBooks() -> AnyPublisher<[Book], Error> { return Just([ Book(id: "1", name: "Book 1"), Book(id: "2", name: "Book 2"), ]) .eraseToAnyPublisher() } There will be a mismatch, hence compile error Cannot convert return expression of type ‘AnyPublisher<[Book], Just.Failure>’ (aka ‘AnyPublisher<Array, Never>’) to return type ‘AnyPublisher<[Book], Error>’ The reason is because Just produces Never, not Error. The workaround is to introduce Error...

November 14, 2019 · 1 min · 107 words · Khoa

How to fix unable to infer complex closure return type in SwiftUI

Issue #505 Make sure all String are passed into Text, not Optional<String> VStack { Text(data.title) Text(data.description!) Text(data.text!) }

November 13, 2019 · 1 min · 18 words · Khoa

How to make Swift Package Manager package for multiple platforms

Issue #504 https://twitter.com/NeoNacho/status/1181245484867801088?s=20 There’s no way to have platform specific sources or targets today, so you’ll have to take a different approach. I would recommend wrapping all OS specific files in #if os and just having one target. For tests, you could do something similar, one test target, but conditional tests Every files are in Sources folder, so we can use platform and version checks. For example Omnia is a Swift Package Manager that supports iOS, tvOS, watchOS, macOS and Catalyst....

November 13, 2019 · 1 min · 119 words · Khoa