読者です 読者をやめる 読者になる 読者になる

【swift】2.2の変更点(2)

概要

リリースノートをベースに【swift】2.2の変更点を作成しましたが、わかりやすい記事があったので、こちらも紹介します。

++ and -- are deprecated

++、--記法が非奨励になりました。swift 3.0ではエラーになります。

var i = 0
// 非奨励
i++
// 今後はこのように記述します
i += 1
i = i + 1

cスタイルのループ記法が使えなくなります。

for var i = 1; i <= 10; i += 1 {
    print("\(i) green bottles")
}

for in構文を使います。

for i in 1...10 {
    print("\(i) green bottles")
}

for in 構文は、開始値<終了値という制約があります。

for var i = 10; i >= 0; i -= 1 {
}

この場合、以下のように記述します。

for i in (1...10).reverse() {
}

Arrays and other slice types now have removeFirst()

最初の要素を取り出す関数removeFirstが追加されました。removeAtIndex(0)でも同じことができます。

var array = Array(1...10)
array.removeFirst() // 1
array.removeLast() // 10
print(array.count) // 8

ただし、removeFirst/removeLastは要素が存在しない場合には実行時エラーになります。

var array = [Int]()
array.removeFirst() // 実行時エラー

該当の要素がない場合、nilを返す最後の要素を取得する関数popLastがありますが、popFirstは追加されません。

var array = [Int]()
array.popLast() // nil

You can now compare tuples (within reason)

タプルの比較演算子が追加されました。

let singer = ("Taylor", "Swift")
let alien = ("Justin", "Bieber")

if singer == alien {
    print("Matching tuples!")
} else {
    print("Non-matching tuples!")
}

Tuple splat syntax is deprecated

引数をタプルで渡すことが非奨励になりました。

func describePerson(name: String, age: Int) {
    print("\(name) is \(age) years old")
}

let person = ("Taylor Swift", age: 26)
describePerson(person)

More keywords can be used as argument labels

一部のキーワードを引数ラベルとして使えるようになりました。

func printGreeting(name: String, repeat repeatCount: Int) {
    for _ in 0 ..< repeatCount {
        print(name)
    }
}

printGreeting("Taylor", repeat: 5)

var parameters have been deprecated

引数を関数内で変更できるようにするためのキーワードvarが非奨励になりました。値を変更する場合には、別変数を使います。

func printGreeting(var name: String, repeat repeatCount: Int) {
    // 値を変更できる
    name = name.uppercaseString

    for _ in 0 ..< repeatCount {
        print(name)
    }
}

printGreeting("Taylor", repeat: 5)

変数を別途作成します。

func printGreeting(name: String, repeat repeatCount: Int) {
   // 新しい変数に値をセットします。
    let upperName = name.uppercaseString

    for _ in 0 ..< repeatCount {
        print(upperName)
    }
}

printGreeting("Taylor", repeat: 5)

Renamed debug identifiers: #line, #function, #file

swift 2.1以前では、__LINE__や__FUNCTION__のシンボルが行数、関数名に置換されました。2.2移行では、#line, #functionになります。

func printGreeting(name: String, repeat repeatCount: Int) {
    // old - deprecated!
    print("This is on line \(__LINE__) of \(__FUNCTION__)")

    // new - shiny!
    print("This is on line \(#line) of \(#function)")

    let upperName = name.uppercaseString

    for _ in 0 ..< repeatCount {
        print(upperName)
    }
}

printGreeting("Taylor", repeat: 5)

Stringified selectors are deprecated

文字列セレクタが非奨励になりました。

以下の例だと、セレクタを#selector(buttonTapped)と記述します。もし、関数buttonTappedがなければコンパイルエラーになります。

navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Tap!", style: .Plain, target: self, action: "buttonTaped")

Compile-time Swift version checking

コンパイル時にバージョンチェックできるビルドオプションが追加されました。

#if swift(>=2.2)
print("Running Swift 2.2 or later")
#else
print("Running Swift 2.1 or earlier")
#endif

New documentation keywords: recommended, recommendedover, and keyword

swiftはmarkdown形式のドキュメントを書くことができます。

/**
Say hello to a specific person
- parameters:
- name: The name of the person to greet
- returns: Absolutely nothing
- authors:
Paul Hudson
Bilbo Baggins
- bug: This is a deeply dull function
*/
func sayHello(name: String) {
    print("Hello, \(name)!")
}

sayHello("Bob")

