Swift3 配列 日付でソートする場合
配列の中で日付でソートしたい場合についてまとめます。
Swift3 CoreDataソート実装
ソートについてまとめる
以下の関数を日付でソートしたいとする。
func getData() { let context = appDelegate.persistentContainer.viewContext do { expenses = try context.fetch(Expenses.fetchRequest()) } catch { print("Cannot fetch Expenses") } }
このように記載する。
func getData() { let context = appDelegate.persistentContainer.viewContext let fetchRequest = NSFetchRequest<ResultType>(entityName: "Expenses") let sort = NSSortDescriptor(key: #keyPath(Expenses.date), ascending: true) fetchRequest.sortDescriptors = [sort] do { expenses = try context.fetch(fetchRequest) } catch { print("Cannot fetch Expenses") } }
NSFetchRequestがsortDescriptorsというプロパティを持っています。
それをインスタンスにセットするだけです。
ちなみにsortDescriptorsは配列をセットします。
こんな感じです。実装したコード
fetchRequest.sortDescriptors = [ NSSortDescriptor(key: "最優先のカラム名" , ascending: true), NSSortDescriptor(key: "2番目に優先したいカラム名", ascending: true)]
検索してソートするときに、例えば、男女別でソートして、男子を先に表示する。 その後、生年月日でソートするとかソートには複数の条件が考えられるからです。 sortDescriptorsには、次のようなものをセットできます。
public init(key: String?, ascending: Bool) //キーに文字列、降順、昇順か public init(key: String?, ascending: Bool, selector: Selector?)
selectorって何?美味しいの?という人のために、、
selectorは、処理先のメソッドを指定するもの。
例えば、
selector: #selector(ViewController.hoge(_:)),
と引数で指定したときは、その呼び出す関数を@objつけて記載する。
@objc func hoge(_ sender:Timer) -> Void { print("タイマー実行") }
こんな感じ。 Objective-Cではポインターだったけど、swiftでは構造体となっているので、このように記載しないといけない。 Objective-Cの文字列とセレクタを変換するみたいです。 あとはコンパイラがやってくれる。
以上です。
git まとめ
gitのまとめ
git config
でメールアドレスなどを登録する
git config -l
で設定ファイルを見れるこれは結構使える。
3つの環境がある。
1-作業環境
2-ステージング環境
3-リポジトリ(保存するところ)
リモート(GitHubサーバー)、ローカル(自分のPC)それぞれにこの3つの環境がある。
これがゴチャゴチャになると理解できなくなる。
git add .
作業環境から、ステージング環境に上げる 最後のドット . が大切
現在のという意味。
git commit -m "コミットメッセージを自分でわかるように書く"
これでリポジトリに上がる。 日付やidが割り当てられ、その時の状態に戻ることが可能。
git log -online
logが 1行で表示される 見やすい
git log -p
gitの変更内容が見れる - - - が以前のもの +++が追加されたもの
git status
ステイタス 現在の状況、場所とか確認できる これは大切
git rm index.html のようにする
ファイル消去はgitのコマンドを利用する gitを利用しないで削除すると、gitで管理できなくなり、エラーが出る。 これもポイント
push pull関係
まずリモートの設定をきちんとしておかないといけない。
git remote -v
リモートの状態を確認
git remote set-url origin {URL.git}
リモートのURLを設定するコマンド urlは最後に .git となっているはず.
git push {ローカルのブランチ名}:{リモートのブランチ名}
pushについてのコマンド
pullしたところにしか、pushできない。だから安全。これ結構大切です。
git pull origin {pullしたいリモートブランチ名}:{ローカルブランチ名}
リモートリポジトリ内の特定のブランチをpullしたいときに利用
Swift MVCモデルの役割の具体的説明(途中なので、読まないこと!)
todoアプリを作る MVCもでるで
モデルの役割
データ構造を表現すること
final class Task { var text: String // タスクの内容 var deadline: Date // 締切 // textとdeadlineを引数にとるイニシャライザメソッド init (text: String, deadline: Date) { self.text = text self.deadline = deadline } // dictionaryを引数にとるイニシャライザメソッド。 init(from dictionary: [String: Any]) { text = dictionary["text"] as! String deadline = dictionary["deadline"] as! Date } }
Task内容は、 1-タスク内容 2-締め切
モデル--データの振る舞いやロジックを保持する
final class TaskDataSource: NSObject { private var tasks = [Task]() func loadData() { let userDefaults = UserDefaults.standard let taskDictionaries = userDefaults.object(forKey: "tasks") as? [[String: Any]] guard let t = taskDictionaries else { return } for dic in t { let task = Task(from: dic) tasks.append(task) } }
UserDefaultsクラスの役割は
ユーザーのデフォルトデータベースとのインターフェイス。アプリの起動時にキーと値のペアを永続的に保存します。
standardプロパティは
standardUserDefaultsは、現在のアプリケーションの検索リストを検索するように設定されたNSUserDefaultsのグローバルインスタンスを返します。
ざっくりインスタンスの返すとおぼえておくと良いかも。
func save(task: Task) { tasks.append(task) var taskDictionaries = [[String: Any]]() for t in tasks { let taskDictionary: [String: Any] = ["text": t.text, "deadline": t.deadline] taskDictionaries.append(taskDictionary) } let userDefaults = UserDefaults.standard userDefaults.set(taskDictionaries, forKey: "tasks") userDefaults.synchronize() }
Task を保存するために、Tasksをdataに変換して保存する または辞書型にキャストして配列として保存。 ここでは後者
コントローラ--ModelとViewの仲介を行う
rails NameError: uninitialized constant?? Devise入れたらおかしくなったときの対処法
deviseを入れてからおかしくなったので解決法。
このようなエラーが出る。
NameError: uninitialized constant User
rails c
rails s
もできなくなる??
routesの
devise_for :users
を削除するとサーバーが起動する。
原因は
デバイスをインストールしていないのに
こちらがインストールコマンド rails g devise:install
デバイスでuserテーブルを作ってしまったようだ。
rails g devise user
これにより、ルーティングにはdeviseが記載され、おかしな挙動になりrailsコマンドが利用できなくなる。
対処法はこちらにあった
この記事ではより、初心者向けに理由を説明したい。
1-routes.rbにあるdevise_for :usersというコードを削除する
これがあるとルーティングがおかしくなるからか、railsコマンドが利用できない。
上記のNameError: uninitialized constant User のエラーが出る。
2-マイグレーションファイルをロールバックする。
Railsは、DBのバージョン管理がデフォルトで利用できる。それがマイグレーションファイル。
テーブルの操作をするときは、マイグレーションファイルを生成して、実行する。
このマイグレーションファイルのバージョンを持っているので、マイグレーションファイルをそのまま削除すると
厄介なことになる。
それで
rake db:rollback
でロールバックと言って、マイグレーションファイルのバージョンを戻す。 それから、userテーブルを作ったときの、マイグレーションファイルを削除する。
3-usrモデルを削除する
rails d model user
このuserモデルをdeviseをインストールしていないのにdeviseで生成したのがすべての間違いのはじまり。
よってここまで戻ってからdeviseをインストールする。
rails g devise:install
めでたし、めでたし
SWift ??とは
??は中値演算子という
オプショナル型が値を持っていれば、それをラップして代入。
持っていなければ、右辺を代入する。
例
let hoge:Int? hoge = 1 let fuga = hoge ?? 3 print(fuga) =>1
値が入っているので1が出力される
let hoge:Int? hoge = nil let fuga = hoge ?? 3 print(fuga) =>3
値が入っていないので??中値演算子の右辺3が代入されている
実例
override func mapAgent(_ mapAgent: MsMapAgent, showGoogleMap datPerson: DatPerson) { //datPerson.jusho があるならラップしてjushoへ代入 そうでなければ""を入れなさい let jusho = datPerson.jusho ?? "" //urlにはjushoを代入 let url = jusho != "" ? URL(string:"comgooglemaps://?q=\(jusho)¢er=\(datPerson.latitude),\(datPerson.longitude)&zoom=14&views=traffic")! : URL(string:"comgooglemaps://?center=\(datPerson.latitude),\(datPerson.longitude)&zoom=14&views=traffic")! if (UIApplication.shared.canOpenURL(URL(string:"comgooglemaps://")!)) { // UIApplication.shared.openURL(url) UIApplication.shared.open(url, options: [:], completionHandler: {(success) in if (success){ NSLog("success") } }) } else { MsAlert.confirmOk(self, "Cannot open Google Maps") } }
Swift3 CoreData 最大値取得 (途中!読まないこと!)
まずimport
import Foundation import UIKit import CoreData
static func maxId() -> Int { //contextはDBファイルそのもの 入れ物を用意 let appDelegate = UIApplication.shared.delegate as? AppDelegate let context = appDelegate?.persistentContainer.viewContext /// ここからが最大値の取得方法 let expressionUserId = "Maxid" /// fetchRequestの生成 let fetchRequest = NSFetchRequest<NSFetchRequestResult>()
\<NSFetchRequestResult はジェネリクス
型をパラメータとして受け取ることができる。ここでは割愛
このクラス定義は
open class NSFetchRequest<ResultType> : NSPersistentStoreRequest, NSCoding where ResultType : NSFetchRequestResult open var entity: NSEntityDescription?
というプロパティを持つ
/// EntityDescriptionの生成 //in : context contextの中にあるという 意味 let entityDescription = NSEntityDescription.entity( forEntityName :"Person" , in : context!)
entityの初期化はこのように記載
それに倣っただけ。
open class func entity(forEntityName entityName: String, in context: NSManagedObjectContext) -> NSEntityDescription?
fetchRequest.entity = entityDescription // let keyPathExpression = NSExpression(forKeyPath: "id") //id を探しますよ、カラムはidを持っていてね let expression = NSExpression(forFunction: "max:", arguments: [keyPathExpression]) let expressionDescription = NSExpressionDescription() expressionDescription.name = expressionUserId expressionDescription.expression = expression expressionDescription.expressionResultType = NSAttributeType.integer64AttributeType fetchRequest.resultType = NSFetchRequestResultType.dictionaryResultType fetchRequest.propertiesToFetch = [expressionDescription]
propertiesToFetchは配列を渡さないといけない
**定義はこうなっている
open var propertiesToFetch: [Any]?
//エラーハンドリング do{ let results = try context?.fetch(fetchRequest) if let maxId = ((results?.first as AnyObject).value(forKey: expressionUserId)) as? Int { print("maxId = \(maxId)") return maxId + 1 } else{ return 1 } } catch let error { print(error) } return -1 }