頭と尻尾はくれてやる!

パソコンおやじのiPhoneアプリ・サイト作成・運営日記


ユニットテストを後から追加すると動かない

Xcodeでプロジェクト作成時にテストなしで作成したものの、後で追加したい場合がある。

プロジェクト名を仮にMyProjectとしておく。
テスト関連ファイルを追加するには、TARGETSから

XcodeのUnit Testing Bundle追加画面
↑このUnit Testing Bundleを選んで追加する。
追加されたMyProjectTest.swiftファイルの冒頭で
@testable import MyProject
って追加して、必要なファイルのTarget Membershipをチェックすればこれで動いて欲しいところだが、、、

The file "/Users/…/MyProject/YES" could not be opened. Verify the value of the CODE_SIGN_ENTITLEMENTS build setting for target "MyProjectTests" is correct and that the file exists on disk.

なんてエラーが出てテストコードの実行ができない。
調べたもののよくわからないので最初から追加しててユニットテストができてるプロジェクトと比較するとBuild Settings(テスト用のターゲットね)のSigningのCode Signing EntitlementsってところがYESになってる。動く方は何もなかった。そういやエラーメッセージにもYESってのがあったが、、、

XcodeのCode Signing Entitlementsの画面

ということで手動でこのCode Signing EntitlementsのYESを削除してみたら、期待通りにテストコードが動くようになった。

今度から最初のプロジェクト作成時に追加するようにしようっと。

ちなみにmacOSアプリでの話。



macOS 10.15.3
Xcode 11.3.1



SwiftでInt?をCGFloat?にしたい

Swiftの関数でオプショナル型の整数をもらって、それがnilならnilで、値があるならCGFloatに(つまりCGFloat?に)したい。
func f(_ i: Int?) {
//let cgf = CGFloat(i)//—(1)
//let cgf = i as? CGFloat//—(2)
let cgf = (i != nil) ? CGFloat(i!) : nil//—(3)

}

//(1)はオプショナル型に対してはダメ、という下のようなエラーメッセージが出る。
Cannot invoke initializer for type 'CGFloat' with an argument list of type '(Int?)'

//(2)だとコンパイルは通るけど下のような警告通り機能しない。
Cast from 'Int?' to unrelated type 'CGFloat' always fails

//(3)の三項演算子はちゃんと動くけど、、、見にくいぞ!数ヶ月後に見たら怒りが湧くだろう。

Swiftのことだから何かうまい書き方がありそうなものだけど、よくわからなかった、、、

ということでextensionでなんとかしてみた。
実はオプショナル型のにextensionを書いたのは初めてだ。こんな風に書くのね。
extension Optional where Wrapped == Int {
var toOptCGFloat: CGFloat? {
if self == nil {
return nil
}
return CGFloat(self!)
}
}

こうしておくとさっきのは↓このようにすっきり書ける。
func f(_ i: Int?) {
let cgf = i.toOptCGFloat

}



macOSでFinderなどからtableにドラッグ&ドロップする



↑このようにアプリ外のファイルをNSTableViewオブジェクトにドラッグ&ドロップする。
NSTableViewはNSViewを継承している(※1)のでNSViewからのドラッグ&ドロップと同じでは?と最初は思ったが別な記述が必要になる。

optional func tableView(_ tableView: NSTableView, 
validateDrop info: NSDraggingInfo,
proposedRow row: Int,
proposedDropOperation dropOperation: NSTableView.DropOperation)
-> NSDragOperation
というNSTableViewDataSourceのメソッドでtableにドロップが可能かどうかの判定を行ってたりする。
実際にドロップされたファイル名などはNSTableViewのサブクラスで処理されるので、tableに表示するためdelegateを使ってViewControllerに渡し、tableに表示している。


YamaguchiTatsuya/DragAndDrop_OtherToTable: masOS sample code to drag and drop files from other app to NSTableView object
↑GitHubに置いたサンプルコードはこちら。



※1 NSTableViewの親はNSControlで、その親はNSView



