カテゴリー
SugiBlog ホームページ制作・システム開発|大阪

座標から住所に変換する 逆ジオコーディング

緯度経度の座標から逆ジオコーディング(リバースジオコーディング)で住所を取得することができます。
これにはGoogleのAPIを利用しますので、GoogleMapsをインポートしている前提でのお話です。

座標をGoogleMapから取得します。
例えばタップであればcoordinate: CLLocationCoordinate2Dが取得できますので
これを元にCLLocationオブジェクトを作成します。

let location: CLLocation = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)

逆ジオコーディングを行うメソッド
結果をアラートで表示しています。

func ReverseGeocoder(location: CLLocation) {

    var address: String = ""

    CLGeocoder().reverseGeocodeLocation(location, completionHandler: {(placemarks, error)->Void in

        if error != nil {
            print("error")
            return
        }

        if placemarks!.count > 0 {
            let pms = placemarks![0]
            address = self.makeAddressString(placemark: pms)

            let aTitle = "住所表示"
            let aMessage = address
            let alert = UIAlertController(title: aTitle, message: aMessage, preferredStyle: .alert)

            alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))

            self.present(alert, animated: false, completion: nil)

        } else {

            print("error")

        }

    })

}

取得できた住所を一連の文字列に変換するメソッド

func makeAddressString(placemark: CLPlacemark) -> String {

    var address: String = ""

    //address += placemark.postalCode != nil ? placemark.postalCode! : ""
    address += placemark.administrativeArea != nil ? placemark.administrativeArea! : ""
    address += placemark.subAdministrativeArea != nil ? placemark.subAdministrativeArea! : ""
    address += placemark.locality != nil ? placemark.locality! : ""
    address += placemark.subLocality != nil ? placemark.subLocality! : ""
    address += placemark.thoroughfare != nil ? placemark.thoroughfare! : ""
    address += placemark.subThoroughfare != nil ? placemark.subThoroughfare! : ""

    return address

}

Xcode: 8.3.2
Swift: 3.1
OS: Sierra 10.12

1,967 views

アラートを表示する UIAlertController

アラートを表示するにはUIAlertControllerを利用します。

アラート(ダイアログ)を表示する

タイトルとメッセージを設定し、アラートのオブジェクトを作成します。

let aTitle = "タイトル"
let aMessage = "メッセージ表示"

let alert = UIAlertController(title: aTitle, message: aMessage, preferredStyle: .alert)

OKボタンを作成します。

alert.addAction(
    UIAlertAction(title: "OK", style: .default, handler: { action in
        print("OKをタップした場合の処理")
    })
)

キャンセルボタンを作成します。
処理は何もしないので、handlerはnilで大丈夫です。

alert.addAction(UIAlertAction(title: "キャンセル", style: .cancel, handler: nil))

アラートを表示する

self.present(alert, animated: false, completion: nil)

続きを読む…»

1,652 views

複数のStoryboardを使った画面遷移

アプリ開発をしていく中で様々な画面を作成していくと、Storyboardが複雑化してしまいます。
そこで、シーンをグループ分けしStoryboardを分割することで開発が楽になります。

今回は別のStoryboardのシーンへ遷移させる方法をご紹介します。

新規ファイルでStoryboardを追加します。

通常はMain.storyboardがありますので、Sub.storyboardを作成します。

ViewControllerを追加し、Storyboard IDを設定します。

仮に「sub_exam」としておきます。

あとは遷移したいところに以下のコードを追加するだけです。

let SubStoryboard: UIStoryboard = UIStoryboard(name: "Sub", bundle: nil)
let subExam: UIViewController = SubStoryboard.instantiateViewController(withIdentifier: "sub_exam")
show(subExam, sender: nil)

Sub.storyboardのViewControllerをイニシャルビューとしている場合は以下のようになります。

let subExam: UIViewController = SubStoryboard.instantiateInitialViewController() as! UIViewController

続きを読む…»

2,706 views

カメラで写真を撮影する AVFoundation

今回はシステムのカメラUIImagePickerControllerではなくAVFoundationフレームワークを
使った方法をご紹介します。
簡単に実装するならUIImagePickerControllerが楽ですが、AVFoundationのほうが柔軟なアプリの作成が可能になります。

