Skip to content

Instantly share code, notes, and snippets.

@gitbricho
Last active April 19, 2016 17:02
Show Gist options
  • Save gitbricho/d34d97efbd6232c249a5 to your computer and use it in GitHub Desktop.
Save gitbricho/d34d97efbd6232c249a5 to your computer and use it in GitHub Desktop.
テンプレート:テーブルビュー
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
//詳細ビューコントローラの参照を保持.
var detailVC:DetailViewController?
//マスタービューコントローラの参照を保持
var masterVC:ViewController?
func applicationDidFinishLaunching(aNotification: NSNotification) {
// Insert code here to initialize your application
}
func applicationWillTerminate(aNotification: NSNotification) {
// Insert code here to tear down your application
}
}
import Cocoa
class C連絡先: NSObject {
//MARK: プロパティ
var z氏名:String
var zよみ:String
var z写真:NSImage?
//MARK: イニシャライザ
init(氏名:String, よみ:String, 写真:NSImage?) {
self.z氏名 = 氏名
self.zよみ = よみ
self.z写真 = 写真
}
}
import Cocoa
class C連絡先: NSObject {
//MARK: プロパティ
var zID:Int64
var z氏名:String
var zよみ:String
var z写真:NSImage?
var z生年月日:NSDate = NSDate.init()
var z性別:String = ""
var zメモ:String = ""
var zバージョン:Int64 = 0
//MARK: イニシャライザ
init(ID:Int64, 氏名:String, よみ:String, 写真:NSImage?) {
zID = ID
z氏名 = 氏名
zよみ = よみ
z写真 = 写真
}
convenience init(ID:Int64, 氏名:String, よみ:String,
写真:NSImage?, 性別:String, 生年月日:NSDate, メモ:String) {
self.init(ID:ID, 氏名:氏名, よみ:よみ, 写真:写真)
z性別 = 性別
z生年月日 = 生年月日
zメモ = メモ
}
func toString() -> String {
return "(\(zID))[simei:\(z氏名), " +
"yomi:\(zよみ), seibetu:\(z性別), " +
"seinenGappi:\(z生年月日.shortDate), " +
"memo:\(zメモ), version:\(zバージョン)]"
}
}
import Foundation
import SQLite
class ContactRepo {
// MARK:プロパティ
var db:Connection
var contacts:Table
let INSERT_KU = "INSERT INTO \"contacts\" (simei, " +
"yomi, seibetu, seinenGappi, photo, memo, version) " +
"values (?, ?, ?, ?, ?, ?, ?)"
let UPDATE_KU = "UPDATE \"contacts\" SET " +
"\"simei\" = ?, \"yomi\" = ?, " +
"\"seibetu\" = ?, \"seinenGappi\" = ?, " +
"\"photo\" = ?, \"memo\" = ?, " +
"\"version\" = ?" +
"WHERE (\"id\" = ? and \"version\" = ?)"
// MARK:イニシャライザ
init(_ db: Connection) {
self.db = db
self.contacts = ContactDef.contacts
}
// MARK:メソッド
func findAll() throws -> [C連絡先] {
return try findAllOrderBy([ContactDef.yomi.desc])
}
func findAllOrderBy(cols: [Expressible])
throws -> [C連絡先] {
var 連絡先リスト:[C連絡先] = []
for row in try db.prepare(contacts.order(cols)) {
連絡先リスト.append(createContact(row))
}
return 連絡先リスト
}
func findOne(id: Int64) throws -> C連絡先? {
var 連絡先リスト:[C連絡先] = []
for row in try db.prepare(
contacts.filter(ContactDef.id == id)) {
連絡先リスト.append(createContact(row))
}
if 連絡先リスト.count > 0 {
return 連絡先リスト[0]
} else {
return nil
}
}
func createContact(row:Row) -> C連絡先 {
return C連絡先(ID: row[ContactDef.id],
氏名: row[ContactDef.simei],
よみ: row[ContactDef.yomi],
写真: row[ContactDef.photo]?.image,
性別: row[ContactDef.seibetu]!,
生年月日: row[ContactDef.seinenGappi]!.nsDate,
メモ: row[ContactDef.memo])
}
func save(ct: C連絡先) throws {
if ct.zID == 0 {
let stmt = try db.prepare(INSERT_KU)
try stmt.run(
ct.z氏名, ct.zよみ, ct.z性別,
ct.z生年月日.shortDate,
ct.z写真?.base64String,
ct.zメモ, ct.zバージョン)
} else {
let stmt = try db.prepare(UPDATE_KU)
try stmt.run(
ct.z氏名, ct.zよみ, ct.z性別,
ct.z生年月日.shortDate,
ct.z写真?.base64String,
ct.zメモ, ct.zバージョン + 1,
ct.zID, ct.zバージョン)
}
}
func delete(ct: C連絡先) throws {
try db.run(contacts.filter(ContactDef.id == ct.zID).delete())
}
}
import Cocoa
import SQLite
//データベースのパス
let DB_PATH = NSHomeDirectory() + "/Desktop/Data/mydb.db"
//初期化のための連絡先データ
let L連絡先データ:[C連絡先] = [
C連絡先(ID: 0, 氏名: "山田太郎", よみ: "やまだたろう",
写真: NSImage(named: "Al_Pacino02")!,
性別: "男", 生年月日: "1980/05/01".nsDate,
メモ: "メモ000001"),
C連絡先(ID: 0, 氏名: "大山優子", よみ: "おおやまゆうこ",
写真: NSImage(named: "Cameron04")!,
性別: "女", 生年月日: "1980/10/12".nsDate,
メモ: "メモ000002")
]
struct ContactDef {
static let contacts = Table("contacts")
//列定義
static let id = Expression<Int64>("id")
static let simei = Expression<String>("simei")
static let yomi = Expression<String>("yomi")
static let seibetu = Expression<String?>("seibetu")
static let seinenGappi = Expression<String?>("seinenGappi")
static let photo = Expression<String?>("photo")
static let memo = Expression<String>("memo")
static let version = Expression<Int64>("version")
}
class ContactDdl {
var db:Connection
init(_ db:Connection) {
self.db = db
}
//テーブルを作成
func createTable() throws -> Void {
try db.run(
ContactDef.contacts.create { t in
t.column(ContactDef.id, primaryKey: true)
t.column(ContactDef.simei)
t.column(ContactDef.yomi)
t.column(ContactDef.seibetu)
t.column(ContactDef.seinenGappi)
t.column(ContactDef.photo)
t.column(ContactDef.memo)
t.column(ContactDef.version)
}
)
}
}
import Cocoa
class DetailViewController: NSViewController {
//MARK:プロパティ
@IBOutlet weak var simeiTextField: NSTextField!
@IBOutlet weak var yomiTextField: NSTextField!
@IBOutlet weak var photoImage: NSImageView!
let app : AppDelegate = (NSApplication.sharedApplication().delegate
as? AppDelegate)!
override func viewDidLoad() {
super.viewDidLoad()
app.detailVC = self
}
func F詳細情報更新(連絡先: C連絡先?) {
var v氏名 = ""
var vよみ = ""
var v写真:NSImage?
if let l連絡先 = 連絡先 {
v氏名 = l連絡先.z氏名
vよみ = l連絡先.zよみ
v写真 = l連絡先.z写真
}
self.simeiTextField.stringValue = v氏名
self.yomiTextField.stringValue = vよみ
self.photoImage.image = v写真
}
}
....
//MARK:アクション
@IBAction func changePhoto(sender: AnyObject) {
if let _ = app.masterVC!.F選択連絡先() {
IKPictureTaker().beginPictureTakerSheetForWindow(
self.view.window,
withDelegate: self,
didEndSelector: #selector(
DetailViewController.pictureTakerDidEnd(
_:returnCode:contextInfo:)),
contextInfo: nil)
}
}
func pictureTakerDidEnd(picker: IKPictureTaker,
returnCode: NSInteger,
contextInfo: UnsafePointer<Void>) {
let image = picker.outputImage()
if image != nil && returnCode == NSModalResponseOK {
self.photoImage.image = image
app.masterVC!.F選択連絡先()?.z写真 = image
}
}
import Cocoa
import Quartz
class DetailViewController: NSViewController {
//MARK:プロパティ
@IBOutlet weak var simeiTextField: NSTextField!
@IBOutlet weak var yomiTextField: NSTextField!
@IBOutlet weak var photoImage: NSImageView!
@IBOutlet weak var seinenGappiDatePicker: NSDatePicker!
@IBOutlet weak var seibetuCombo: NSComboBox!
@IBOutlet var memoTextView: NSTextView!
let app : AppDelegate = (NSApplication.sharedApplication().delegate
as? AppDelegate)!
let 性別選択リスト = ["","男","女"]
var 保存連絡先:C連絡先?
override func viewDidLoad() {
super.viewDidLoad()
app.detailVC = self
seibetuCombo.removeAllItems()
seibetuCombo.addItemsWithObjectValues(性別選択リスト)
//seibetuCombo.selectItemAtIndex(0)
}
func F詳細情報更新(連絡先: C連絡先?) {
保存連絡先 = C連絡先(ID: 0, 氏名: "",よみ: "", 写真: nil)
if let l連絡先 = 連絡先 {
保存連絡先!.z氏名 = l連絡先.z氏名
保存連絡先!.zよみ = l連絡先.zよみ
保存連絡先!.z写真 = l連絡先.z写真
保存連絡先!.z性別 = l連絡先.z性別
保存連絡先!.z生年月日 = l連絡先.z生年月日
保存連絡先!.zメモ = l連絡先.zメモ
}
self.simeiTextField.stringValue = 保存連絡先!.z氏名
self.yomiTextField.stringValue = 保存連絡先!.zよみ
self.photoImage.image = 保存連絡先!.z写真
self.seibetuCombo.stringValue = 保存連絡先!.z性別
self.memoTextView.string = 保存連絡先!.zメモ
self.seinenGappiDatePicker.dateValue = 保存連絡先!.z生年月日
}
//MARK:アクション
@IBAction func changePhoto(sender: AnyObject) {
if let _ = app.masterVC!.F選択連絡先() {
IKPictureTaker().beginPictureTakerSheetForWindow(
self.view.window,
withDelegate: self,
didEndSelector: #selector(
DetailViewController.pictureTakerDidEnd(
_:returnCode:contextInfo:)),
contextInfo: nil)
}
}
func pictureTakerDidEnd(picker: IKPictureTaker,
returnCode: NSInteger,
contextInfo: UnsafePointer<Void>) {
let image = picker.outputImage()
if image != nil && returnCode == NSModalResponseOK {
self.photoImage.image = image
app.masterVC!.F選択連絡先()?.z写真 = image
}
}
}
import Cocoa
extension NSDateFormatter {
convenience init(dateFormat: String) {
self.init()
self.dateFormat = dateFormat
}
}
extension NSDate {
struct Date {
static let formatter = NSDateFormatter(
dateFormat: "yyyy/MM/dd")
}
var shortDate: String {
return Date.formatter.stringFromDate(self)
}
}
extension String {
struct Date {
static let formatter = NSDateFormatter(
dateFormat: "yyyy/MM/dd")
}
var nsDate: NSDate {
return Date.formatter.dateFromString(self)!
}
var image: NSImage? {
//空白を+に変換
let base64String = self.stringByReplacingOccurrencesOfString(
" ",
withString: "+",
options:NSStringCompareOptions.RegularExpressionSearch,
range: nil)
//文字列をデコード
let decodeBase64:NSData? =
NSData(base64EncodedString:base64String,
options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)
if let decodeSuccess = decodeBase64 {
//NSDataからUIImageを生成
return NSImage(data: decodeSuccess)
}
return nil
}
}
extension NSImage {
var base64String: String {
let rep = NSBitmapImageRep(data: TIFFRepresentation!)!
let data:NSData? = rep.representationUsingType(
.NSPNGFileType, properties: [:])!
//BASE64のStringに変換する
if let pngData = data {
return pngData.base64EncodedStringWithOptions(
NSDataBase64EncodingOptions.Encoding64CharacterLineLength)
}
return ""
}
func savePNG(path:String) -> Bool {
return true
//return base64String.writeToFile(path, atomically: true, encoding: ???)
}
}
import Cocoa
class ViewController: NSViewController ,
NSTableViewDataSource,
NSTableViewDelegate {
//MARK:プロパティ
var z連絡先データ:[C連絡先] = [
C連絡先(氏名: "山田太郎", よみ: "やまだたろう",
写真: NSImage(named: "Al_Pacino02")!),
C連絡先(氏名: "大山優子", よみ: "おおやまゆうこ",
写真: NSImage(named: "Cameron04")!)
]
@IBOutlet weak var contactTableView: NSTableView!
let app : AppDelegate = (NSApplication.sharedApplication().delegate
as? AppDelegate)!
//MARK:ライフサイクル
override func viewDidLoad() {
super.viewDidLoad()
app.masterVC = self
contactTableView.setDataSource(self)
contactTableView.setDelegate(self)
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
//MARK:データソース
func numberOfRowsInTableView(tableView: NSTableView) -> Int {
return z連絡先データ.count
}
func tableView(aTableView: NSTableView,
objectValueForTableColumn aTableColumn: NSTableColumn?,
row rowIndex: Int) -> AnyObject? {
var vセルデータ = "";
if (rowIndex < z連絡先データ.count) {
let contact:C連絡先 = z連絡先データ[rowIndex]
switch (aTableColumn?.title)! {
case "氏名":
vセルデータ = contact.z氏名
case "よみ":
vセルデータ = contact.zよみ
default:
break
}
}
//print("rtn:\(vセルデータ)")
return vセルデータ
}
//MARK: デリゲート
//MARK:アクション
//MARK:ヘルパー関数
}
....
//MARK: デリゲート
//テーブルビューの選択行が変わった場合.
func tableViewSelectionDidChange(aNotification: NSNotification) {
//詳細ビューコントローラの関数を実行
app.detailVC!.F詳細情報更新(F選択連絡先())
}
//MARK:アクション
//MARK:ヘルパー関数
//選択行の連絡先情報を返す.
func F選択連絡先() -> C連絡先? {
let l選択行 = self.contactTableView.selectedRow
if l選択行 >= 0 && l選択行 < self.z連絡先データ.count {
return self.z連絡先データ[l選択行]
}
return nil
}
....
//MARK:アクション
@IBAction func addContact(sender: AnyObject) {
let l新規行 = z連絡先データ.count
let l新規連絡先 = C連絡先(氏名: "新規氏名\(l新規行+1)",
よみ: "しんきよみ\(l新規行+1)", 写真: nil)
self.z連絡先データ.append(l新規連絡先)
self.contactTableView.beginUpdates()
self.contactTableView.insertRowsAtIndexes(
NSIndexSet(index: l新規行),
withAnimation: NSTableViewAnimationOptions.EffectNone)
self.contactTableView.endUpdates()
self.contactTableView.selectRowIndexes(
NSIndexSet(index: l新規行),
byExtendingSelection:false)
self.contactTableView.scrollRowToVisible(l新規行)
}
@IBAction func deleteContact(sender: AnyObject) {
if let _ = F選択連絡先() {
//データソースのデータを削除
let l削除行 = self.contactTableView.selectedRow
self.z連絡先データ.removeAtIndex(l削除行)
//テーブルビューのデータを削除(右へスライドするアニメ付き)
self.contactTableView.beginUpdates()
self.contactTableView.removeRowsAtIndexes(
NSIndexSet(index: l削除行),
withAnimation: NSTableViewAnimationOptions.SlideRight)
self.contactTableView.endUpdates()
if l削除行 > 0 {
//削除行が先頭行でない場合
//選択行を1つ前の行へ移動
self.contactTableView.selectRowIndexes(
NSIndexSet(index: l削除行-1),
byExtendingSelection:false)
} else if self.z連絡先データ.count > 0 {
//削除行が先頭行だが、行が一行以上ある場合
self.contactTableView.selectRowIndexes(
NSIndexSet(index: l削除行),
byExtendingSelection:false)
}
self.contactTableView.scrollRowToVisible(
self.contactTableView.selectedRow)
app.detailVC!.F詳細情報更新(F選択連絡先())
}
}
....
import Cocoa
import SQLite
class ViewController: NSViewController ,
NSTableViewDataSource,
NSTableViewDelegate {
//MARK:プロパティ
var z連絡先一覧 = [C連絡先]()
@IBOutlet weak var contactTableView: NSTableView!
let app : AppDelegate = (NSApplication.sharedApplication().delegate
as? AppDelegate)!
//MARK:ライフサイクル
override func viewDidLoad() {
super.viewDidLoad()
app.masterVC = self
contactTableView.setDataSource(self)
contactTableView.setDelegate(self)
//----- sqlite test --------
do {
//データベースに接続
//let dbMemory = try Connection(.InMemory)
//let dbTemporary = try Connection(.Temporary)
//let dbTemporary = try Connection("")
let db = try Connection(DB_PATH) //URI
print("接続:\(db.description)")
//DDL作成
let ddl = ContactDdl(db)
do {
try ddl.createTable()
print("create table!")
} catch {
print("create Table: error!")
}
do {
//初期データを作成
let repo = ContactRepo(db)
z連絡先一覧 = try repo.findAll()
if z連絡先一覧.count == 0 {
print("登録データは0件")
for ct in L連絡先データ {
try repo.save(ct)
}
z連絡先一覧 = try repo.findAll()
}
} catch {
print("create Data: error!")
}
//取得データを表示
print("登録件数=\(z連絡先一覧.count)")
for ct in z連絡先一覧 {
print(ct.toString())
}
} catch {
print("error!")
}
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
//MARK:データソース
func numberOfRowsInTableView(tableView: NSTableView) -> Int {
return z連絡先一覧.count
}
func tableView(aTableView: NSTableView,
objectValueForTableColumn aTableColumn: NSTableColumn?,
row rowIndex: Int) -> AnyObject? {
var vセルデータ = "";
if (rowIndex < z連絡先一覧.count) {
let contact:C連絡先 = z連絡先一覧[rowIndex]
switch (aTableColumn?.title)! {
case "氏名":
vセルデータ = contact.z氏名
case "よみ":
vセルデータ = contact.zよみ
default:
break
}
}
//print("rtn:\(vセルデータ)")
return vセルデータ
}
//MARK: デリゲート
//テーブルビューの選択行が変わった場合.
func tableViewSelectionDidChange(aNotification: NSNotification) {
//詳細ビューコントローラの関数を実行
app.detailVC!.F詳細情報更新(F選択連絡先())
}
//MARK:アクション
@IBAction func addContact(sender: AnyObject) {
let l新規行 = z連絡先一覧.count
let l新規連絡先 = C連絡先(ID: 0,
氏名: "新規氏名\(l新規行+1)",
よみ: "しんきよみ\(l新規行+1)", 写真: nil)
self.z連絡先一覧.append(l新規連絡先)
self.contactTableView.beginUpdates()
self.contactTableView.insertRowsAtIndexes(
NSIndexSet(index: l新規行),
withAnimation: NSTableViewAnimationOptions.EffectNone)
self.contactTableView.endUpdates()
self.contactTableView.selectRowIndexes(
NSIndexSet(index: l新規行),
byExtendingSelection:false)
self.contactTableView.scrollRowToVisible(l新規行)
}
@IBAction func deleteContact(sender: AnyObject) {
if let _ = F選択連絡先() {
//データソースのデータを削除
let l削除行 = self.contactTableView.selectedRow
self.z連絡先一覧.removeAtIndex(l削除行)
//テーブルビューのデータを削除(右へスライドするアニメ付き)
self.contactTableView.beginUpdates()
self.contactTableView.removeRowsAtIndexes(
NSIndexSet(index: l削除行),
withAnimation: NSTableViewAnimationOptions.SlideRight)
self.contactTableView.endUpdates()
if l削除行 > 0 {
//削除行が先頭行でない場合
//選択行を1つ前の行へ移動
self.contactTableView.selectRowIndexes(
NSIndexSet(index: l削除行-1),
byExtendingSelection:false)
} else if self.z連絡先一覧.count > 0 {
//削除行が先頭行だが、行が一行以上ある場合
self.contactTableView.selectRowIndexes(
NSIndexSet(index: l削除行),
byExtendingSelection:false)
}
self.contactTableView.scrollRowToVisible(
self.contactTableView.selectedRow)
app.detailVC!.F詳細情報更新(F選択連絡先())
}
}
//MARK:ヘルパー関数
//選択行の連絡先情報を返す.
func F選択連絡先() -> C連絡先? {
let l選択行 = self.contactTableView.selectedRow
if l選択行 >= 0 && l選択行 < self.z連絡先一覧.count {
return self.z連絡先一覧[l選択行]
}
return nil
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment