20210418のSwiftに関する記事は11件です。

[Swift] CombineでAnyCancellableを省略する

前置き Combine を使うと必ず書くことになるのが AnyCancellable です。 これを毎回書くのが億劫だなと感じたので、書かずに済む方法を考えました。 前提 RxSwiftでの実装を見る RxSwift を使った際にも DisposeBag を書き続けなければならないという問題がありました。 これにはライブラリがあり、それを導入して解決することができました。 上記、中身はたくさんありますが、実質的には このコード だけで機能しています。 fileprivate var disposeBagContext: UInt8 = 0 extension Reactive where Base: AnyObject { func synchronizedBag<T>( _ action: () -> T) -> T { objc_sync_enter(self.base) let result = action() objc_sync_exit(self.base) return result } } public extension Reactive where Base: AnyObject { var disposeBag: DisposeBag { get { return synchronizedBag { if let disposeObject = objc_getAssociatedObject(base, &disposeBagContext) as? DisposeBag { return disposeObject } let disposeObject = DisposeBag() objc_setAssociatedObject(base, &disposeBagContext, disposeObject, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) return disposeObject } } set { synchronizedBag { objc_setAssociatedObject(base, &disposeBagContext, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } } } 馴染みがないとわかりづらいですが、行っていることはとてもシンプルです。 通常はextensionで生やせないメンバ変数を、Objectice-C時代からある黒魔術を使って追加しています。(もっとシンプルな例が見たい方はこちら) 上記のコードを AnyCancellable に適応することで、省略することが可能です。 実装 今回は3つの段階を踏んで紹介しますが、プロジェクトに導入する場合は段階の好み選んでいただければと思います。 1. NSObject を拡張する 多くのクラスで基底部分にあるNSObjectを拡張する形をとります。 private var cancellableContext: UInt8 = 0 extension NSObject { var cancellables: Set<AnyCancellable> { get { if let cancellables = objc_getAssociatedObject(self, &cancellableContext) as? Set<AnyCancellable> { return cancellables } let cancellables = Set<AnyCancellable>() objc_setAssociatedObject(self, &cancellableContext, cancellables, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) return cancellables } set { objc_setAssociatedObject(self, &cancellableContext, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } } 前提で記載したRxSwiftの場合は、rx.disposeBagという「rx」プレフィックスをワンクッション挟む実装の都合上、若干長くなっていましたが、それがない分だけシンプルなコードになりました。 example final class Object: NSObject { // これが不要になる // private var cancellables = Set<AnyCancellable>() func exec() { Just<Int>(0) .sink(receiveCompletion: { _ in // do something }, receiveValue: { _ in // do something }) .store(in: &self.cancellables) // 参照箇所 } } このように、クラス内に AnyCancellable を定義しなくても呼び出せるようになります。 2. Publisher を拡張する 先の「1」で行った実装のままでも十分に機能します。 ただ、コードを書いていくうちに AnyCancellable を登録する部分である 「 .store(in: &self.cancellables) 」も書くのが億劫になります。 その場合は、さらにPublisherを拡張して、その部分を隠蔽化することで対応できます。 extension Publisher { // case 1 func sink<T: NSObject>(_ target: T, receiveCompletion: @escaping ((Subscribers.Completion<Self.Failure>) -> Void), receiveValue: @escaping ((Self.Output) -> Void)) { sink(receiveCompletion: receiveCompletion, receiveValue: receiveValue).store(in: &target.cancellables) } } extension Publisher where Self.Failure == Never { // case 2 func sink<T: NSObject>(_ target: T, receiveValue: @escaping ((Self.Output) -> Void)) { sink(receiveValue: receiveValue).store(in: &target.cancellables) } // case 3 func assign<O: NSObject>(to keyPath: ReferenceWritableKeyPath<O, Self.Output>, on object: O) { assign(to: keyPath, on: object).store(in: &object.cancellables) } } example final class Object: NSObject { // case 1 func exec1() { Just<Int>(0) .sink(self, receiveCompletion: { _ in // do something }, receiveValue: { _ in // do something }) } // case 2 func exec2() { Just<Int>(0) .sink(self, receiveValue: { _ in // do something }) } // case 3 private var number: Int = 0 func exec3() { Just<Int>(10) .assign(to: \.number, on: self) } } AnyCancellable を登録するコードがない分、だいぶ簡潔になりました。 3. Protocol で制限する 「1」「2」で行った実装では、extension でグローバルに拡張しているため、どこからでも呼び出せてしまいます。そこに一定の制約を設けたい場合は Protocol で縛っていきます。 protocol Storable: NSObject { var cancellables: Set<AnyCancellable> { get set } } この作成したプロトコルを、拡張したメソッドにも適応して縛ります。 旧: where T: NSObject ↓↓↓ 新: where T: Storable つまり、以下のようになります。 extension Publisher { func sink<T: Storable>(_ target: T, receiveCompletion: @escaping ((Subscribers.Completion<Self.Failure>) -> Void), receiveValue: @escaping ((Self.Output) -> Void)) { sink(receiveCompletion: receiveCompletion, receiveValue: receiveValue).store(in: &target.cancellables) } } extension Publisher where Self.Failure == Never { func sink<T: Storable>(_ target: T, receiveValue: @escaping ((Self.Output) -> Void)) { sink(receiveValue: receiveValue).store(in: &target.cancellables) } func assign<O: Storable>(to keyPath: ReferenceWritableKeyPath<O, Self.Output>, on object: O) { assign(to: keyPath, on: object).store(in: &object.cancellables) } } example 使用したい NSObject にのみ Storable を適応することで使用することができます。 final class Object: NSObject, Storable { func exec() { Just<Int>(0) .sink(receiveCompletion: { _ in // do something }, receiveValue: { _ in // do something }) } } ライブラリ せっかくなのでライブラリ化しました。 Cocoapods Carthage SPM 3つとも対応しています。 何かあればPRお願いいたします? 終わりに 前置きから長くなってしまいましたが、コードを少しでも簡単に書くためのテクニックくらいに思っていただけると幸いですmm もっとこうした方が良いなどあればコメントいただけると!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Swift - frameとboundsの違い

はじめに 初回の投稿ですが、お手柔に宜しくお願いします〜 ところで、frameとboundsの違いについて結構最近やっとわかった、記録しておこうかなと思います。 frameとは frameはsuperviewが基準にして相対的な座標・大きさを返すプロパティ boundsとは boundsは要素自身が基準にして相対的な座標・大きさを返すプロパティ コードで理解 sample.swift let yellowView: UIView = UIView() yellowView.backgroundColor = UIColor.yellow yellowView.frame = CGRect(x: 50, y: 50, width: 100, height: 100) self.view.addSubview(yellowView) // Yellow ViewのFrameとBoundsをプリントアウト print("Yellow View Frame: \(yellowView.frame)") // Frameをプリントアウト print("Yellow View Bounds: \(yellowView.bounds)") // Boundsをプリントアウト 結果は以下: boundsは自分自身が基準なので、特に設定してない場合x、y両方0です。 画像で理解 boundsを設定した場合はどうなりますか yellowViewにredViewをaddし、さらにyellowViewのboundsのx、yを(-20,-20)にしてみましょう。 sample2.swift let redView: UIView = UIView() redView.backgroundColor = UIColor.red redView.frame = CGRect(x: 0, y: 0, width: 50, height: 50) yellowView.addSubview(redView) print("Red View Frame: \(redView.frame)") print("Red View Bounds: \(redView.bounds)") 結果はこうなってます: また、yellowViewのboundsのx、yを(-20,-20)にしてみましょう。 sample3.swift yellowView.bounds = CGRect(x: -20, y: -20, width: 100, height: 100) 実行してみたら 原因は、yellowViewの原点座標は(-20,-20)になり、redViewの原点座標は(0,0)のままなので、redViewは右下に移動してしまいました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

window.rootViewController入れ替え時のアニメーション

重要な点は、UIView.transitionのanimationsでViewControllerの入れ替えをするのではなく、先に入れ替え処理を書いてからUIView.transitionを呼び出すこと。(animations引数は空のクロージャ。) class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? ... func setRootViewController(_ vc: UIViewController) { guard let window = window else { return } window.rootViewController = vc UIView.transition( with: window, duration: 0.5, options: .transitionFlipFromLeft, animations: {}, completion: { _ in }) } } こんな感じでアニメーションさせられます。 アニメーションの種類は他にもあるので .transitionFlipFromLeft に定義ジャンプして確認してみてください。 ページ送りやフェードのアニメーションもできます。 参考 Swap rootViewController with animation?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【SwiftUI】芝生カレンダー作った

SwiftUIでヒートマップ形式のカレンダー(芝生、草とか言われてるやつ)を作ってみたので簡単な仕組みではありますがメモしておこうと思います。 MMHeatmapライブラリ 折角ライブラリを作ったので学習も兼ねてSwift Package Managerに対応し、公開してみました。 リポジトリ: https://github.com/s-n-1-0/MMHeatmap 導入方法とかはリポジトリのREADME.mdにあるので割愛します。 View構造 最下層から順に説明します。 1週間用VStack まず1週間分(7つのセル)を次のような感じでVStackで縦に並べます。 VStack(spacing:2){ ForEach(0..<7){ i in RoundedRectangle(cornerRadius: 2).frame(width: 10,height: 10).modifier(CellColorModifier(isRange: (i >= start && i <= end ) , value: values[i], maxValue: maxValue,minColor: style.minCellColor,baseColor: style.baseCellColor)) } } MMHeatmapColumnView.swift プレビューしにくいのでこの階層ではDate型は扱わず、上のViewから与えられた表示範囲と値に従ってセルの色を決定します。 ※CellColorModifierについては後述します。 1ヵ月用HStack 次にHStackで1週間用VStackを週数分並べます。 1ヶ月分の週数の特定は、翌月の0日(つまりその月の最終日)を設定したDateComponentsをDate型にした後、Calendarで週数を求めることができます。 var comp = DateComponents() comp.year = 2021 comp.month = MM + 1 comp.day = 0 let date = calendar.date(from: comp)! let weeks = calendar.component(.weekOfMonth, from: date) 数ヶ月用HStack 最後に1ヶ月用HStackを指定範囲の月数分並べます。 セルの色決定 データとなる数値配列の中で最大値の色をbaseColor、最小値0の色をminColorとしてbaseColorとminColorの中間色を求めます。 尚、データの値をnilとした場合はセルの色を透明(Color.clear)に設定しています。 次のモディファイアの saturation = (saturation - secondSaturation) * pct + secondSaturation brightness = (brightness - secondBrightness) * pct + secondBrightness の部分で中間色(彩度、明度)を決定しています。 (このコードでは色相の中間色は求めてませんでした) fileprivate struct CellColorModifier:ViewModifier { init(isRange:Bool,value:Int?,maxValue:Int,minColor:UIColor,baseColor:UIColor) { self.isRange = isRange if let v = value{ let pct:CGFloat = CGFloat(v) / CGFloat(maxValue) var secondHue:CGFloat = 0 var secondSaturation:CGFloat = 0 var secondBrightness:CGFloat = 0 var secondAlpa:CGFloat = 0 minColor.getHue(&secondHue, saturation: &secondSaturation, brightness: &secondBrightness, alpha: &secondAlpa) var hue:CGFloat = 0 var saturation:CGFloat = 0 var brightness:CGFloat = 0 var alpha:CGFloat = 0 baseColor.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) saturation = (saturation - secondSaturation) * pct + secondSaturation brightness = (brightness - secondBrightness) * pct + secondBrightness self.rangeColor = Color(UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: alpha)) }else{ self.rangeColor = Color(UIColor.clear) } } let isRange:Bool let rangeColor:Color func body(content: Content) -> some View { Group{ if(isRange){ content.foregroundColor(rangeColor) }else{ content.foregroundColor(Color.clear) } } } } Swift Package 次の記事を参考にしました。jjjkkkjjj様に感謝します。 https://qiita.com/jjjkkkjjj/items/727517263292ae7a3a87 ちなみにSwiftUIのプレビューをする際に大量のエラーが出る場合は、プレビューするファイル以外を閉じて仮想端末をMacからiPhoneやiPadにすると直りました。 終わりに 以上で基本的な芝生カレンダーを作ることができました。 改善するやる気が起きたらGeometryReaderを使ってMMHeatmapを画面サイズに応じたカレンダーに改良したいと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

YoutubeAPIを使用してJSON形式の情報をXcodeで扱う方法

YoutubeAPIを使用してみよう YoutubeAPIを使用してJson形式の情報を扱えるようにするには以下の手順で作業を行う 1:YoutubeAPIを使用でできるよにプロジェクトの作成、とAPIキーを作成するconsole.cloud.google.com 2:Xcodeで対象のJSON形式に対応したmodelを作成する 3:APIへリクエストを投げる 4:レスポンス情報をmodel型のオブジェクトへデコードする まずは、APIキーの作成をするためにhttps://developers.google.com/youtube/v3/getting-started?hl=ja へアクセスして 作業を始める前に という項目の手順よりGoogleアカウントが無ければ作成 https://console.cloud.google.com/apis/credentials?hl=ja&project=youtubeapp-311106&folder=&organizationId= へアクセス 私の画面だとハンバーガーメニューの右側のGoogole Cloud Platformの右のYoutubeAppのタブから作成できる。 その後 +認証情報の作成 というタブをクリックしてAPIキーを発行する このAPIキーはYoutubeAPIへリクエストを投げる時にクエリパラメータとして渡す値で 文字通り鍵(認証)に役割を果たす。 では試しに。 https://www.googleapis.com/youtube/v3/search?q=任意の文字&key=取得したキー&part=snippet というURLへアクセスすると JSONファイルがレスポンスとして返ってくる。 要はこれをXcodeで扱えるようにする事ができればいい。 そのために alamofireというライブラリを使用する。 このライブラリはhttp通信のためのライブラリ cocoapodでライブラリをプロジェクトにインストールする。 テストコード デフォルトのストーリーボードに紐付けられているViewControllerでテストコードを書いてみる import UIkit import Alamofire class ViewController: UIViewController{ override func viewDidLoad() { super.viewDidLoad() //リクエスト URL let urlString = "https://www.googleapis.com/youtube/v3/search?q=検索したいワード&key=APIキー&part=snippet"      //リクエストを作成 let request = AF.request(urlString) //リクエストをyoutubeApiに投げてレスポンス情報を取得 request.responseJSON{(response) in do{ //Json情報を取得して対象のモデルオブジェクトへ変換 guard let data = response.data else { return } let decode = JSONDecoder() let video = try decode.decode(Video.self, from: data) print("video:", video.items.count) } catch { print("変換に失敗しました\(error)") } print("response", response) } } } modelはこのように import Foundation class Video: Decodable { let kind: String let items: [Item] } class Item: Decodable { let snippet: Snippet } class Snippet: Decodable { let publishedAt: String let channelId: String let title: String let description: String let thumbnails: Thumbnail } class Thumbnail: Decodable { let medium: ThumbnailInfo let high: ThumbnailInfo } class ThumbnailInfo: Decodable { let url: String let width: Int? let height: Int? } Json形式の情報をデコードするには変数名を一致させる必要があり、配列に対しては上記のように クラスを作成して入れる情報をクラスで扱えるようにする。 例えば、レスポンスとして返ってきたjson情報には Itemという配列がある。この配列の中には更にkindやidなどの変数や、snippetなどの配列がある この配列の中に入っている情報一つの型(クラス)で扱う。 結果として一つのvideoクラスのインスタンスが作成され、 その中のItemという変数名の配列にjson情報のItem配列の各要素が格納される ちなみに、json情報の全ての要素を格納する変数を用意しなくても取り出したい情報だけ用意しておけばいい。 逆に、json情報にない情報を格納する変数がモデルオブジェクトで宣言されているとエラーとなる。 あと生成したオブジェクトの情報を使って、imageURLから画像をダウンロードしたり、文字列を labelに割り当てたり似たり焼いたりお好みに
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Swift]虹色のボーダーアニメーションを作成する

はじめに 今回は使い所は限られるとは思いますが、虹色ボーダーラインのアニメーションを実装します。 こんな感じ↓ Swiftで虹色のボーダーラインのアニメーション pic.twitter.com/tzrhSnnebS— M (@p_x9) April 18, 2021 本編 1. 虹色のCGColor配列を作成 虹色の配列を作成します。色相、彩度、明度のうち、色相を少しずつ変化させればなだらかな虹色が作成できます。 後々のためここではUIColorではなくCGColorの配列としておきます。 var rainbow: [CGColor] { let increment: CGFloat = 0.02 return [CGFloat](stride(from: 0.0, to: 1.0, by: increment)).map{ hue in UIColor(hue: hue, saturation: 1.0, brightness: 1.0, alpha: 1.0).cgColor } } 2. 虹色のグラデーションを作成する まず虹色のグラデーションのレイヤを作成します。 グラデーションのレイヤを作成するにはCAGradientLayerを使います。 ここでCAGradientLayerのcolorsプロパティに先ほど作成した虹色の配列を適用することで、虹色グラデーションのレイヤができます。 let gradientLayer = CAGradientLayer() gradientLayer.colors = rainbow 今回はラベルに虹色のボーダーラインアニメーションを追加しますが、そのフレームに対し少しマージンを取ります。 gradientLayer.frame = CGRect(x: -4, y: -4, width: label.frame.width+8, height: label.frame.height+8) グラデーションの始まりと終わりのポイントを指定します。 今回は左上から右下にかけてのグラデーションにしたいので、以下のように設定しました。この時、x,yともに0から1の範囲で指定する必要があるので注意が必要です。 gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0) gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0) こんな感じです。 3. アニメーションを行うレイヤの作成 CAShapeLayerを使用します。 まずボーダラインのpathを指定します。 let shapeLayer = CAShapeLayer() let path = UIBezierPath(rect: CGRect(x: 0, y: 0, width: label.frame.width+8, height: label.frame.height+8)) shapeLayer.path = path.cgPath またfillColorは透明にしておきます。線の太さも決めておきます。 shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.lineWidth = 8.0 4. maskの設定 グラデーションのレイヤにmaskとして3で作成したアニメーションを行うレイヤを設定します。 四角いグラデーションのレイヤから、maskに設定したレイヤによってくり抜くといったイメージです。 5. レイヤをviewに適用 今回はlabelに対して設定します。 label.layer.addSublayer(shapeLayer) アニメーションの作成 CABasicAnimationを使用します。CAShapeLayerのstrokeEndプロパティを0から1までアニメーションさせたいので以下のように実装します。 また、アニメーションの時間も設定しておきます。 let animation = CABasicAnimation(keyPath: #keyPath(CAShapeLayer.strokeEnd)) animation.fromValue = 0.0 animation.toValue = 1.0 animation.duration = 3.0 ここではアニメーションを無限にループさせたいので以下のように設定しておきます。 animation.repeatDuration = .infinity 6. animationのレイヤへの適用 以下を実行するとアニメーションが始まります。 self.shapeLayer.add(animation, forKey: #keyPath(CAShapeLayer.strokeEnd)) 7.完成 これで完成です。 動作原理 まず、CAGradientLayerでグラデーションのレイヤを作ります。 maskプロパティに別レイヤを設定すると、設定したレイヤの形にくり抜くことができます。 そこで、CAShapeLayerで外枠となる部分のレイヤを作成し、maskとして適用することでグラデーションの外枠ができます。 CAShapeLayerのstrokeStartとstrokeEndが外枠の始まりと終わりの部分を表すのでこと値をアニメーションで徐々に変化させることで、外枠がアニメーションし目的を達成することができます。 おわりに 読んでいただいてありがとうございます。初めて二日連続で記事を書きました。参考になれれば嬉しいです。 ご指摘ご質問等ございましたら、コメントまたはDMまでお願いします。 本記事での内容はこちらのリポジトリよりダウンロードできます。 簡単に実行できるので良かったら試してみてください 追記 2021/04/19 この記事に関連した記事を書きました。 合わせて読んでいただけると嬉しいです https://qiita.com/p_x9/items/5fbe76748ee060f18daa
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Swift5] cellをtapしたときのhighlightを無効にする方法

はじめに tableView全てのcell, または,特定のcellをtapしたときのhighlightを無効にする方法をメモしました. tableView全体のcellに適用する場合 tableView.allowsSelection = false 上記を記述することで,didSelectRowAt#が動作しなくなるので,tapしてもアニメーションが発生しなくなります. ただし,cellの上にUIButtonを配置した場合,そのbuttonはdidSelectRowAt#と関係ないので動作します. UITableViewが編集モードの時にも無効にしたい場合,上の記述に加えて以下を記述する. tableView.allowsSelectionDuringEditing = false 特定のcellに適用する場合 cell.selectionStyle = .none 参考 How can I disable the UITableView selection?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SwiftとFirestoreで部分一致させる

はじめに Swiftを使ってCloud FirestoreのデータをLike検索したので、メモのために残しておきます。 やり方 こんな感じでoder、start、endを使えばいけます! 「searchText」に部分一致する対象を検索しています。 swiftでは"\u{f8ff}"の様に中かっこで囲むのが肝みたいです。 sample Firestore.firestore().collection("users").order(by: "name").start(at: [searchText]).end(at: [searchText + "\u{f8ff}"]).getDocuments(){ (querySnapshot, error) in if let querySnapshot = querySnapshot { print("成功") } else if let error = error { print("失敗") } } 参考文献 Cloud FirestoreでLike検索する方法
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

swift - アクセス修飾子

はじめに swiftのアクセス修飾子の種類とアクセスレベルについてメモしました. アクセス修飾子 上から下にアクセスレベルが下がる. private : {}内のみ. fileprivate : 属するファイル内. internal : 属するプロジェクト内.デフォルトなので,アクセス修飾子を何もつけずに定義した場合,アクセスレベルはinternal. public : プロジェクト間(上書き不可能). open : プロジェクト間(上書き可能). 基本的に,アプリ開発では,1 ~ 3 を利用. Frameworkなどの開発では,4, 5 を利用. アクセス修飾子をきちんと設定することで,他の開発者に誤って書き換えられたりすることを防ぐことができ,安全性が向上する.
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Xcode]Xcodeのエディタ設定-表示編