ネット上でも様々な情報がありますが、今回の肝になるのがデバイスの向きと
撮影した写真の向きの問題です。
例えば、iPhoneのみ対応のアプリで縦画面(portrait)に完全固定であれば
そう難しくないのですが、私が作ろうとしていたのが、iPhoneでは縦固定、iPadでは横固定で、
且つNavigationControllerを使用していたため、結構頭を悩ませました。

NavigationControllerを使っていると、カメラのシーンだけ縦に固定することができないのです。
通常はViewControllerに対してshouldAutorotateをoverrideすれば特定のシーンのみ
固定することが可能なのですが、NavigationControllerを使用している場合、
ViewControllerはNavigationControllerに包括されているのでViewControllerのshouldAutorotateをoverrideしても効果がないのです。
そしてその場合はNavigationControllerのshouldAutorotateをoverrideすることになりますが、
そうしてしまうと包括されている全てのシーンに適用されてしまいます。

また、iPhoneのみ対応で縦画面固定だったとしても、適切に処理していないと、
“最初から端末を横にして”カメラを起動すると写真が横にならないという事態になってしまいます。
これは私が参考にさせて頂いた書籍でもそこまでは対応していませんでした。

今回、意識するポイントとしては2種類、それぞれ3つあります。

まず1つ目

  • デバイスの向き
  • プレビューの向き
  • 保存時の出力の向き

これはiPhoneでは縦、iPadでは横とする場合のポイントです。

次に2つ目

  • インターフェースの向き
  • プレビューの向き
  • レイヤーの向き

これは画面の回転に対応する場合に気を付けるポイントです。

それでは、以上を踏まえた上で先に進みましょう。
まずはiPhoneでは縦固定、iPadでは横固定の場合で作成します。

カメラ利用の許可

まずはカメラを利用するためInfo.plistにカメラの利用許可を追加します。
また、写真を撮影するということは保存するためにフォトライブラリーにアクセスしますので、
そちらも一緒に追加します。

Privacy - Camera Usage Description
Privacy - Photo Library Usage Description

Valueには「写真を撮影します。」「写真を保存します。」等と設定します。
続きを読む…»

3,991 views

カメラで写真を撮影する UIImagePickerController

システムのカメラ機能を使って写真を撮影します。
特に考えることなく、簡単に実装できますので試してみてください。

簡単に実装できますが、カスタマイズすることができないので、
カスタマイズしたい方はAVFoundationを利用してください。

カメラ利用の許可

まずはカメラを利用するためInfo.plistにカメラの利用許可を追加します。
また、写真を撮影するということは保存するためにフォトライブラリーにアクセスしますので、そちらも一緒に追加します。

Privacy - Camera Usage Description
Privacy - Photo Library Usage Description

Valueには「写真を撮影します。」「写真を保存します。」等と設定します。

デリゲート

UIImagePickerControllerDelegateとUINavigationControllerDelegateを設定します。
後者が必要なのはUIImagePickerControllerの親クラスがUINavigationControllerのためです。

class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {

Viewの配置

StoryBoardでViewControllerにViewと、カメラ起動と保存ボタンの2つのButtonを配置します。

配置したViewを「previewView」としてOutlet接続します。

@IBOutlet weak var previewView: UIView!

続きを読む…»

1,149 views

ブラウザで指定したURLを開く

外部ブラウザ(Safari)で指定したURLを開く方法のご紹介です。

URLを指定します。

let url = URL(string: "http://~")

ブラウザを起動

UIApplication.shared.open(url!)

サードパーティ製ブラウザで開く場合は、URLスキームを変えてやる必要があります。
※現状での動作は確認していますが、各アプリの変更によってスキームが変更になる可能性はあります。

Google Chromeの場合
こちらの場合、httpは省きます。

let url = URL(string: "googlechrome://~")

Firefoxの場合

let url = URL(string: "firefox://open-url?url=http://~")

Operaの場合

let url = URL(string: "opera-http://~")

Xcode: 8.3.2
Swift: 3.1
OS: Sierra 10.12

2,148 views

WEBから取得したJSONデータを解析しRealmに取り込む

何やらタイトルが長くなってしまいましたが、複合的な内容なのでこうなりました。
今回やりたかったことはタイトルの通りですが、分解すると…
1)WEBからデータをダウンロード
2)バックグラウンドで処理を実行
3)JSONデータを解析
4)解析したデータをRealmに挿入
以上の4つです。