Swift 2.2で、3つのキーワードが追加されました。recommended, recommendedover, keyword。 Xcode 7.3では、このキーワードを追加しても何も変わりません。

関連情報

【swift】日付時間処理

概要

swiftで日付時刻の処理を行う場合には、NSDate、NSCalendarクラスを使います。

NSDate, NSDateFormatterを使う方法

書式を使って時間を取得します

日付時刻の書式については、 ここを参照してください。

  // 現在時間を取得
  let now = NSDate()
  let formatter = NSDateFormatter()
  // yyyyMMdd HH:mm:ss
  formatter.dateFormat = "HH"

  // 時間を整数値に変換
  let hour = Int(formatter.stringFromDate(now))
  // 時間に応じて挨拶を変える
  if hour < 12 {
      print("Good Morning!")
  } else  if hour < 18 {
      print("Good Afternoon!")
  } else {
      print("Good Evening!")
  }

日付時刻の文字列フォーマットします

NSDateFormatterにlocaleを設定する、国別のの日付表示を取得できます。

// 2016/3/27の場合
let date = NSDate()
// US English Locale (en_US)
dateFormatter.locale = NSLocale(localeIdentifier: "en_US")
print(dateFormatter.stringFromDate(date)) // My 27, 2016

// French Locale (fr_FR)
dateFormatter.locale = NSLocale(localeIdentifier: "fr_FR")
print(dateFormatter.stringFromDate(date)) // 27 mars 2016

// Japanese Locale (ja_JP)
dateFormatter.locale = NSLocale(localeIdentifier: "ja_JP")
print(dateFormatter.stringFromDate(date)) // 2016/03/27

文字列表現をパーズしてNSDateに変換します

let RFC3339DateFormatter = NSDateFormatter()
RFC3339DateFormatter.locale = NSLocale(localeIdentifier: "ja_JP")
RFC3339DateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
let string = "2016-03-27T16:39:57-08:00"
let date2 = RFC3339DateFormatter.dateFromString(string)
print(date2) // Optional(2016-03-28 00:39:57 +0000)

NSCalendarを使う方法

NSCalendarを使うと、年、月、日、時間、分、秒を個別に取得することができます。

  let now = NSDate()
  let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierJapanese)!
  let hour: NSDateComponents = calendar.components(NSCalendarUnit.Hour, fromDate: now)
  print(hour.hour)

日付計算もできます。が、ちょっと使うのは面倒。

let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)!
let now = NSDate()
let date = calendar.dateByAddingUnit(.Day, value: 1, toDate: now, options: NSCalendarOptions())

参考情報

【swift】2.2の変更点

概要

Swift 2.2がリリースされました。オープンソース化後の最初のアップデートですね。

Xcode 7.3 on Mac OSX Yosemite 10.11.4で(一部)確認しました。

予約後の一部が引き数名として使えるようになりました

SE-0001: Allow (most) keywords as argument labels

// inはOK
func extractWord(prefix: String, in sentence: String) -> Array? {
    return nil
}
// inoutはNG
// シングルクォートで囲む必要がある
func addParameter(name: String, `inout`: Bool) {    
}

既存コードに対する影響はありません。

意味が明確になる変数を使えるメリットはありそうですが、一部のキーワードはNGのままというのが微妙です。

タプルの比較演算子が追加されました

SE-0015: Tuple comparison operators

let t1 = (50, 165)
let t2 = (50, 165)
t1 == t2 // ---> true

let t3 = (weight: 50, height: 165)
let t4 = (height: 165, weight: 50)
t3 == t4 // ---> false

既存コードに対する影響はありません。

要素を先頭から順に比較しています。名前は無視されるので、タプルを比較する場合には演算子オーバーロードする必要はありそうです。

Sequence初期化に制約を追加することができるようになりました

SE-0014: Constraining AnySequence.init

// 変更前
public struct AnySequence : SequenceType {
  public init<
    S: SequenceType
    where
      S.Generator.Element == Element
  >(_ base: S) { ... }
}

// 変更後
public struct AnySequence : SequenceType {
  public init<
    S: SequenceType
    where
      S.Generator.Element == Element,
      S.SubSequence : SequenceType,
      S.SubSequence.Generator.Element == Element,
      S.SubSequence.SubSequence == S.SubSequence
  >(_ base: S) { ... }
}

既存コードに対する影響はありません。

メリットがよくわかりませn。

型宣言に関連したtype aliasをassociatedtypeに置き換えることなりました