はじめに 久しぶりにXcodeのエディタの設定を見直す機会があったので、それぞれの機能や設定の仕方をまとめることにしました。 今回はそのうち表示に関連するものです。 本記事においては、以下の環境に基づいて記述しています。 Xcode:Version 12.4 (12D4e) 本編 以下の項目は全てXcode->Preferences->TextEditingから設定できます。 Displayの部分を上から順に概要を示します。 Show Line numbers その名の通りエディタ画面の左側の行番号を表示するかしないかの設定です。 普通に表示してた方がいいと思います。 Off On Code folding ribbon コードをブロックごとに折り畳むことのできる機能です。デフォルトではオフになってたような気がします。 VSCodeとかではよく使ってたので見つけた瞬間すぐオンにしました。割と便利です。 ↓こんな感じ Mark separators オンにすると//MARK: -コメントを記述した部分に境界線を表示してくれます。 Off On Code coverage iteration counts これはUnitTestに関連する機能です。オンにするとtestを実行後に、関数の呼び出し回数を表示してくれます。 Off On Page guide at column 1行に何文字までにするかを設定できます。これをオンにした時、設定した文字数を超える部分にガイドが表示されます。 1行何文字ルールとかある人とかには便利だとは思いますが自分は使ってません。 Off On Highlight instances of selected symbol オンにすると関数や変数などをクリックした時に同じシンボルをハイライトしてくれるようになります。また、クリック後にどれぐらいの秒数後にハイライトされるかも設定できるようになっています。 他人のコード読む時とかないと困るレベルくらいに使ってます。すぐにオンにすべき。 Off On Documentation Comments Fade doc comment delimitters オンにするとドキュメントコメントの///を目立たないようにしてくれます。 Off On Fade doc comment markup delimitters オンにするとドキュメントコメントの-を目立たないようにしてくれます。 Off On Line Wrapping Wrap Line to editor width オンにすると1行が画面に収まらない時に、折り返して表示してくれるようになります。また、折り返した行を本来の行に対してどれだけインデントするかの設定ができます。 ↓こんな感じの機能です。 画面幅が十分 画面は幅が不十分 Editor over scroll プログラムファイルの一番最後の行にいった時に、その下にどれくらいのスペースを表示するかの設定です。 None Medium Large 番外編 ・スペルミスをしたときに赤い下線で示してくれる機能 Edit->Format->Spelling and Grammar->Check Spelling While Typeで設定できます。 こんな感じ ・タブやスペース、改行の可視化 Editor->invisibles で設定できます。 こんな感じ おわりに 読んでいただいてありがとうございます。ご指摘ご質問等ございましたらコメントかDMまでください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

