環境:iOS10.1
新しいiPhoneを購入後、WifiのHTTPプロキシ設定を「手動」で行うとしたところ、入力しても保存されず、なぜかオフになってしまう現象が起きた。
どうやら前のiPhoneのバックアップから復元した場合に発生するようだ。
「このネットワーク設定を削除」から設定を一度削除し、パスワードを入力して接続し直したところ、プロキシ設定ができるようになった。
Window -> Devices and Simulators からiPhoneデバイスを選択、identifier
の部分が UDIDになる。
初期表示はシリアル番号
となっているがその辺りをクリックすると表示項目が切り替わり、UDID
が現れる。
シリアル番号
-> UDID
-> ECID
-> 機種ID
の順に切り替わる。
右クリックからコピーできる。
ターミナルから以下コマンドを実行。Xcodeをインストールしていれば使える
$ instruments -s devices
追記:
instruments コマンドがいつの間にか deprecated になっていた。
`instruments` is now deprecated in favor of 'xcrun xctrace' (see `man xctrace` for more information on its replacement)
代わりに以下コマンドを使う。
$ xcrun xctrace list devices
環境:
Swift2.2
iOS8以降対象
いつも設定している Appearance のコピペ用メモ。
以下を AppDelegate で呼ぶ。
mainColor は extension で独自に設定したもの。
private func setupAppearance() { // アプリケーション全体のtintColor設定 self.window?.tintColor = UIColor.mainColor // ステータスバーの文字色を白に。 // プラス`Info.plist`に`View controller-based status bar appearance = NO`を追加 UIApplication.sharedApplication().statusBarStyle = .LightContent // ナビゲーションバーの色 UINavigationBar.appearance().barTintColor = UIColor.mainColor // ナビゲーションバーボタンの色を白に。 UINavigationBar.appearance().tintColor = UIColor.whiteColor() // ナビゲーションバーのタイトル文字色を白に。 UINavigationBar.appearance().titleTextAttributes = [ NSForegroundColorAttributeName: UIColor.whiteColor() ] }
こんな感じに。
環境: Swift2.2
タプルとcaseを組み合わせて使うと便利だったのでメモ。
オプショナル型な複数の値の組み合わせで場合分けしたい場合に使う。
また値はアンラップして取り出して変数にバインドする。
ポイントはcase部分で「?」をつけること。これでオプショナル型でnilでない場合にマッチする。
let num: Int? = ... let str: String? = ... switch(num, str) { case let (num?, str?): // num, strともオプショナル型でnil以外にマッチ // case let (.Some(num), .Some(str)): // これでもよい print("num: \(num), str: \(str)") case (let num?, nil): // numはオプショナル型でnil以外、strはnilにマッチ // case (.Some(let num), nil): // これでもよい print("num: \(num)") case case (nil, _?): // numはnil、strはオプショナル型でnil以外にマッチ // case (nil, .Some(_)): // これでもよい break default: // num、strともにnilにマッチ break }
if let
の代わりにif case let
に使うif case let
でパターンマッチが利用できる。
オプショナルをアンラップして変数にバインド。
これもポイントはcase部分で「?」をつけること。
// a は Optional if case let x? = a { } // 以下と同じ if case .Some(let x) = a { }
そしてタプルを組み合わせて使うと、複数の値を一気にバインドできる。
if let
よりスッキリ書ける気がする。
if let
// a, b, c は Optional if let x = a, let y = b, let z = c { }
if case let
if case let (x?, y?, z?) = (a, b, c) { }
参考:
Swift2のパターンマッチ構文集(ほぼ翻訳) - Qiita
http://qiita.com/mono0926/items/f2875a9eacef53e88122
環境
Mac
MySQL Server version: 5.7.13
位置参照情報ダウンロードサービス
http://nlftp.mlit.go.jp/isj/
今回はこちらから東京都の大字・町丁目レベルのデータをダウンロードする。
13000-09.0b.zip
というファイルがダウンロードされる。
これを解凍すると13_2015.csv
というCSVファイルがあるのでこのデータをMySQLにインポートする。
まず先に文字コードをShift_JISからUTF-8に変換しておく。
nkfコマンドを使おうと思ったがMacには入っていなかったのでhomebrewでインストールした。
$ brew install nkf
UTF-8に変換
$ nkf -w 13_2015.csv > 13_2015_utf8.csv
中身を確認してみる。
$ head 13_2015_utf8.csv "都道府県コード","都道府県名","市区町村コード","市区町村名","大字町丁目コード","大字町丁目名","緯度","経度","原典資料コード","大字・字・丁目区分コード" "13","東京都","13101","千代田区","131010001001","一ツ橋一丁目","35.691634","139.756685","1","3" "13","東京都","13101","千代田区","131010001002","一ツ橋二丁目","35.692947","139.757320","1","3" "13","東京都","13101","千代田区","131010002000","一番町","35.687723","139.739668","1","1" "13","東京都","13101","千代田区","131010003001","永田町一丁目","35.676328","139.745749","1","3" "13","東京都","13101","千代田区","131010003002","永田町二丁目","35.675705","139.740497","1","3" "13","東京都","13101","千代田区","131010004001","猿楽町一丁目","35.698471","139.759949","1","3" "13","東京都","13101","千代田区","131010004002","猿楽町二丁目","35.700021","139.758377","1","3" "13","東京都","13101","千代田区","131010005001","霞が関一丁目","35.674720","139.753419","1","3" "13","東京都","13101","千代田区","131010005002","霞が関二丁目","35.675706","139.750734","1","3"
10列の項目があるが今回は使いたいのは名称と緯度経度のみなのでそれだけ入れるテーブルを用意する。
名称はすべて連結しname
カラムへ、緯度経度はPointにしてgeometry型のlatlon
カラムに突っ込む。
-- MySQLにログイン $ mysql -uroot -- 適当なDBを作成 mysql> create database geo; mysql> use geo; -- テーブル作成 mysql> CREATE TABLE `spots` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `latlon` geometry NOT NULL, PRIMARY KEY (`id`), SPATIAL KEY `index_spots_on_latlon` (`latlon`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
※注 MySQL5.7.5以降でInnoDBでもSPATIALインデックスが使えるようになった。
そして、LOAD DATA INFILEコマンドでCSVデータをインポートする。
LOAD DATA INFILE '/path/to/13_2015_utf8.csv' REPLACE INTO TABLE geo.spots FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\r\n' STARTING BY '' IGNORE 1 LINES (@dummy, @prefecture, @dummy, @city, @dummy, @area, @lat, @lon, @dummy, @dummy) SET name = CONCAT(@prefecture, @city, @area), latlon = ST_GeomFromText(CONCAT('POINT(', @lon, ' ', @lat, ')')); Query OK, 5666 rows affected (0.20 sec) Records: 5666 Deleted: 0 Skipped: 0 Warnings: 0
データを確認してみる。
mysql> SELECT id, name, ST_AsText(latlon) FROM spots limit 10; +----+-----------------------------------------+-----------------------------+ | id | name | ST_AsText(latlon) | +----+-----------------------------------------+-----------------------------+ | 1 | 東京都千代田区一ツ橋一丁目 | POINT(139.756685 35.691634) | | 2 | 東京都千代田区一ツ橋二丁目 | POINT(139.75732 35.692947) | | 3 | 東京都千代田区一番町 | POINT(139.739668 35.687723) | | 4 | 東京都千代田区永田町一丁目 | POINT(139.745749 35.676328) | | 5 | 東京都千代田区永田町二丁目 | POINT(139.740497 35.675705) | | 6 | 東京都千代田区猿楽町一丁目 | POINT(139.759949 35.698471) | | 7 | 東京都千代田区猿楽町二丁目 | POINT(139.758377 35.700021) | | 8 | 東京都千代田区霞が関一丁目 | POINT(139.753419 35.67472) | | 9 | 東京都千代田区霞が関二丁目 | POINT(139.750734 35.675706) | | 10 | 東京都千代田区霞が関三丁目 | POINT(139.748265 35.671608) | +----+-----------------------------------------+-----------------------------+ 10 rows in set (0.00 sec)
※注 STプレフィックスが付く空間用関数はMySQL5.6以降、追加されていっているもの。
CSVデータの中身は何もいじらずにサクッとできた。LOAD DATA INFILE 便利!
参考:
MySQL :: MySQL 5.6 リファレンスマニュアル :: 13.2.6 LOAD DATA INFILE 構文
https://dev.mysql.com/doc/refman/5.6/ja/load-data.html
シミュレータでは表示されるが、実機だと表示されない。
バグらしい、とりあえず自分の場合は iPhone 側の再起動で表示されるようになった。
Launch Storyboard not showing image when projec... | Apple Developer Forums
https://forums.developer.apple.com/message/131986
Launchscreen storyboard doesn't display image | Apple Developer Forums
https://forums.developer.apple.com/thread/17146
環境: swift2.2 Xcode7.3.1
Swiftで以下のようなDEBUG Macroを使いたい。
#if DEBUG print("DEBUG") #elseif STAGING print("STAGING") #else print("ELSE") #endif
Objective-C の場合はPreprocessor Macros
に設定していたが Swift ではOther Swift Flags
の方に設定する必要がある。
PROJECT or TARGETS -> Build Settings -> Swift Compiler - Custom Flags -> Other Swift Flags から対象の Configuration に-D DEBUG
を追加することでフラグとして利用できるようになる。
後は実行する TARGET の Scheme の Build Configuration が合っていればOK。
以上。
ついでに Configuration の追加だが PROJECT -> Info -> Configurations から行う。
環境:swift2.1
NSUserDefaults
にオブジェクトのまま保存したかったが、保存できるオブジェクトはNSArray
, NSDictionary
, NSString
, NSNumber
, NSDate
,NSData
に限られていた。
調べたところ、オブジェクトをNSData
に変換できることがわかった。
NSData
にできればNSUserDefaults
にも保存できる。
実装方法
NSCoding
プロトコルのデコードメソッドinit?(coder aDecoder: NSCoder)
とエンコードメソッドencodeWithCoder(aCoder: NSCoder)
を実装するNSKeyedArchiver.archivedDataWithRootObject:
でオブジェクトをNSData
に変換NSKeyedUnarchiver.unarchiveObjectWithData:
でNSData
からオブジェクトに変換以下サンプルコード
struct UserDefaultsKey { static let User = "user" } struct SerializedKey { static let UserId = "userId" static let Uuid = "uuid" static let NickName = "nickName" } class User: NSObject, NSCoding { var userId: Int var uuid: String var nickName: String? init(userId: Int, uuid: String, nickName: String? = nil) { self.userId = userId self.uuid = uuid self.nickName = nickName } required init?(coder aDecoder: NSCoder) { self.userId = aDecoder.decodeObjectForKey(SerializedKey.UserId) as? Int ?? 0 self.uuid = aDecoder.decodeObjectForKey(SerializedKey.Uuid) as? String ?? "" self.nickName = aDecoder.decodeObjectForKey(SerializedKey.NickName) as? String } func encodeWithCoder(aCoder: NSCoder) { aCoder.encodeObject(self.userId, forKey: SerializedKey.UserId) aCoder.encodeObject(self.uuid, forKey: SerializedKey.Uuid) aCoder.encodeObject(self.nickName, forKey: SerializedKey.NickName) } } class UserService { static let sharedInstance = UserService() private let userDefaults = NSUserDefaults.standardUserDefaults() func register(userId userId: Int, uuid: String, nickName: String? = nil) { let archivedObject = NSKeyedArchiver.archivedDataWithRootObject(User(userId: userId, uuid: uuid, nickName: nickName)) self.userDefaults.setObject(archivedObject, forKey: UserDefaultsKey.User) self.userDefaults.synchronize() } var registeredUser: User? { guard let unarchivedObject = self.userDefaults.objectForKey(UserDefaultsKey.User) as? NSData, let user = NSKeyedUnarchiver.unarchiveObjectWithData(unarchivedObject) as? User else { return nil } return user } }
使用時
// 保存 UserService.sharedInstance.register(userId: 1, uuid: "xxxxx") // 取得 let user = UserService.sharedInstance.registeredUser
この方法でNSData
にすればシリアライズ・デシリアライズできるのでNSUserDefaults
ではなくファイルとしても保存できる。
参考:
iOS でオブジェクトをシリアライズしてファイルに保存する方法 - A Day In The Life
http://glassonion.hatenablog.com/entry/20110904/1315145330
環境:Swift2.1
UIImage と UILabel を合成する方法について。
UIImage をセットした UIImageView を作成、そしてそれに UILabel を addSubview する。
UIImageView(UIView) が持つ CALayer プロパティのrenderInContext
メソッドでグラフィックコンテキストに描画する。
グラフィックコンテキストから描画した画像を取得する。
以下、サンプルコード。UIImage は前回記事のcolorImage
メソッドを使って作成している。
let yellowImage = UIImage.colorImage(color: UIColor.yellowColor(), size: CGSize(width: 100, height: 100)) let yellowImageView = UIImageView(image: yellowImage) let myLabel = UILabel(frame: CGRect(x: 10, y: 10, width: 80, height: 17)) myLabel.text = "Hello!" myLabel.backgroundColor = UIColor.greenColor() myLabel.textAlignment = .Center yellowImageView.addSubview(myLabel) UIGraphicsBeginImageContextWithOptions(yellowImageView.frame.size, false, UIScreen.mainScreen().scale) if let context = UIGraphicsGetCurrentContext() { yellowImageView.layer.renderInContext(context) let newYellowImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() let newYellowImageView = UIImageView(image: newYellowImage) }
Playground での実行結果
指定した UIColor の単色で塗りつぶした UIImage を生成したい。
※ 追記済み
iOS10.0 から追加された UIGraphicsImageRenderer
を使用する。
extension UIColor { func image(size: CGSize) -> UIImage { return UIGraphicsImageRenderer(size: size).image { rendererContext in self.setFill() // 色を指定 rendererContext.fill(.init(origin: .zero, size: size)) // 塗りつぶす } } }
使用時
let redImage = UIColor.red.image(size: .init(width: 50, height: 50))
extension UIImage { convenience init?(color: UIColor, size: CGSize) { guard let cgImage = UIGraphicsImageRenderer(size: size).image(actions: { rendererContext in rendererContext.cgContext.setFillColor(color.cgColor) // 色を指定 rendererContext.fill(.init(origin: .zero, size: size)) // 塗りつぶす }).cgImage else { return nil } self.init(cgImage: cgImage) } }
使用時
// Optional let blueImage = UIImage(color: .blue, size: .init(width: 50, height: 50))
UIImage の Extension に追加。
extension UIImage { static func image(color: UIColor, size: CGSize) -> UIImage { UIGraphicsBeginImageContextWithOptions(size, false, 0.0) let context = UIGraphicsGetCurrentContext()! context.setFillColor(color.cgColor) context.fill(CGRect(origin: .zero, size: size)) let image = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext() return image } }
使用時
let greenImage = UIImage.image(color: .green, size: CGSize(width: 50, height: 50))
UIImage の Extension に追加。
import UIKit extension UIImage { static func image(color color: UIColor, size: CGSize) -> UIImage { UIGraphicsBeginImageContext(size) let context = UIGraphicsGetCurrentContext() CGContextSetFillColorWithColor(context, color.CGColor) CGContextFillRect(context, CGRect(origin: CGPointZero, size: size)) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return image } }
使用時
let greenImage = UIImage.image(color: UIColor.greenColor(), size: CGSize(width: 50, height: 50))