macOS 10.15.2 Catalina
Swift 5.1.3
Xcode 11.3.1



関連記事
macOSでFinderなどからviewにドラッグ&ドロップする
macOSの同一アプリ内で画像などをドラッグ&ドロップする
macOSで同一アプリ内でtableからviewへドラッグ&ドロップする
macOSでFinderなどからtableにドラッグ&ドロップする(当記事)


参考記事
Using Drag and Drop with NSTableView — Nate Thompson
Drag and Drop Tutorial for macOS | raywenderlich.com


macOSで同一アプリ内でtableからviewへドラッグ&ドロップする



↑このようにmacOS内のtableの表示項目(ファイル名とか)をドラッグし、NSViewオブジェクト部分へドロップする。

    func tableView(_ tableView: NSTableView, pasteboardWriterForRow row: Int) 
-> NSPasteboardWriting? {

return imageNames[row] as NSString
}
↑NSTableViewDataSourceのメソッドで何がドラッグ&ドロップされるのかを記述する。

    override func performDragOperation(_ draggingInfo: NSDraggingInfo) 
-> Bool {

let pasteBoard = draggingInfo.draggingPasteboard

let point = convert(draggingInfo.draggingLocation, from: nil)


if let strings = pasteBoard.readObjects(forClasses: [NSString.self],
options: nil) as? [String] {
processImages(strings, center: point)
}
return true
}
↑するとドロップした時点でpaste boardに入ってる先ほど指定した型のオブジェクトを得ることができる。


YamaguchiTatsuya/DragAndDrop_TableToView: masOS sample code to drag and drop files from NSTable to NSView object
↑GitHubに置いたサンプルコードはこちら。



macOS 10.15.2 Catalina
Swift 5.1.3
Xcode 11.3.1



関連記事
macOSでFinderなどからviewにドラッグ&ドロップする
macOSの同一アプリ内で画像などをドラッグ&ドロップする
macOSで同一アプリ内でtableからviewへドラッグ&ドロップする(当記事)
macOSでFinderなどからtableにドラッグ&ドロップする


参考記事
Using Drag and Drop with NSTableView — Nate Thompson
Drag and Drop Tutorial for macOS | raywenderlich.com


macOSの同一アプリ内で画像などをドラッグ&ドロップする



↑このようにNSViewオブジェクトに乗っている別なNSViewオブジェクト(ここでは画像)をマウスで動かしたい。

元々iOSで似たようなことをやってるコードがあったのでmacOS用に移植した。
{
let panGestureRecognizer = NSPanGestureRecognizer(target: self,
action: #selector(self.drawView(recognizer:)))

imageView.addGestureRecognizer(panGestureRecognizer)
}
↑ジェスチャーを設定。

    @objc private func drawView(recognizer: NSPanGestureRecognizer) {

guard let targetView = recognizer.view else {
assertionFailure("targetView is nil")
return
}

let distance = recognizer.translation(in: targetView)

let newCenter = CGPoint(x: targetView.center.x + distance.x,
y: targetView.center.y + distance.y)

targetView.center = newCenter

recognizer.setTranslation(CGPoint(x: 0, y: 0), in: targetView)
}
↑そのジェスチャーを拾う部分。
ほとんどiOSと同じなんだけど、他にmacOSならではのやり方があるのかも?


YamaguchiTatsuya/DragAndDrop_InView: masOS sample code to drag and drop an image in NSView object
↑GitHubに置いたサンプルコードはこちら。



macOS 10.15.2 Catalina
Swift 5.1.3
Xcode 11.3.1



関連記事
macOSでFinderなどからviewにドラッグ&ドロップする
macOSの同一アプリ内で画像などをドラッグ&ドロップする(当記事)
macOSで同一アプリ内でtableからviewへドラッグ&ドロップする
macOSでFinderなどからtableにドラッグ&ドロップする


参考記事
Using Drag and Drop with NSTableView — Nate Thompson
Drag and Drop Tutorial for macOS | raywenderlich.com





Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.