protocol中では、新しく導入したキーワードassociatedtypeキーワードを使うようにします。typealiasはコンパイルエラーになります。

SE-0011: Replace typealias keyword with associatedtype for associated type declarations

// ワーニングが出力されるようになります。
protocol Prot {
    associatedtype Container : SequenceType
    typealias Element = Container.Generator.Element // error: cannot declare type alias inside protocol, use protocol extension instead
}

protocol Prot {
    associatedtype Container : SequenceType
}
extension Prot {
    typealias Element = Container.Generator.Element
}

既存コードに対する影響はありません。

Swift3では、typealiasが全面的になくなり意味が明確なキーワード、type, associated, requiredtype, placeholdertypeに置き換わるようです。

typealiasというキーワードがそもそも曖昧だったということですね。Swift3で仕様が変わるようなので多用しない方がよさそうです。

引数ラベルを使った関数ネーミング

SE-0021: Naming Functions with Argument Labels

// 引数が異なる同じ名前の関数がある場合、
extension UIView {
  func insertSubview(view: UIView, at index: Int)
  func insertSubview(view: UIView, aboveSubview siblingSubview: UIView)
  func insertSubview(view: UIView, belowSubview siblingSubview: UIView)
}
// 同じ型の関数を呼び分けるためにはクロージャーを作成する必要がありました。
let fn: (UIView, UIView) = { view, otherView in
  button.insertSubview(view, aboveSubview: otherView)
}
// これが名前付き引数で関数を区別できるようになりました。
let fn = someView.insertSubview(_:at:)
let fn1 = someView.insertSubview(_:aboveSubview:)

既存コードに対する影響はありません。

引き数名で区別しないといけない関数名を作ること自体が良くないような気もするのですが...

Objective-Cセレクタメソッドとして参照できるようになりました

SE-0022: Referencing the Objective-C selector of a method

