Xcode Swift Code Snippets
Swiftに限らず、開発する際に同じ処理をなんども一から書いたり、調べることからスタートするのは面倒です。
そこでSwiftのコードスニペットをさがしたところ、
Xcode Swift Code Snippets
を見つけました。
Inspiration
I was inspired by Matt Thompson's Xcode-Snippets article and GitHub repo but I haven't found anything similar for Swift.
I also used that thing in swift and SwiftSingleton as a sample implementations.
あの有名なMattさんのObjective-Cのスニペットに感化されSwift版を作成したそうです。
本記事ではどんなスニペットが用意されているかをまとめました。
導入方法などはこちら
swift-documentdirectory
ドキュメントディレクトリへのパスを取得できます。
if let path = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first {
let documentsDirectoryURL = NSURL.fileURL(withPath: path)
}
🔽iOSのデータ保存先について
iOS App
├── Documents
├── Library
│ ├── Caches
│ └── Preferences
└── tmp
Documents/
・ユーザが作成したデータ(テキスト、写真)、再作成が不可能なデータなど重要なデータを保存する。
・ユーザに見せたくないファイル(設定ファイルなど)はここに置かない。
・iTunes、iCloud バックアップ対象。
Library/
・ユーザのデータファイル以外を保存するディレクトリ。自分でサブディレクトリを用意して保存する。
・ユーザに見せたくないファイルはここに置く。
・iTunes、iCloud バックアップ対象(Caches ディレクトリを除く)。
Library/Caches/
・一時的なデータを保存するディレクトリ。システムが自動削除する可能性がある。
・後から再度ダウンロードして復旧可能なデータを置くこと。
・iTunes、iCloud バックアップ対象外。
Library/Preferences/
・アプリの設定を保存するディレクトリ。NSUserDefaultsのデータはここに保存される。
tmp/
・一時的なデータを保存するディレクトリ。アプリが動作してないときにシステムが自動削除する可能性がある。
・iTunes、iCloud バックアップ対象外。
・使い終わったらアプリ側で削除して容量削減に務める。
swift-dispatchafter
遅延実行処理。一定時間後に処理を行う。
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(<#seconds#>)) {
}
swift-dispatchasync
非同期処理
DispatchQueue.global(qos: .default).async {
// グローバルキューで実行される
DispatchQueue.main.async {
// メインキューで実行される
}
}
swift-dispatchmain
メインキューで非同期処理を実行
DispatchQueue.main.async(execute: { () -> Void in
// 処理
})
swift-nslocalizedstring
多言語対応設定
NSLocalizedString(<#key#>, comment: <#comment#>)
swift-closuretypealias
引数、戻り値をもつ、typealiasを設定したクロージャ。
引数に複雑な型のクロージャを取る関数の定義は読みにくいです。
typealiasキーワードを用いることで 可読性が高まります。
typealias <#ClosureName#> = (_ <#arguments#>: <#type#>) -> <#return value#>
swift-closureoptionaltypealias
引数、戻り値をもつ、typealiasを設定したオプショナルなクロージャ。
typealias <#ClosureName#> = ((_ <#arguments#>: <#type#>) -> <#return value#>)?
swift-weak
クロージャ内で[weak self]
を使用する。
[weak self] in
guard let strongSelf = self else { return }
swift-uitableviewdelegate
UITableViewDelegate
//MARK: UITableViewDelegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
}
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
}
swift-uitableviewdatasource
UITableViewDataSource
//MARK: UITableViewDataSource
func numberOfSections(in tableView: UITableView) -> Int {
return <#numberOfSections#>
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return <#numberOfRows#>
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: <#identifier#>, for: indexPath)
configureCell(cell: cell, forRowAt: indexPath)
return cell
}
func configureCell(cell: UITableViewCell, forRowAt indexPath: IndexPath) {
}
swift-forin
パターンマッチ。
コレクション型を任意のオブジェクトへキャストし、for-in
文を回す。
for case let <#object#> in <#collection#> as [<#Type#>] {
}
🔽使用例
let sampleDict = ["key1": "one", "key2": "two"]
for case let (key, "one") in sampleDict as [String: String] {
print(key)
}
// 出力結果
// key1
swift-ibo
IBOutlet
@IBOutlet weak var <# OutletName #>: <# OutletType #>!
swift-sortarrayofstrings
ロケールに対応した配列のソート
<#arrayOfStrings#>.sorted { (a, b) -> Bool in
let comparisonResult = a.compare(b, options: [], range: a.range(of: a), locale: Locale.current)
// 右辺を変更することで、昇順・降順を設定する
return comparisonResult == .orderedSame
}
🔽使用例
var testArray = ["d", "b", "c", "a"]
testArray = testArray.sorted { (a, b) -> Bool in
let comparisonResult = a.compare(b, options: [], range: a.range(of: a), locale: Locale.current)
return comparisonResult == .orderedAscending
}
print(testArray)
swift-urlsession-datatask
シンプルなHTTPリクエスト処理
let session = URLSession.shared
let task = session.dataTask(with: <#request#>){ (data, response, error) in
<#code#>
}
task.resume()
swift-urlsession-delegate
デリゲートを伴うHTTPリクエスト処理
let session = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
let task = session.dataTask(with: <#request#>){ (data, response, error) in
<#code#>
}
task.resume()
swift-uiviewcontrollerlifecycle
UIViewControllerのライフサイクル
//MARK: UIViewController lifecycle
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
}
swift-uicollectionviewdelegate
UICollectionViewDelegate 処理
//MARK: UICollectionViewDelegate
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
}
swift-uicollectionviewdatasource
UICollectionViewDataSource
//MARK: UICollectionViewDataSource
func numberOfSections(in collectionView: UICollectionView) -> Int {
return <#numberOfSections#>
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// TODO:- Required Method
return <#numberOfItems#>
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: <#identifier#>, for: indexPath)
configureCell(cell: cell, forItemAt: indexPath)
// TODO:- Required Method
return cell
}
func configureCell(cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let view = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: <#identifier#>, for: indexPath)
return view
}
swift-uiremotenotification
リモート通知機能における、登録処理とハンドリングメソッド
//MARK: Remote Notifications
// Move this line somewhere where your app starts
// UIApplication.shared.registerForRemoteNotifications()
// Ask user for allowed notification types
// let settings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
// UIApplication.shared.registerUserNotificationSettings(settings)
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print("Successfully egistered for Remote Notifications with token: \(deviceToken)")
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Registration for Remote Notifications failed with error: \(error)")
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
}
swift-mark
マーク記述を追記して、コードをセクションごとに分ける
// MARK: - <#Section#>
swift-didbecomeactive
アプリケーションがアクティブになった時のオブザーバーを設定
NotificationCenter.default.addObserver(self, selector: #selector(<#selector#>), name: NSNotification.Name.UIApplicationDidBecomeActive, object: nil)
swift-mail
MFMailComposeViewController
メーラーの起動・送信処理
//MARK: MFMailComposeViewController
func presentModalMailComposerViewController(animated: Bool) {
if MFMailComposeViewController.canSendMail() {
let mailComposeVC = MFMailComposeViewController()
mailComposeVC.delegate = <#delegate#>
mailComposeVC.setSubject(<#subject#>)
mailComposeVC.setMessageBody(<#body#>, isHTML: true)
mailComposeVC.setToRecipients([<#recipients#>])
present(mailComposeVC, animated: animated, completion: nil)
} else {
let alert = UIAlertController(title: NSLocalizedString("Error", value: "Error", comment: ""),
message: NSLocalizedString("Your device doesn't support Mail messaging", value: "Your device doesn't support Mail messaging", comment: ""),
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: "Cancel"), style: .cancel, handler: nil))
present(alert, animated: true, completion: nil)
}
}
//MARK: MFMailComposeViewControllerDelegate
func mailComposeController(controller: MFMailComposeViewController!, didFinishWithResult result: MFMailComposeResult, error: NSError!) {
if error != nil {
print("Error: \(error)")
}
dismiss(animated: true)
}
swift-iba
IBActionを設定
@IBAction func <# FuncName #>(_ sender: AnyObject) {
<# code #>
}
swift-singleton
Singletonパターン
static let shared : <#SingletonClass#> = <#SingletonClass#>()
swift-uiapplicationdelegate
アプリのライフサイクル
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
return true
}
func applicationWillResignActive(_ application: UIApplication) {
}
func applicationDidBecomeActive(_ application: UIApplication) {
}
func applicationWillEnterForeground(_ application: UIApplication) {
}
func applicationDidEnterBackground(_ application: UIApplication) {
}
func applicationWillTerminate(_ application: UIApplication) {
}
swift-elegantmark
マークをつける
////////////////////////////////////////////////////////////////
//MARK:-
//MARK:<#Section#>
//MARK:-
////////////////////////////////////////////////////////////////