2017年11月06日

Fall 2017 | Session 201 | Building Apps for iPhone X

https://developer.apple.com/videos/play/fall2017/201/
13:35

いよいよiPhone Xが発売されましたが、iPhone X対応アプリを実装するためのビデオが公開されていました。Fall 2017と題する短いビデオクリップ集。

このセッションではiPhone X対応するために必要なコード等の修正点を簡潔に伝えています。一応iOS 11対応という形でiOS 11で導入されたAPIですがすべてiPhone Xでセンサーカメラ部分が導入されたり、コントロールセンサーが代わったりしたことに対応する方法。

WWDCアプリを例に示している。

□Auto Layout

Auto Layoutを使っていれば自動的にiPhone Xのレイアウトに対応可能。

新たに導入された Safe Area に注意する必要がある。スクリーンの表示エリアとコントロールを配置してよいエリアに違いがある。Safe Area外に追加すると、コントロールセンターの操作と競合することになる。XibファイルでレイアウトするときにSuperview に接続するのではなく、Safe Area に接続する。

□サーチコントローラー(Swift)

サーチコントロールをテーブルビューで使う場合、サーチコントロールを生成して親コントローラー上でpresent()するだけでよかった。バックグラウンドカラーが違ったり、ランドスケープモードでクリッピングエリアがコントロールを隠したりすることになる。

iOS11では(iPhone Xに対応するためには)navigationItem に追加する必要がある(コードは6:40あたり)。


let serchController = UISerchController(serchResultsController: nil)
serchController.serchResultsUpdater = self
serchController.obscuresBackgroundDuringPresentation = false
serchController.serchBar.text = serchText

if #available(iOS 11.0, *) {
self.navigationItem.serchController = searController
serchController.isActive = true
} else {
present(searchController, animated: true, copletion: nil )
}



□テーブルビューのヘッダのサーチフール度(Objective-C)

if (@available(iOS 11.0, *) {
self.navigationItem.serchController = self.serchController;
self.navigationItem.serchController.active = showSearchBar;
} else {
if ( _showSerchBar ) {
self.tableView.tableHeader =
self.serchController.searchBar;
} else {
self.tableView.tableHeaderView = nil;
}
}



□テーブルビューのセル

テーブルセル内のContent Viewはデフォルトで Safe Area 内に配置されるが、Xib の「Content View Insets To Safe Area」をチェックをはずすとSafe Area外まで表示させることができる。

また「Use Safe Area Layout Guides」をチェックする。

□Summary

iOS 11 SDKを使う。Launch Storyboardを使う。
縦横両方のレイアウトでテストする。
Safe Areas に気を付ける
・safeAreaLayoutGuide for Auto Layout
・safeAreaInsets for manual calculations
posted by 永遠製作所 at 23:12| 東京 ☀| Comment(0) | WWDC | このブログの読者になる | 更新情報をチェックする

2017年06月09日

WWDC17 | Session 201 | What's New in Cocoa Touch

WWDC17 | Session 201 | What's New in Cocoa Touch
40:25

https://developer.apple.com/videos/play/wwdc2017/201/

Cocoa touchで新たに導入された機能などの概要。詳細は別セッションで。

■新機能

□ドラッグアンドドロップ
・ドラッグするビューに UIDragInteraction を追加する。
・受け入れるビューに UIDropInteraction を追加する。
・始めからサポートされているビュー:
TableView, CollectionView, TextView, TextField, WebView
・UIPasteConfiguration

□ファイル管理

・UIDocumentBrowserViewControllerを使う。
・ローカルファイルやネットワークファイルにもアクセスできる。
・複数のアプリが同じファイルにアクセスするのでアクセス管理が必要。
・そのために NSFileCoordinator や UIDocument を使うと良い。

■UIの変更

□Large Title

ナビゲーションバーのトップのタイトルを大きくする。検索フィールドとの一体化。メインのビューをスクロールしたときに自動的に縮小する。読み込み中のスピン表示も一体化。

class UINviationBar {
var prefersLargeTitle: Bool
}

class UINavigationItem {
var largeTitleDisplayMode: LargeTitleDisplayMode
var serchController: UISerchController?
}


上下のエリアが可変になったのでそこを調整する必要がある。
class UIView {
var safeAreaLayoutGuide: UILayoutGuid: { get }
var safeAreaInsets: UIEdgeInsets { get }
func safeAreaInsetsDidChange()
}

class UIScrollView {
var contentInsetAdjustmentBehaviro: UIScrollViewContntInsetAdjustmentBehavior
var adjustedContentInset: UIDegeInsets { get }
}


□Swipe Actions

・テーブルビューのスワイプ時の機能をカスタマイズできるようになった。

UISwipeActionsConfiguration
UIContetxualAction

class UITableView {
var separatorInsetReference: UITableViewSeparatorInsetReference
}


■API変更

□Swift 4

・enum, struct を Codable にする。NSCoding, JSON, Porperty lists
・\記法でのキーパス表記が可能になった。
・KVO

□画面上部からのノーティフィケーションセンター、下部からのコントロールセンター表示

class UIViewController {
func preferredScreenEdgesDeferringSystemGestures() -> UIRectEdge
}


□Auto Layout and Scroll View

class UIScrollView {
var contentLayoutGuide: UILayoutGuide { get }
var frameLayoutGuide: UILayoutGuide { get }
}


centerXAnchor

□Dynamic Type

カスタムフォントへの対応
ラインスペースへの対応
Visual Fromatting Language への対応

□Password 自動入力
□アセットカタログ

・UIColor を名前で作成
・PDFベースの画像

□可変リフレッシュレート
□ローカリゼーション

RL表記言語へのUIの対応
ラベル:WWDC UIKit iOS11
posted by 永遠製作所 at 15:26| 東京 ☀| Comment(0) | TrackBack(0) | WWDC | このブログの読者になる | 更新情報をチェックする

2017年04月10日

[Mac,Swift2]NSTableViewでソートする

NSTableViewで列を指定して並べ替える方法は、Objective-Cでは簡単に実装することができた。NSArray/NSMutableArrayがNSSortDescriptorを使うメソッドを以て致し、NSArrayが保持しているオブジェクトがNSObjectを親クラスに持っていればkey-value対応により適切に応答してくれた。Mac/iOSのObjective-Cでは全てのオブジェクトはNSObjectを親クラスに持つ。

例えばこんな感じ。


- (void)tableView:(NSTableView *) aTableView
sortDescriptorsDidChange:(NSArray *) oldDescriptors
{
[mainList sortUsingDescriptors:[mainListView sortDescriptors]];
[mainListView reloadData];
}


※ここでは以下のようなインスタンス変数の宣言がされているとする。

IBOutlet NSTableView *mainListView;
NSMutableArray *mainList;


ところが、Swiftの配列はNSSortDescriptorを引数に持つメソッドがない。ということは自分で実装しなければならない。

続きを読む
posted by 永遠製作所 at 00:58| 東京 ☁| Comment(0) | TrackBack(0) | Swift | このブログの読者になる | 更新情報をチェックする

2017年03月21日

[Swift2]NSCalendarUnitの合成


NSDateから年・月・日などの数字だけを抜き出すときにNSDateComonentsを使うんだけど、Swiftでちょっと書き方が変わった部分がある。

Objective-C時代はこんな書き方でした。リファレンスからの抜粋。


unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDate *date = [NSDate date];
NSDateComponents *comps = [gregorian components:unitFlags fromDate:date];


これがSiwft2では以下のようになるとリファレンスには書かれている。これだとObjective-Cとさほど代わりはない。


let flags: NSCalendarUnit = .DayCalendarUnit | .MonthCalendarUnit | .YearCalendarUnit
let date = NSDate()
let components = gregorian.components(flags, fromDate: date)


ところがこれを Xcode 7.2.1 で書くと、エラーになってしまってコンパイルできない。


Type of expression is ambiguous without more context


型が分からないというなら直接的に指定するしかないと指定する。


let flags2: NSCalendarUnit = NSCalendarUnit.Day | NSCalendarUnit.Month | NSCalendarUnit.Year


が、するとまた別のエラーになる。


Binary operator '|' cannot be applied to two 'NSCalendarUnit' operands'



じゃあ、一体どう指定するんだよ?と強引に指定するとこんな風になる。


let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
let flags = NSCalendarUnit(rawValue: NSCalendarUnit.Year.rawValue
+ NSCalendarUnit.Month.rawValue
+ NSCalendarUnit.Day.rawValue
)
guard let comps = calendar?.components(flags, fromDate: date) else {
return
}
let year = comps.year, month = comps.month, day = comps.day


確かにこれだと正常に実行できるんだけど、あまりにも強引すぎてもっときれいな書き方があっていいはずなんだけど。

Swift3ではこんな書き方になる(クラス名等はSwift2のまま)。


let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
guard let comps = calendar?.components([.Year,.Month,.Day], fromDate: date) else {
return
}


そしてこれがまたコンパイルが通って正常に実行される。Swift3ではメソッドがSetで定義されているのでこれでもいいのだが、Swift2ではcomponents(flags:NSCalendarUnit, fromDate: NSDate)とNSCalendarUnitで定義されているので[NSCalendarUnit]で渡して渡せる理由がわからない。

そこでこんな書き方をしてみたら、ようやくなぜだかわかった。


let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
let flags = NSCalendarUnit([.Year,.Month,.Day])
guard let comps = calendar?.components(flags, fromDate: date) else {
return
}


リファレンスとかからはわからないけどNSCalendarUnitのコンストラクタに配列を取るものがあるってことなんでしょう。

posted by 永遠製作所 at 15:16| 東京 ☔| Comment(0) | TrackBack(0) | Swift | このブログの読者になる | 更新情報をチェックする

2017年03月20日

[macOS, Swift2] ファイル選択ダイアログ

未だに古い環境のOS Xでプログラミングしてるんだけど、その中の基本的な操作であるファイルオープンダイアログの使い方を一応覚え書きとして。

NSOpenPanelはObjective-C時代そのまま。インスタンスはそのままコンストラクタで作る。シートでダイアログを開いて、結果はブロックで受け取る。OK/Cancelは NSFileHandlingPanelOKButton / NSFileHandlingPanelCancelButton で判定。

以下はNSViewControllerのサブクラス中で使う場合。


func showOpenPanel() {
let panel = NSOpenPanel()
panel.beginSheetModalForWindow(self.view.window!) {
[weak self] (response) -> Void in

switch ( response ) {
case NSFileHandlingPanelOKButton:
let urls = panel.URLs
self?.readFromURL(urls[0])
break
default:
return
}
}
}


シートを表示している最中だからselfがなくなることはないと思うけど、一応ブロック中でselfを使う場合は習慣化させたいので weak self 。

ファイルを1つだけ選択する場合。NSURLで受け取るのが現代的。複数選択する場合やディレクトリ可の場合には beginSheet... の前に下記コードを入れておくだけ。


self.allowsMultipleSelection = true
self.canChooseDirectories = true


ラベル:Swift MacOS NSOpenPanel
posted by 永遠製作所 at 00:07| 東京 ☀| Comment(0) | TrackBack(0) | Swift | このブログの読者になる | 更新情報をチェックする