エラーが出なくなるまでかなり苦労したのですが、一番の原因は日本語の扱いに関する部分ですので、
日本語を含まないデータの解析だけならすんなり可能ではないかと思います。

1)WEBからデータをダウンロード

WEBからデータをダウンロードするにはURLSessionを使います。

ダウンロードするURLを指定

let url: String = "http://www.exam.jp/json.php"

セッションを作成します。

let session = URLSession(configuration: URLSessionConfiguration.default)

タスクを登録します。

let task = session.dataTask(with: URLRequest(url: Foundation.URL(string: url)!), completionHandler: {
    (data, response, error) in

    if let urlContent = data {
        // ここに処理を記述
    }

})

作成したタスクを実行します。

task.resume()

2)バックグラウンドで処理を実行

バックグラウンドで処理を実行するには、GCD(Grand Central Dispatch)を使用します。

DispatchQueue.global().async {
    // バックグラウンドスレッドでの処理を記述
}

asyncだと非同期処理、syncだと同期処理になります。
続きを読む…»

1,393 views

Navigation Controllerを非表示で使う

Navigation Controllerは非常に便利ですね。
でも画面構成的にどうしても上部に表示されるナビゲーションバーを非表示にしたいことがあります。

ドキュメントアウトラインの[Navigation Controller Scene]-[Navigation Controller]-[Navigation Bar]を選択し、Attributes inspectorを開きます。
Drawingのところの「Hidden」にチェックを入れます。

これだけだと、ナビゲーションバーは非表示になりましたが、上部に隙間が出来る場合があります。
そんなときはviewDidLoadに次のコードを記述すれば解決できます。

self.automaticallyAdjustsScrollViewInsets = false

Navigation ControllerにもAttributes inspectorを開けば、Bar Visibilityのところに「Shows Navigation Bar」のチェックがあり、こちらを外せば非表示にはなるのですが、画面左端からスワイプしても戻れなくなりました。

Xcode: 8.3.1
Swift: 3.1
OS: Sierra 10.12

1,338 views

前の画面に戻る unwind segue

複数のシーンを作成し、移動するアプリを制作する際、Androidのように戻るボタンがありませんので、その辺もきちんと実装しておく必要があります。
NavigationControllerを使えば簡単なのですが、今日はそれを使わない場合の方法をご紹介します。

遷移元のViewControllerに以下のコードを追加します。

@IBAction func unwindMe(segue: UIStoryBoardSegue) {
}

中身は何もなくて構いません。

次に遷移先のViewControllerに戻るボタンを配置します。
配置したボタンをControlを押しながらExitに結び付けます。

これだけで遷移元のViewControllerに戻ることができます。

また、コードで実行したい時は、ドキュメントアウトラインでExitの下に追加されたUnwind segue…を選択し、Identifierを設定します。

ここでは「backToMain」とします。

後は以下のコードを実行します。

performSegue(withIdentifier: "backToMain", sender: self)

ちなみに、最初のコードを以下のようにすれば、どの遷移先から戻ってきたかによって処理を分岐できるようです。

@IBAction func unwindMe(segue: UIStoryBoardSegue) {
    if segue.identifier == "backToMain" {
        //....何らかの処理
    }
}

Xcode: 8.3.1
Swift: 3.1
OS: Sierra 10.12

3,926 views

iPhoneやiPadでメールの送信ができない

iPhoneやiPadで自社のメールを送受信したい、といった場合に
受信はできるけど送信だけがなぜかできない…という問題に遭遇したので
備忘録としてメモしておきます。

これは、自社のメールサーバーが「POP before SMTP」を採用している
場合に起こるようです。

SMTP設定のプライマリサーバに、ホスト名・ユーザー名・パスワード等、
全ての情報を入力して登録すると送信ができません。
「POP before SMTP」で運用しているメールサーバーでメールを送信するためには
上記のうち、ユーザー名・パスワードは空にする必要があります。

認証は受信の作業で行っているので、送信の際にはユーザー名等が必要ないということですね。

image1

903 views