control.sendAction(#selector(MyApplication.doSomething), to: target, forEvent: event)

extension MyApplication {
  @objc(jumpUpAndDown:)
  func doSomething(sender: AnyObject?) { … }
}

引数ラベルを使った関数ネーミングを使っています。

既存コードに対する影響はありません。

Objective-Cのコードを含むプロジェクトでは便利なのかもしれません。

新しいビルド設定オプションが追加されました

SE-0020: Swift Language Version Build Configuration

#if swift(>=2.2)
  print("Active!") // --> Active!
#else
  this! code! will! not! parse! or! produce! diagnostics!
#endif

既存コードに対する影響はありません。

Cのプリプロセッサに相当するもの。これは便利そうです。

関連情報

【Java】Apache POIを使ったExcelファイル操作

ダウンロード

Apache POIプロジェクトサイトから、poi-bin-3.13-20150929.zipをダウンロードする。解凍後、必要なjarファイルをプロジェクトに追加する。

  • poi-3.13-20150929.jar
  • poi-ooxml-3.13-20150929.jar
  • poi-ooxml-schemas-3.13-20150929.jar
  • xmlbeans-2.6.0.jar

注意

  • poiだけだと、Excel2007より前の形式(拡張子xls)しか扱えない。
  • poi-ooxmlを含めると、XML形式(拡張子xlsx)のExcelファイルも扱える。

エクセル操作

ファイル読み込み・出力

	try (FileInputStream in = new FileInputStream("XXXX.xlsx")) {
		Workbook book = WorkbookFactory.create(in);
		Sheet sheet = book.getSheetAt(0);

		// データ追加

	    // Excelファイル出力
		try (FileOutputStream  out = new FileOutputStream("YYYY.xlsx")) {
			book.write(out);
		}

	} catch (Exception e) {
		// エラー処理
	}

セル操作

  • セルは、Row/Cellという順でアクセスする。
  • Row/Cellは必ずしも存在するわけではないので、アクセスする場合にはnullチェックする。
  • エクセルのデータタイプは、セルに追加するデータ型(Integer, String)に対応する。
セルに値を設定する
		Row row = sheet.getRow(rowIndex);
		if (row != null) {
			Cell cell = row.getCell(colIndex);
			if (cell != null) {
				cell.setCellValue(value);
			}
		}
セルに値を追加する
		Row row = sheet.getRow(rowIndex);
		if (row != null) {
			Cell cell = row.getCell(colIndex);
			if (cell == null) {
				cell = row.createCell(colIndex);
			}
			cell.setCellValue(value);
		}
カラムを削除する

POIには、エクセルのカラムを削除する機能はない。すべてのRowに対してカラムを削除する、カラムのセルを削除する。

    public static void deleteColumn(Sheet sheet, int fromColumn, int toColumn){
        for ( int r = 0; r < sheet.getLastRowNum() + 1; r++ ){
            Row row = sheet.getRow(r);

            if ( row == null ) { continue; }

            int lastColumn = row.getLastCellNum();
            if (lastColumn < fromColumn ) { continue; }
            if (lastColumn < toColumn) { toColumn = lastColumn; }

            for ( int c = fromColumn + 1; c < lastColumn + 1; c++ ){
                Cell cell    = row.getCell(c-1);
                if ( cell != null ) {
                    row.removeCell(cell);
                }
            }
        }
    }
セルに2重罫線を設定する

セルのスタイルプロパティを設定する。 ここで、セルの位置、プロパティはCellUtilクラスで定義されている以下の値を使う。

(CellUtil (POI API Documentation))で定義されているがコメントがないので想像するしかない。

セル位置
  • BORDER_LEFT
  • BORDER_RIGHT
  • BORDER_TOP
  • BORDER_BOTTOM
プロパティ
  • BORDER_NONE
  • BORDER_THIN
  • BORDER_MEDIUM
  • BORDER_DASHED
  • BORDER_DOTTED
  • BORDER_THICK
  • BORDER_DOUBLE
  • BORDER_HAIR
  • BORDER_MEDIUM_DASHED
  • BORDER_DASH_DOT
  • BORDER_MEDIUM_DASH_DOT
  • BORDER_DASH_DOT_DOT
  • BORDER_MEDIUM_DASH_DOT_DOT
  • BORDER_SLANTED_DASH_DOT
    public static void setCellStyle(Sheet sheet, int rowIndex, int colIndex, String pos, short val) {
		Row row = sheet.getRow(rowIndex);
		if (row != null) {
			Cell cell = row.getCell(colIndex);
			if (cell != null) {
				CellUtil.setCellStyleProperty(cell, cell.getSheet().getWorkbook(), pos, val);
			}
		}

    }
セルに背景色を設定する

IndexedColorsクラスに色の定義がある。

IndexedColors (POI API Documentation) 例) 白を指定する場合には、IndexedColors.WHITE.getIndex()を使う。

    public static void setCellColor(Sheet sheet, int rowIndex, int colIndex, short color) {
		Row row = sheet.getRow(rowIndex);
		if (row != null) {
			Cell cell = row.getCell(colIndex);
			if (cell != null) {
				CellStyle style = cell.getCellStyle();
				style.setFillForegroundColor(color);
			}
		}

    }
セルにフォントを設定する

CellUtilを使わない場合、他のセルのフォントも変わってしまうのでCellUtilクラスを使う必要がある。

    public static void setNormalFont(Sheet sheet, int rowIndex, int colIndex) {
    	Font font = sheet.getWorkbook().createFont();
    	font.setBold(false);
    	font.setFontName("MS Pゴシック");
		Row row = sheet.getRow(rowIndex);
		if (row != null) {
			Cell cell = row.getCell(colIndex);
			if (cell != null) {
				CellUtil.setFont(cell, sheet.getWorkbook(), font);
				CellStyle style = cell.getCellStyle();
				style.setFont(font);
			}
		}

    }
セルに設定された値を取得

関連情報

【HTTP】日本語ファイル名でダウンロード

概要

ファイルをダウンロードする場合、HTTPヘッダにファイル名を設定します。

Content-Disposition: attachment; filename=ファイル名

日本語ファイル名にするためには、ファイル名の文字コードとURLエンコードが必要です。

Content-Disposition: attachment; filename*=UTF-8''URLエンコードされたファイル名

詳しくは、RFC 6266を参照してください。

関連情報

【Windows】IPアドレスからホスト名を取得する

概要

Windows OSでは、以下のコマンドでIPアドレスからホスト名を取得することができます。

nbtstat -A IPアドレス

関連情報

javascript関連情報まとめ

概要

javascript関連の情報をまとめ中です。

関連情報

javascript

Javascript言語の情報は、MDNが一番まとまっていると思います。

チュートリアルは、いろいろとあるのでよさそうなものを試すのが良い。

jQuery

DOM APIを使いやすくしたライブラリ。もっとも良く使われているJavascriptライブラリの一つ。

HTML/CSS

Test

現在調査中。