デリゲートとプロトコル

始めに  この記事を書く1週間ほど前から僕はSwiftの勉強を始めたわけですが、学ぶ中で出てきたデリゲートとプロトコルについて簡単に説明します。 デリゲートとプロトコルの意味  デリゲートは英語で人に任せるという意味を持っている、プロトコルを用いたデザインパターンのことです。ちなみにプロトコルとはメソッドの書いてある仕様書のことです。  デリゲートを用いると、他のクラスで定義されたメソッドなどを、自分のクラスで簡単に使用することができます。すなわちデリゲートという操作を行って、プロトコルに書いてある自分の使いたいメソッドを利用するということです。お分かりいただけたでしょうか? 1.プロトコル 依頼する処理をメソッドとして定義します。 2.処理を依頼するクラス デリゲートメソッドを使用し、プロトコルを適用したクラスから処理の流れを記述します。 3.処理を依頼されるクラス プロトコルで定義されたデリゲートメソッドを実装します。 デリゲートを使う理由 イベント発生を検知する処理と検知した後にする処理を分けることで、コードはわかりやすくなり、処理を任せる側は実際に処理をするクラスやどんな処理をするのかを考えなくていいためだと僕は理解しました。 終わりに コードの書き方などは自分自身で0からデリゲートを用いて、コードを書けるようになったときに説明しようと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む