- 投稿日:2020-07-10T17:16:53+09:00
Swiftのextensionをとは? 初心者が簡単にまとめてみました
はじめに
swiftの勉強を始めてみると、今まで使ったことのないコードや機能に出会うことが多いです。今回はその中の1つextensionの紹介をします。
修正点などありましたら、指摘していただくと嬉しいです。extensionとは
extension 「拡張」という言葉の通り、クラス(class)や構造体(struct)
プロトコル(protocol)などに、関数(メソッド)や変数(プロパティ)を追加することができる機能です。それなら普通にクラスや構造体にコードを追加すればいいじゃないかと思いますが(自分も思いましたが)、それ以上の機能や便利な面もあるので、使いこなしていきましょう。
まずは基本的なことから行きます。
具体的な書き方
extension 拡張する型の名前 { //追加するメソッドやプロパティを記述する }書き方は簡単です。
拡張したいクラスや構造体の名前と、追加のメソッドやプロパティを記述します。
自分で定義したクラスなどを入れて、新しいメソッドを追加することが簡単にできます。extensionの記述例
最初に言ったように、自分で作ったクラスや構造体ならその部分にコードを直接記述すれば、メッソドとプロパティは追加できます。しかし、自分で定義していないもの(元々存在しているもの)に関してはその操作ができません。
そこでextensionの1つ目の素晴らしい点が、自分が作ったものでなくてもSwiftに元々あるクラスなどにも機能を拡張することができるという点です。例えばとても身近なIntやStringといったクラスに新たなメソッドを定義することができます。
extension Int { func niceNumber() { print("Wow! Nice number!") } }このようなおかしなメソッドも追加することができ、実際に使うことができます。
let number = 5 number.niceNumber() //=> Wow! Nice Number!これはextensionを使わないとできないことだと思います。
ちなみにIntやStringはオープンソースになっていて、GitHub上で誰でも中身を見ることができます。またUITextFieldなどはオープンソースではないですが、もちろん拡張することはできます。
プロトコルの拡張
素晴らしい点2つ目は、プロトコルの拡張です。
プロコトルというのは、メソッドやプロパティの中身を定義することができませんでした。そのため、それぞれのプロトコルを適用したクラスなどで中身を書いていく必要がありました。//プロトコルの定義 protocol Canfly { func fly() } //プロトコルを適用しているクラス class Eagle: Canfly { func fly() { print("The eagle can fly")//1つ1つメソッドの処理を書く } } //プロトコルを適用しているクラス class Airplane: Canfly { func fly() { print("The plane can fly")//1つ1つメソッドの処理を書く } }ところがextensionを使うことで、その中身を事前に定義することができるのです。
書き方は今までと一緒です。上記の例をそのまま使うと
extension Canfly { func fly() { print("The object can fly") } }こうすることによって、Canflyプロトコルのflyメソッドの中身を定義することができました。
すると
class Eagle: Canfly { //fly()メソッドの定義をしなくても大丈夫 } class Airplane: Canfly { //fly()メソッドの定義をしなくても大丈夫 } let myEagle = Eagle() let myPlane = Airplane() myEagle.fly() //=> The object can fly myPlane.fly() //=> The object can flyこのようにして、コードの量や負担を減らすことができました。
今まで既存のプロトコルを適用する際に、全部のメッソドを呼び出したり定義していないのに大丈夫なのかなと思っていた方も多いと思いますが、それらは全てextensionをつかってappleさんが事前に定義してくれているから大丈夫なんです。
コードを見やすくする
extension最後の活用方法は、extensionを使うことでコードがすっきりして見やすくなります。
具体的には以下のように、1つのクラスにたくさんのプロトコルを適用している場合、どのメソッドがどのプロトコルに対応している操作なのか、コードが膨大になり分わかりにくくなります。
import UIKit // プロトコルを2つも適用している、、、 class WeatherViewController: UIViewController, UITextFieldDelegate, UINavigationControllerDelegate { @IBOutlet weak var conditionImageView: UIImageView! @IBOutlet weak var temperatureLabel: UILabel! @IBOutlet weak var cityLabel: UILabel! @IBOutlet weak var searchTextField: UITextField! override func viewDidLoad() { super.viewDidLoad() ....... } //どのメソッドが func textFieldShouldReturn(_ textField: UITextField) -> Bool { ..... } //どのプロパティに対応しているのか func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { ...... } //多すぎてわからなくなる func textFieldDidEndEditing(_ textField: UITextField) { ....... } //なんの操作をしているだろう func navigationController() { ........ } }そこでextensionを使うことで、プロトコルごとにコードを記述する場所を分けるのです。
具体的には以下のようにすることができます。
import UIKit class WeatherViewController: UIViewController, UITextFieldDelegate, UINavigationControllerDelegate { @IBOutlet weak var conditionImageView: UIImageView! @IBOutlet weak var temperatureLabel: UILabel! @IBOutlet weak var cityLabel: UILabel! @IBOutlet weak var searchTextField: UITextField! override func viewDidLoad() { super.viewDidLoad() ....... } } //プロトコルごとに分ける---------------------------------------------------------------------------------- extension WeatherViewController: UITextFieldDelegate { func textFieldShouldReturn(_ textField: UITextField) -> Bool { ..... } func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { ...... } func textFieldDidEndEditing(_ textField: UITextField) { ....... } } //プロトコルごとに分ける---------------------------------------------------------------------------------- extension WeatherViewController: UINavigationControllerDelegate { func navigationController(........) { ........ } }これでプロトコルとメソッドの対応関係もしっかり分かり、コードもすっきりしました。
以上でextensionの使い方等の解説を終わります。これはプログラミング初心者が簡単にまとめたものなので、修正などがありましたらご指摘お願いします。
- 投稿日:2020-07-10T17:16:53+09:00
Swiftのextensionをわかりやすく解説
extensionとは
extension 「拡張」という言葉の通り、クラス(class)や構造体(struct)
プロトコル(protocol)などに、関数(メソッド)や変数(プロパティ)を追加することができる機能です。それなら普通にクラスや構造体にコードを追加すればいいじゃないかと思いますが(自分も思いましたが)、それ以上の機能や便利な面もあるので、使いこなしていきましょう。
まずは基本的なことから行きます。
具体的な書き方
extension 拡張する型の名前 { //追加するメソッドやプロパティを記述する }書き方は簡単です。
拡張したいクラスや構造体の名前と、追加のメソッドやプロパティを記述します。
自分で定義したクラスなどを入れて、新しいメソッドを追加することが簡単にできます。extensionの記述例
最初に言ったように、自分で作ったクラスや構造体ならその部分にコードを直接記述すれば、メッソドとプロパティは追加できます。しかし、自分で定義していないもの(元々存在しているもの)に関してはその操作ができません。
そこでextensionの1つ目の素晴らしい点が、自分が作ったものでなくてもSwiftに元々あるクラスなどにも機能を拡張することができるという点です。例えばとても身近なIntやStringといったクラスに新たなメソッドを定義することができます。
extension Int { func niceNumber() { print("Wow! Nice number!") } }このようなおかしなメソッドも追加することができ、実際に使うことができます。
let number = 5 number.niceNumber() //=> Wow! Nice Number!これはextensionを使わないとできないことだと思います。
ちなみにIntやStringはオープンソースになっていて、GitHub上で誰でも中身を見ることができます。またUITextFieldなどはオープンソースではないですが、もちろん拡張することはできます。
プロトコルの拡張
素晴らしい点2つ目は、プロトコルの拡張です。
プロコトルというのは、メソッドやプロパティの中身を定義することができませんでした。そのため、それぞれのプロトコルを適用したクラスなどで中身を書いていく必要がありました。//プロトコルの定義 protocol Canfly { func fly() } //プロトコルを適用しているクラス class Eagle: Canfly { func fly() { print("The eagle can fly")//1つ1つメソッドの処理を書く } } //プロトコルを適用しているクラス class Airplane: Canfly { func fly() { print("The plane can fly")//1つ1つメソッドの処理を書く } }ところがextensionを使うことで、その中身を事前に定義することができるのです。
書き方は今までと一緒です。上記の例をそのまま使うと
extension Canfly { func fly() { print("The object can fly") } }こうすることによって、Canflyプロトコルのflyメソッドの中身を定義することができました。
すると
class Eagle: Canfly { //fly()メソッドの定義をしなくても大丈夫 } class Airplane: Canfly { //fly()メソッドの定義をしなくても大丈夫 } let myEagle = Eagle() let myPlane = Airplane() myEagle.fly() //=> The object can fly myPlane.fly() //=> The object can flyこのようにして、コードの量や負担を減らすことができました。
今まで既存のプロトコルを適用する際に、全部のメッソドを呼び出したり定義していないのに大丈夫なのかなと思っていた方も多いと思いますが、それらは全てextensionをつかってappleさんが事前に定義してくれているから大丈夫なんです。
コードを見やすくする
extension最後の活用方法は、extensionを使うことでコードがすっきりして見やすくなります。
具体的には以下のように、1つのクラスにたくさんのプロトコルを適用している場合、どのメソッドがどのプロトコルに対応している操作なのか、コードが膨大になり分わかりにくくなります。
import UIKit // プロトコルを2つも適用している、、、 class WeatherViewController: UIViewController, UITextFieldDelegate, UINavigationControllerDelegate { @IBOutlet weak var conditionImageView: UIImageView! @IBOutlet weak var temperatureLabel: UILabel! @IBOutlet weak var cityLabel: UILabel! @IBOutlet weak var searchTextField: UITextField! override func viewDidLoad() { super.viewDidLoad() ....... } //どのメソッドが func textFieldShouldReturn(_ textField: UITextField) -> Bool { ..... } //どのプロパティに対応しているのか func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { ...... } //多すぎてわからなくなる func textFieldDidEndEditing(_ textField: UITextField) { ....... } //なんの操作をしているだろう func navigationController() { ........ } }そこでextensionを使うことで、プロトコルごとにコードを記述する場所を分けるのです。
具体的には以下のようにすることができます。
import UIKit class WeatherViewController: UIViewController, UITextFieldDelegate, UINavigationControllerDelegate { @IBOutlet weak var conditionImageView: UIImageView! @IBOutlet weak var temperatureLabel: UILabel! @IBOutlet weak var cityLabel: UILabel! @IBOutlet weak var searchTextField: UITextField! override func viewDidLoad() { super.viewDidLoad() ....... } } //プロトコルごとに分ける---------------------------------------------------------------------------------- extension WeatherViewController: UITextFieldDelegate { func textFieldShouldReturn(_ textField: UITextField) -> Bool { ..... } func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { ...... } func textFieldDidEndEditing(_ textField: UITextField) { ....... } } //プロトコルごとに分ける---------------------------------------------------------------------------------- extension WeatherViewController: UINavigationControllerDelegate { func navigationController(........) { ........ } }これでプロトコルとメソッドの対応関係もしっかり分かり、コードもすっきりしました。
以上でextensionの使い方等の解説を終わります。これはプログラミング初心者が簡単にまとめたものなので、修正などがありましたらご指摘お願いします。
- 投稿日:2020-07-10T17:16:53+09:00
Swiftのextensionを簡単にまとめました
extensionとは
extension 「拡張」という言葉の通り、クラス(class)や構造体(struct)
プロトコル(protocol)などに、関数(メソッド)や変数(プロパティ)を追加することができる機能です。それなら普通にクラスや構造体にコードを追加すればいいじゃないかと思いますが(自分も思いましたが)、それ以上の機能や便利な面もあるので、使いこなしていきましょう。
まずは基本的なことから行きます。
具体的な書き方
extension 拡張する型の名前 { //追加するメソッドやプロパティを記述する }書き方は簡単です。
拡張したいクラスや構造体の名前と、追加のメソッドやプロパティを記述します。
自分で定義したクラスなどを入れて、新しいメソッドを追加することが簡単にできます。extensionの記述例
最初に言ったように、自分で作ったクラスや構造体ならその部分にコードを直接記述すれば、メッソドとプロパティは追加できます。しかし、自分で定義していないもの(元々存在しているもの)に関してはその操作ができません。
そこでextensionの1つ目の素晴らしい点が、自分が作ったものでなくてもSwiftに元々あるクラスなどにも機能を拡張することができるという点です。例えばとても身近なIntやStringといったクラスに新たなメソッドを定義することができます。
extension Int { func niceNumber() { print("Wow! Nice number!") } }このようなおかしなメソッドも追加することができ、実際に使うことができます。
let number = 5 number.niceNumber() //=> Wow! Nice Number!これはextensionを使わないとできないことだと思います。
ちなみにIntやStringはオープンソースになっていて、GitHub上で誰でも中身を見ることができます。またUITextFieldなどはオープンソースではないですが、もちろん拡張することはできます。
プロトコルの拡張
素晴らしい点2つ目は、プロトコルの拡張です。
プロコトルというのは、メソッドやプロパティの中身を定義することができませんでした。そのため、それぞれのプロトコルを適用したクラスなどで中身を書いていく必要がありました。//プロトコルの定義 protocol Canfly { func fly() } //プロトコルを適用しているクラス class Eagle: Canfly { func fly() { print("The eagle can fly")//1つ1つメソッドの処理を書く } } //プロトコルを適用しているクラス class Airplane: Canfly { func fly() { print("The plane can fly")//1つ1つメソッドの処理を書く } }ところがextensionを使うことで、その中身を事前に定義することができるのです。
書き方は今までと一緒です。上記の例をそのまま使うと
extension Canfly { func fly() { print("The object can fly") } }こうすることによって、Canflyプロトコルのflyメソッドの中身を定義することができました。
すると
class Eagle: Canfly { //fly()メソッドの定義をしなくても大丈夫 } class Airplane: Canfly { //fly()メソッドの定義をしなくても大丈夫 } let myEagle = Eagle() let myPlane = Airplane() myEagle.fly() //=> The object can fly myPlane.fly() //=> The object can flyこのようにして、コードの量や負担を減らすことができました。
今まで既存のプロトコルを適用する際に、全部のメッソドを呼び出したり定義していないのに大丈夫なのかなと思っていた方も多いと思いますが、それらは全てextensionをつかってappleさんが事前に定義してくれているから大丈夫なんです。
コードを見やすくする
extension最後の活用方法は、extensionを使うことでコードがすっきりして見やすくなります。
具体的には以下のように、1つのクラスにたくさんのプロトコルを適用している場合、どのメソッドがどのプロトコルに対応している操作なのか、コードが膨大になり分わかりにくくなります。
import UIKit // プロトコルを2つも適用している、、、 class WeatherViewController: UIViewController, UITextFieldDelegate, UINavigationControllerDelegate { @IBOutlet weak var conditionImageView: UIImageView! @IBOutlet weak var temperatureLabel: UILabel! @IBOutlet weak var cityLabel: UILabel! @IBOutlet weak var searchTextField: UITextField! override func viewDidLoad() { super.viewDidLoad() ....... } //どのメソッドが func textFieldShouldReturn(_ textField: UITextField) -> Bool { ..... } //どのプロパティに対応しているのか func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { ...... } //多すぎてわからなくなる func textFieldDidEndEditing(_ textField: UITextField) { ....... } //なんの操作をしているだろう func navigationController() { ........ } }そこでextensionを使うことで、プロトコルごとにコードを記述する場所を分けるのです。
具体的には以下のようにすることができます。
import UIKit class WeatherViewController: UIViewController, UITextFieldDelegate, UINavigationControllerDelegate { @IBOutlet weak var conditionImageView: UIImageView! @IBOutlet weak var temperatureLabel: UILabel! @IBOutlet weak var cityLabel: UILabel! @IBOutlet weak var searchTextField: UITextField! override func viewDidLoad() { super.viewDidLoad() ....... } } //プロトコルごとに分ける---------------------------------------------------------------------------------- extension WeatherViewController: UITextFieldDelegate { func textFieldShouldReturn(_ textField: UITextField) -> Bool { ..... } func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { ...... } func textFieldDidEndEditing(_ textField: UITextField) { ....... } } //プロトコルごとに分ける---------------------------------------------------------------------------------- extension WeatherViewController: UINavigationControllerDelegate { func navigationController(........) { ........ } }これでプロトコルとメソッドの対応関係もしっかり分かり、コードもすっきりしました。
以上でextensionの使い方等の解説を終わります。これはプログラミング初心者が簡単にまとめたものなので、修正などがありましたらご指摘お願いします。
- 投稿日:2020-07-10T16:51:00+09:00
xibファイルを読み込んでNSTableViewを作成する
概要
- 以下のような簡単なテーブルを作っていきます。
- (基本的な所は省略して、忘備録的に書いていますので細かい所はサンプル参照ということでご容赦を…。)
- また以下のテーブルのセルは
xib
ファイルから読み込んだものを使用しています。GitHub
参考
- Macアプリ初心者:NSTableView でカスタムした一覧を作ってみる - Qiita
- 別Xibにしない場合について書かれています。
テキストだけの単純なテーブル
Storyboard側
TableView
のdelegate
とdatasource
をコントローラにバインディング
CellView
のIdentifier
をMyView
に設定しておくコード
- 表示するデータを用意
var messages = ["sample message 1", "sample message 2", "sample message 3"]
- テーブル表示に必要なメソッド2種を実装する
NSUserInterfaceItemIdentifier(rawValue: "MyView")
により、
Storyboardで指定したMyView
を読み込んでコード内で使用することができるextension StandardTableViewController : NSTableViewDelegate, NSTableViewDataSource { func numberOfRows(in tableView: NSTableView) -> Int { return messages.count } func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { guard let cellView = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "MyView"), owner: self) as? NSTableCellView else { return NSTableCellView() } cellView.textField?.stringValue = messages[row] return cellView } }カスタムXibを用いたテーブルビュー
概要
- 別のXibファイルをセルに使用したい場合の実装です。
実装
カスタムセルのクラス(CustomTableCellView.swift)
- カスタムセルのため、
NSTableCellView
のサブクラスを作成します。- テーブルの
delegate
設定等は前述と同じなので割愛しています。protocol CustomTableCellViewDelegate: class { func selectionButtonClicked(for cell: NSTableCellView) } class CustomTableCellView: NSTableCellView { @IBOutlet weak var cellImageView: NSImageView! @IBOutlet weak var titleLabel: NSTextField! @IBOutlet weak var descriptionLabel: NSTextField! @IBOutlet weak var selectionButton: NSButton! var delegate: CustomTableCellViewDelegate? override func draw(_ dirtyRect: NSRect) { super.draw(dirtyRect) } func configure(for cellData: CustomCellData) { self.cellImageView.image = cellData.image self.titleLabel.stringValue = cellData.title self.descriptionLabel.stringValue = cellData.descriptionText } // MARK: - Actions @IBAction func selectionButtonClicked(_ sender: NSButton) { // セルのボタンのアクションをコントローラに返すため、delegateを使用する delegate?.selectionButtonClicked(for: self) } }カスタムセルのxib(CustomTableCellView.xib)
- カスタムセルのUI側です。
- クラスを作成する
CustomTableCellView
に指定します- セルの
identifier
等の設定は不要です。
CustomTableViewController
のtableView.register
で設定するからですね定数定義ファイル(Konst.swift)
- identifier等に使用する定数をファイルで定義しておきます
struct Konst { struct SegueIdentifier { static let showStandardTableViewController = "ShowStandardTableViewController" static let showCustomTableViewController = "ShowCustomTableViewController" } struct CellIdentifier { static let customTableCellView = "CustomTableCellView" } struct NibName { static let customTableCellView = "CustomTableCellView" } }ビューコントローラ(CustomTableViewController.swift)
- 別のxibファイルから読み込むため、
viewDidLoad
でtableView
にxib
の登録を行う
- iOSでカスタムセルを使う際と同じですね。
// 別のXibファイルから読み込む場合は登録が必要 tableView.register(NSNib(nibNamed: Konst.NibName.customTableCellView, bundle: nil), forIdentifier: NSUserInterfaceItemIdentifier(rawValue: Konst.CellIdentifier.customTableCellView)) tableView.reloadData()
- 同様にテーブル表示に必要なプロトコルメソッドを実装
cell
のUI設定はcell側 = Model側に任せてしまう。教本でよく見る実装です。
cellView.configure(for: cellDataList[row])
// MARK: - NSTableViewDelegate, NSTableViewDataSource Methods extension CustomTableViewController: NSTableViewDelegate, NSTableViewDataSource { func numberOfRows(in tableView: NSTableView) -> Int { return cellDataList.count } func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { guard let cellView = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: Konst.CellIdentifier.customTableCellView), owner: self) as? CustomTableCellView else { return NSTableCellView() } cellView.delegate = self cellView.configure(for: cellDataList[row]) return cellView } }
- カスタムセル内のボタンのアクションを受け取るため、delegateパターンを使用しています。
// CustomTableCellViewDelegate Methods extension CustomTableViewController: CustomTableCellViewDelegate { func selectionButtonClicked(for cell: NSTableCellView) { let rowIndex = tableView.row(for: cell) // 選択されたcellViewのIndexを取得できる print("selected row: [\(rowIndex)]") } }
- 投稿日:2020-07-10T14:59:42+09:00
Swiftで大文字か小文字か判定する
Characterの
isUppercase
プロパティは大文字かどうかを、isLowercase
は小文字かどうかを判定してくれます。let a:Character = "a"//Character(readLine()!) if a.isUppercase { print("小文字です") } else { print("大文字です") }
- 投稿日:2020-07-10T14:59:42+09:00
Swiftで大文字か小文字か判定する&アルファベットが格納された配列
Characterの
isUppercase
プロパティは大文字かどうかを、isLowercase
は小文字かどうかを判定してくれます。let a:Character = "a"//Character(readLine()!) if a.isUppercase { print("小文字です") } else { print("大文字です") }
["a","b","c"..."z"]
と["A","B","C"..."Z"]
は使えそう
参考let upChaAry = (65...90).map{ String(Character(UnicodeScalar($0)!)) } let lowChaArr = (97...122).map{String(Character(UnicodeScalar($0)!))} print(lowChaArr) print(upChaAry)
- 投稿日:2020-07-10T12:48:11+09:00
今日の気になる&調べた
Sasfariのタブを残しておいたりする代わりにここに記載・追記していこうと思う。
気になる
- ついに出た、「骨伝導の完全ワイヤレスイヤホン」! 音楽も外音も同時リスニング 骨伝導+ワイヤレスなんて欲しいに決まってる
- macOS Safariで簡単にmarkdownリンクをコピーできるExtensionを書いた Qiitaへの投稿を楽にするために入れた
調べた
LINE
- LINEログインしたときにLINE公式アカウントを友だち追加する(ボットリンク) | LINE Developers
- LINE Front-end Framework
- line-liff-v2-starter
- LINE Messaging API SDK | LINE Developers
- LINE の Bot 開発 超入門(前編) ゼロから応答ができるまで C# 編 - Qiita
- C#で開発するLINE Botアプリケーション (開発環境編) - pierre3のブログ
- Messaging APIリファレンス | LINE Developers
SwiftUI
- observableobject swiftui array 変更 - Google 検索
- How to push controller from ExtensionDelegate WatchKit
- SwiftUIにおけるForEach内からのBindingオブジェクトの渡し方
- Building watchOS App Interfaces with SwiftUI | Apple Developer Documentation
- SwiftUI: How to remove margin between views in VStack? - Stack Overflow
SF Symbols
C# on Mac
- macOS ではじめる ASP.NET Core x Entity Framework Core x PostgreSQL - Qiita
- チュートリアル: ASP.NET Core で Web API を作成する | Microsoft Docs ごめんなさい C#に関しては素人なんです。
GUID とか OTPとか
- 投稿日:2020-07-10T12:10:29+09:00
AIZU ONLINE JUDGE の問題をSwiftでやってみた(プログラミング入門 配列編)
トピック #1 配列
AIZU ONLINE JUDGEの問題にSwiftで解答したものになります。競技プログラミングは普段やりませんので、こうしたほうが簡単!などがあればコメントで教えて下さい。
ブラウザでプログラミング・実行ができる「オンライン実行環境」paiza.IOでテスト出力が行えます6_A
問題
与えられた数列を逆順に出力するプログラムを作成して下さい。入力は以下の形式で与えられます
n
a_1 a_2 a_3...a_n
逆順の数列を1行に出力して下さい。数列の要素の間に1つの空白を入れて下さい(最後の数の後に空白は入らないことに注意して下さい)。
解答let a = Int(readLine()!)! var arr = readLine()!.split(separator: " ").map({Int($0)}) print(arr.reversed())6_
問題
解答
let a = Int(readLine()!)! var sArr:[Int] = [] var hArr:[Int] = [] var cArr:[Int] = [] var dArr:[Int] = [] for i in 0 ..< a { var b = readLine()!.split(separator: " ") var num = Int(b[1]) ?? 0 switch b[0] { case "S": sArr.append(num) case "H": hArr.append(num) case "C": cArr.append(num) case "D": dArr.append(num) default: break } } func checkTramp(_ tramp: [Int]) -> [Int] { var notHaveArr:[Int] = [] for i in 0 ..< tramp.count { if tramp.contains(i) == false { notHaveArr.append(i) } } return notHaveArr } for i in checkTramp(sArr) { print("S \(i)") } for i in checkTramp(hArr) { print("H \(i)") } for i in checkTramp(cArr) { print("C \(i)") } for i in checkTramp(dArr) { print("D \(i)") }6_B
問題
太郎が花子と一緒にトランプ遊びをしようとしたところ、52枚あるはずのカードが n 枚のカードしか手元にありません。これらの n 枚のカードを入力として、足りないカードを出力するプログラムを作成して下さい。太郎が最初に持っていたトランプはジョーカーを除く52枚のカードです。
52枚のカードは、スペード、ハート、クラブ、ダイヤの4つの絵柄に分かれており、各絵柄には13のランクがあります。
入力
最初の行に太郎が持っているカードの枚数 n (n ≤ 52)が与えられます。続いて n 組のカードがそれぞれ1行に与えられます。各組は1つの空白で区切られた文字と整数です。文字はカードの絵柄を表し、スペードが'S'、ハートが'H'、クラブが'C'、ダイヤが'D'で表されています。整数はそのカードのランク(1 〜 13)を表しています。
出力
足りないカードをそれぞれ1行に出力して下さい。各カードは入力と同様に1つの空白で区切られた文字と整数です。
解答let a = Int(readLine()!)! var sArr:[Int] = [] var hArr:[Int] = [] var cArr:[Int] = [] var dArr:[Int] = [] for i in 1 ... a { var b = readLine()!.split(separator: " ") var num = Int(b[1]) ?? 0 switch b[0] { case "S": sArr.append(num) case "H": hArr.append(num) case "C": cArr.append(num) case "D": dArr.append(num) default: break } } func checkTramp(_ tramp: [Int]) -> [Int] { var notHaveArr:[Int] = [] for i in 1 ... tramp.count { if tramp.contains(i) == false { notHaveArr.append(i) } } return notHaveArr } for i in checkTramp(sArr) { print("S \(i)") } for i in checkTramp(hArr) { print("H \(i)") } for i in checkTramp(cArr) { print("C \(i)") } for i in checkTramp(dArr) { print("D \(i)") }6_C 公舎の入居数
問題
A大学は1フロア10部屋、3階建ての公舎4棟を管理しています。公舎の入居・退去の情報を読み込み、各部屋の入居者数を出力するプログラムを作成して下さい。n件の情報が与えられます。各情報では、4つの整数b, f, r, vが与えられます。これは、b棟f階のr番目の部屋にv人が追加で入居したことを示します。vが負の値の場合、-v人退去したことを示します。
最初、全ての部屋には誰も入居していないものとします。
入力
最初の行に情報の数 n が与えられます。
続いて n 件の情報が与えられます。各情報には4つの整数 b, f, r, v が空白区切りで1行に与えられます。
出力
4棟について入居者数を出力して下さい。各棟について、1階、2階、3階の順に入居者数を出力します。各階については、1番目、2番目、・・・、10番目の部屋の入居者数を順番に出力します。入居者数の前には1つの空白を出力して下さい。また、各棟の間には####################(20個の#)で区切って下さい。
出力例3 1 1 3 8 3 2 2 7 4 3 8 10 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 #################### 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 #################### 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 #################### 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0解答
let a = Int(readLine()!)! var room1 = [[Int]](repeating: [Int](repeating: 0, count: 10), count: 3) var room2 = [[Int]](repeating: [Int](repeating: 0, count: 10), count: 3) var room3 = [[Int]](repeating: [Int](repeating: 0, count: 10), count: 3) var room4 = [[Int]](repeating: [Int](repeating: 0, count: 10), count: 3) func make(_ b: Int, _ f: Int, _ r: Int, _ v: Int) -> Void { switch b { case 1: room1[f-1][r-1] += v case 2: room2[f-1][r-1] += v case 3: room3[f-1][r-1] += v case 4: room4[f-1][r-1] += v default: break } } for i in 0 ..< a { var c = readLine()!.split(separator: " ").map({Int($0)!}) make(c[0], c[1], c[2], c[3]) } for i in 0 ..< 3 { for j in 0 ..< 10 { print(room1[i][j], terminator: " ") } print("\n") } print(String(repeating: "#", count: 20)) for i in 0 ..< 3 { for j in 0 ..< 10 { print(room2[i][j], terminator: " ") } print("\n") } print(String(repeating: "#", count: 20)) for i in 0 ..< 3 { for j in 0 ..< 10 { print(room3[i][j], terminator: " ") } print("\n") } print(String(repeating: "#", count: 20)) for i in 0 ..< 3 { for j in 0 ..< 10 { print(room4[i][j], terminator: " ") } print("\n") }6_D ベクトルと行列の積
問題
長いので省略
サイトを見て下さい。解答
let a = readLine()!.split(separator: " ").map({Int($0)!}) var matrix = [[Int]]() var vector = [Int]() var solution = [Int](repeating: 0, count: a[0]) for i in 0 ..< a[0] { var m1 = readLine()!.split(separator: " ").map({Int($0)!}) matrix.append(m1) } for i in 0 ..< a[1] { vector.append(Int(readLine()!)!) } for i in 0 ..< a[0] { for j in 0 ..< a[1] { solution[i] += matrix[i][j] * vector[j] } } for i in solution { print(i) }
- 投稿日:2020-07-10T09:07:30+09:00
AIZU ONLINE JUDGE の問題をSwiftでやってみた(プログラミング入門 構造化プログラムⅠ編)
トピック #1 構造化プログラムⅠ
AIZU ONLINE JUDGEの問題にSwiftで解答したものになります。競技プログラミングは普段やりませんので、こうしたほうが簡単!などがあればコメントで教えて下さい。
5_A 長方形の描画
問題
入力される二つの数字の組み合わせに対して以下のような長方形を出力して下さい。
####
####
####
(3,4)
入力は複数のデータセットから構成されています。
H W
H, W がともに 0 のとき、入力の終わりとします。解答
let a = readLine()!.split(separator: " ").map({Int($0)!}) while a[0] != 0 && a[1] != 0 { for _ in 0 ..< a[0] { print(String(repeating: "#", count: a[1])) } }let a = readLine()!.split(separator: " ").map({Int($0)!}) while a[0] != 0 && a[1] != 0 { for _ in 0 ..< a[0] { for _ in 0 ..< a[1] { print("#") } } }が模範解答に近い形なのですが、出力に改行が含まれてしまうため
String(repeating: , count: )
を用いました。5_B フレームの描画
問題
5_Aの続き
(3,4)に対して
####
#。。#
####
となるようにして下さい。
解答let a = readLine()!.split(separator: " ").map({Int($0)!}) while a[0] != 0 && a[1] != 0 { for i in 0 ..< a[0] { if i == 0 || i == a[0] - 1{ print(String(repeating: "#", count: a[1])) } else { var b = String(repeating: ".", count: a[1] - 2) print("#\(b)#") } } }5_C チェスボードの描画
問題
5_Bの続き
(3,4)に対して
#。#。
。#。#
#。#。
となるように出力してください。
解答let a = readLine()!.split(separator: " ").map({Int($0)!}) while a[0] != 0 && a[1] != 0 { for i in 0 ..< a[0] { if i.isMultiple(of: 2) { if a[1].isMultiple(of: 2) { print(String(repeating: "#.", count: a[1]/2)) } else { var b = String(repeating: "#.", count: a[1]/2 - 1) print("\(b).") } } else { if a[1].isMultiple(of: 2) { print(String(repeating: ".#", count: a[1]/2)) } else { var b = String(repeating: ".#", count: a[1]/2 - 1) print("\(b)#") } } } }5_D 構造化プログラミング
問題
入力された数字nに対しnまでに含まれる3の倍数または3を含む数字を出力して下さい。(世界のナベアツ)
解答let a = Int(readLine()!)! var arr:[String] = [] for i in 1 ... a { arr.append(String(i)) } func check(_ num: [String]) -> [Int] { var resultArr:[String] = [] for i in num { if Int(i)!.isMultiple(of: 3){ resultArr.append(i) } } print(resultArr) var arr = num.filter({Int($0)! % 3 != 0}).map({String($0)}) print(arr) for i in arr { if i.contains("3") { resultArr.append(i) } } return resultArr.map({Int($0)!}) } print(check(arr).sorted())
- 投稿日:2020-07-10T00:14:30+09:00
Firestoreでユーザー別のいいね一覧を作る時
この度、初めてアプリをリリースさせて頂きました?
そして、制作中に一番苦労したCloud Firestoreの部分について書き残しておこうと思います✨苦労した点としては、
↑投稿されている画像に対してイイねをした場合、
写真のように、イイねした物の一覧を見る事ができるLike画面を作りました。しかし、、、!
Aの人がイイねした物が、Bの人がイイねを押していなくてもBの人のLike画面にも表示されていました。
今回は、
Aの人がイイねした物がAの人にしか見えないように、
Bの人がイイねした物がBの人にしか見えないように する解決策を見つけたので
書いていきます ↓ ↓ ↓CloudFirestoreの構造
このようにLikeIdにUser の ID (user.uid)を配列(Array型)で入れたらうまくいきました?
コード1(イイねする投稿が表示されている画面)
func likeSwipe(){ let saveDocument = Firestore.firestore() let user = Auth.auth().currentUser let docId = UserDefaults.standard.object(forKey: "docId") as! String let addDocument = saveDocument.collection("Posts") let query = addDocument.document(docId) query.updateData([ "LikeId" : FieldValue.arrayUnion([user!.uid]) ])↑これをイイねボタンを押した時の動作に加えてください。
これで、currentUserのUserIDがLikeIdに加えられます
コード2(Like画面_イイねした投稿の一覧を見る事ができる画面)
func fetchData(completion: @escaping () -> Void){ let user = Auth.auth().currentUser let saveDocument = Firestore.firestore() let uploadDocument = saveDocument.collection("Posts") let query = uploadDocument.whereField("LikeId", arrayContains: user!.uid) query.getDocuments { (querySnapshot, error) in↑これでquery(ユーザーが値をLikeIdに入れているかを検索)して
ユーザーがイイねしたもの(LikeIdに入れた物)のみが表示されるようになります
最後のコード以降は引っ張ってくるデーターを通常通りかけばオケです。https://firebase.google.com/docs/firestore/query-data/get-data?hl=ja
(↑最後のコード以降の参考になれば、、)おまけ(削除するときのコード)
Cellを消した時(投稿のイイねを外した時)
let docId = self.documentIds[indexPath.row] let user = Auth.auth().currentUser let saveDocument = Firestore.firestore() let uploadDocument = saveDocument.collection("Posts") uploadDocument.document(docId).updateData([ "LikeId": FieldValue.arrayRemove([user!.uid]) ])このように、ArrayをRemoveすることで自分のイイね一覧から消えても、
他の人のイイね一覧には残ったまんまです。以上
これで、Cloud Firestoreを使ったユーザー別のいいね一覧を作れると思います☺️
もし良ければ、ダウンロードしてみてください?✨
https://apps.apple.com/jp/app/baggle/id1518188746
- 投稿日:2020-07-10T00:04:20+09:00
コーチマーク+アニメーションでスワイプで削除する操作を表現する
はじめに
コーチマークとUIViewのアニメーションを組み合わせて、スワイプで削除する操作を表現してみました。
コーチマークについて
コーチマークとは・・・
実際の画面の上にオーバーレイや吹き出しを出して
画面上のボタンなどの使い方を案内してくれるやつです。アプリで初めて開く画面とかでときどきに見かけますね('・ω・`)
スワイプ削除
iOSのTableViewでは、セルをスワイプで削除する機能が簡単に実装できますし、
アプリユーザにとっても慣れている操作の一つではないかと思います(^ω^)ただ、削除ボタンみたいに目に見えてわかる機能ではないので、
ユーザ全員が当たり前のようにスワイプで削除できると認識してくれるとは限りません。。。そこで、初めて画面を開いた時にコーチマークを利用して、
スワイプで削除できるよっていうことを案内してみたいと思います!実装
今回は、Instructionsを使用してコーチマークを実装しました!
Instructionsの実装方法は、こちらの記事を参考にさせていただきましたm(_ _)m
→ swift 簡単でおしゃれなチュートリアルライブラリ,Instructions今回は、Carthageでライブラリを導入しました。
github "ephread/Instructions" ~> 2.0まずは、コーチマークを表示するところ
実装は、Instructionsのリポジトリにもサンプルがあったので、そちらを参考にしながら進めました。
CoachMarksControllerのdataSourceを実装して、
coachMarksController.start(in: )
を呼んであげるだけでコーチマークを表示できました(⌒ω⌒)今回は、コーチマークのターゲットがTableViewCellなので、事前にIndexPathを指定して、
spotlightTargetViewにcellを保持するように実装してみました。ViewController.swift(初期設定)// コーチマークの初期設定 private func setupCoachMarksController() { self.coachMarksController.dataSource = self // オーバーレイをタップでもコーチマークを閉じれるようにする self.coachMarksController.overlay.isUserInteractionEnabled = true // コーチマークの背景色を設定 self.coachMarksController.overlay.backgroundColor = UIColor.black.withAlphaComponent(0.5) } /// コーチマークを表示する private func startCoachMarks() { let indexPath = IndexPath(row: 0, section: 0) // [section, row] = [0, 0]のCellがあれば、コーチマークを表示する if tableView.numberOfRows(inSection: indexPath.section) > indexPath.row, let cell = tableView.cellForRow(at: indexPath) { self.spotlightTargetView = cell self.coachMarksController.start(in: .currentWindow(of: self)) } }CoachMarksControllerのdataSourceの実装はこんな感じでシンプル
ViewController.swift(CoachMarksControllerDataSource実装部)extension ViewController: CoachMarksControllerDataSource { func numberOfCoachMarks(for coachMarksController: CoachMarksController) -> Int { return 1 } func coachMarksController(_ coachMarksController: CoachMarksController, coachMarkAt index: Int) -> CoachMark { // 吹き出しを表示する対象のビューを指定する return coachMarksController.helper.makeCoachMark(for: spotlightTargetView) } func coachMarksController(_ coachMarksController: CoachMarksController, coachMarkViewsAt index: Int, madeFrom coachMark: CoachMark) -> (bodyView: (UIView & CoachMarkBodyView), arrowView: (UIView & CoachMarkArrowView)?) { let coachViews = coachMarksController.helper.makeDefaultCoachViews(withArrow: true, withNextText: false, arrowOrientation: coachMark.arrowOrientation) coachViews.bodyView.hintLabel.text = "スワイプでお気に入りから削除できます" return (bodyView: coachViews.bodyView, arrowView: coachViews.arrowView) } }この状態だと、まだ分かりづらいかなーと思うので、アニメーションを加えていきます。
スワイプで削除風のアニメーションを実装
スワイプで削除するようなアニメーションを実装します。
アニメーションは、Stack Overflowの投稿を
パクらせて参考にさせていただきましたm(_ _)m
UITableView invoke swipe actions programmatically参考情報そのままだと少し使いづらいところがあったので、
アニメーション完了後の処理をクロージャで実装できるようにしています。動作
アニメーションを加えたら、いい感じになりました(^-^)v
(Gifの問題で、「削除」ラベルの色が実際と少し違っています。)完成したコード
以下、アニメーション完了後からオーバーレイのタップを許可するなどの微調整をした最終的なソースコードです。
(コーチマーク表示済みかどうかの判定は、UserDefaultsなどで実現できると思うので、省いています。)ViewController.swiftimport UIKit import Instructions final class ViewController: UIViewController { private let coachMarksController = CoachMarksController() // コーチマークでスポットライトが当たるView private var spotlightTargetView: UIView! private var spotlightTargetIndexPath: IndexPath? private var items = ["apple", "banana", "cherry"] @IBOutlet private weak var tableView: UITableView! { didSet { tableView.dataSource = self } } override func viewDidLoad() { super.viewDidLoad() self.setupCoachMarksController() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.navigationItem.title = "お気に入り一覧" } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) self.startCoachMarks() } private func setupCoachMarksController() { self.coachMarksController.dataSource = self self.coachMarksController.delegate = self // コーチマークの背景色を設定 self.coachMarksController.overlay.backgroundColor = UIColor.black.withAlphaComponent(0.5) } /// コーチマークを表示する private func startCoachMarks() { let indexPath = IndexPath(row: 0, section: 0) // [section, row] = [0, 0]のCellがあれば、コーチマークを表示する if tableView.numberOfRows(inSection: indexPath.section) > indexPath.row, let cell = tableView.cellForRow(at: indexPath) { self.spotlightTargetView = cell self.spotlightTargetIndexPath = indexPath self.coachMarksController.start(in: .currentWindow(of: self)) } } } extension ViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return items.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") else { fatalError("Cell is nil.") } cell.textLabel?.text = items[indexPath.row] return cell } func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { return true } func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { self.items.remove(at: indexPath.row) tableView.deleteRows(at: [indexPath], with: .automatic) } } } extension ViewController: CoachMarksControllerDataSource { func numberOfCoachMarks(for coachMarksController: CoachMarksController) -> Int { return 1 } func coachMarksController(_ coachMarksController: CoachMarksController, coachMarkAt index: Int) -> CoachMark { // 吹き出しを表示する対象のビューを指定する return coachMarksController.helper.makeCoachMark(for: spotlightTargetView) } func coachMarksController(_ coachMarksController: CoachMarksController, coachMarkViewsAt index: Int, madeFrom coachMark: CoachMark) -> (bodyView: (UIView & CoachMarkBodyView), arrowView: (UIView & CoachMarkArrowView)?) { let coachViews = coachMarksController.helper.makeDefaultCoachViews(withArrow: true, withNextText: false, arrowOrientation: coachMark.arrowOrientation) coachViews.bodyView.hintLabel.text = "スワイプでお気に入りから削除できます" return (bodyView: coachViews.bodyView, arrowView: coachViews.arrowView) } } extension ViewController: CoachMarksControllerDelegate { func coachMarksController(_ coachMarksController: CoachMarksController, didShow coachMark: CoachMark, afterChanging change: ConfigurationChange, at index: Int) { guard let targetIndexPath = self.spotlightTargetIndexPath else { return } UIView.animateRevealHideActionForRow(tableView: self.tableView, indexPath: targetIndexPath) { [weak self] in // アニメーション完了後、オーバーレイをタップでもコーチマークを閉じれるようにする self?.coachMarksController.overlay.isUserInteractionEnabled = true } } }UIView+.swiftimport UIKit extension UIView { /// TableViewのスワイプアクションの擬似的なアニメーション class func animateRevealHideActionForRow(tableView: UITableView, indexPath: IndexPath, completion: (() -> Void)? = nil) { guard let cell = tableView.cellForRow(at: indexPath) else { return } let swipeLabelWidth = UIScreen.main.bounds.width / 2 let swipeLabelFrame = CGRect(x: cell.bounds.size.width, y: 0, width: swipeLabelWidth, height: cell.bounds.size.height) var swipeLabel: UILabel? = .init(frame: swipeLabelFrame) swipeLabel?.text = " 削除" swipeLabel?.backgroundColor = .red swipeLabel?.textColor = .white cell.addSubview(swipeLabel!) UIView.animate(withDuration: 0.5, animations: { cell.frame = .init(x: cell.frame.origin.x - swipeLabelWidth / 2, y: cell.frame.origin.y, width: cell.bounds.size.width + swipeLabelWidth / 2, height: cell.bounds.size.height) }) { finished in UIView.animate(withDuration: 0.5, animations: { cell.frame = .init(x: cell.frame.origin.x + swipeLabelWidth / 2, y: cell.frame.origin.y, width: cell.bounds.size.width - swipeLabelWidth / 2, height: cell.bounds.size.height) }, completion: { finished in swipeLabel?.removeFromSuperview() swipeLabel = nil completion?() }) } } }さいごに
コーチマークでテキストを添えるだけでも親切だけど、動きをつけるとより親切かなと思いました!
(やり過ぎると、しつこいですけどね・・・)