2017年1月19日木曜日
webから取得したデータをtableViewに表示
//
// ViewController.swift
//
//
import UIKit
class ViewController: UIViewController ,UITableViewDataSource{
// リスト
var dataList : [(id:String, name:String)] = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// データを取得する
getUriData()
tableView.dataSource = self // 追加
}
@IBOutlet weak var tableView: UITableView!
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// データソースメソッドを追加
func tableView(tableView:UITableView, numberOfRowsInSection sectioin: Int)-> Int{
return dataList.count
}
// Cellに値を設定する
func tableView(tableView:UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCellWithIdentifier("listCell", forIndexPath: indexPath)
cell.textLabel!.text = rosenList[indexPath.row].name
return cell
}
// データを取得する
func getUriData(){
let urlString = "uri"
let url = NSURL(string: urlString)
//download by NSSession
let task = NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler:{data, response, error in
//convert json data to dictionary
var dict:NSDictionary
do {
// 余計な"()"を排除する為に、NSData -> NSString(カッコ排除) -> NSData とする
var out = NSString(data:data!, encoding:NSUTF8StringEncoding)
print(out)
out = out?.stringByReplacingOccurrencesOfString("(", withString: "")
out = out?.stringByReplacingOccurrencesOfString(")", withString: "")
print(out)
let data2 = out!.dataUsingEncoding(NSUTF8StringEncoding)
dict = try NSJSONSerialization.JSONObjectWithData(data2!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
// JSONでdictionaryとして取得
let rosenDatas = dict["list"] as! NSArray
var titles:String = ""
for entry in rosenDatas {
let id:String = entry["id"] as! String
titles += id + "/"
let name = entry["name"] as! String
titles += name + " "
let data = (id:id, name:name)
self.dataList.append(data)
}
// UIスレッドに出力する場合
/*
dispatch_async(dispatch_get_main_queue()){
// self.jsonTextView.text = titles
}
*/
self.tableView.reloadData() // UIを更新
} catch {
print("error")
return
}
// print(dict)
})
task.resume()
}
}
2017年1月17日火曜日
タプル配列を使ってみる
構造体配列のようなものを作りたい場合に、タプル配列を使うと良さそうです。
// タプル配列の定義(この段階ではカラ)
var arrayList : [(id:String, name:String, description:String)] = []
// 追加するメンバの作成
let elem2 = (id:"3", name:"hoge2", description:"testその2")
// タプル配列に追加
element.append(elem2)
//配列のインデックス指定でよみ出し
print(arrayList.count)
print(arrayList[1].id)
print(arrayList[1].name)
print(arrayList[1].description)
// forループでよみ出し
for el in arrayList{
let val = el.id + String(":") + el.name + String(":") + el.description
print(val)
}
//: Playground - noun: a place where people can play
import UIKit
var str = "Hello, playground"
// 空のタプル配列の定義
var arrayList : [(id:String, name:String, description:String)] = []
// 追加するメンバの生成
let elem1 = ("1", "hoge1", "testその1") // これでもOK
let elem2 = (id:"3", name:"hoge2", description:"testその2")
let elem3 = (id:"5", name:"hoge5", description:"testその5")
// 配列に追加
arrayList.append(elem1)
arrayList.append(elem2)
arrayList.append(elem3)
print(arrayList.count)
print(arrayList[1].id)
print(arrayList[1].name)
print(arrayList[1].description)
// 読み出してみる
for el in arrayList{
let val = el.id + String(":") + el.name + String(":") + el.description
print(val)
}
// タプル配列の定義(この段階ではカラ)
var arrayList : [(id:String, name:String, description:String)] = []
// 追加するメンバの作成
let elem2 = (id:"3", name:"hoge2", description:"testその2")
// タプル配列に追加
element.append(elem2)
//配列のインデックス指定でよみ出し
print(arrayList.count)
print(arrayList[1].id)
print(arrayList[1].name)
print(arrayList[1].description)
// forループでよみ出し
for el in arrayList{
let val = el.id + String(":") + el.name + String(":") + el.description
print(val)
}
//: Playground - noun: a place where people can play
import UIKit
var str = "Hello, playground"
// 空のタプル配列の定義
var arrayList : [(id:String, name:String, description:String)] = []
// 追加するメンバの生成
let elem1 = ("1", "hoge1", "testその1") // これでもOK
let elem2 = (id:"3", name:"hoge2", description:"testその2")
let elem3 = (id:"5", name:"hoge5", description:"testその5")
// 配列に追加
arrayList.append(elem1)
arrayList.append(elem2)
arrayList.append(elem3)
print(arrayList.count)
print(arrayList[1].id)
print(arrayList[1].name)
print(arrayList[1].description)
// 読み出してみる
for el in arrayList{
let val = el.id + String(":") + el.name + String(":") + el.description
print(val)
}
2017年1月16日月曜日
dictionaryを使ってみる
dictionaryは"key"に対する"value"を格納するものです。
追加する場合は、"定義されていない要素" = "value"とするようです。
(appendとかは使わない??)
// 定義
var dicTest02:Dictionary<String,Int> = [:]
// 追加
dicTest02["ほげ"] = 10
dicTest02["hoge"] = 20
// 取得
print(dicTest02["ほげ"]) // Optional(10)
以下、いろいろ試したジャンクソース
//: Playground - noun: a place where people can play
import UIKit
var str = "Hello, playground"
print("使い方1 初期化と宣言しておいて取り出す")
let dicTest01 = [1:"テスト1", 2:"テスト2", 3:"テスト3"]
print(dicTest01) // [2: "テスト2", 3: "テスト3", 1: "テスト1"]
print(dicTest01[1]) // "テスト1"と表示される < keyがintになっている?
print(dicTest01.count)
for val in dicTest01{ // valueが取り出されて表示される(順番は不定みたい)
print(val) // (2, "テスト2") ...
}
print("使い方2 型指定して宣言、文字列をkeyとしてメンバを格納")
var dicTest02:Dictionary<String,Int> = [:]
dicTest02["ほげ"] = 10
dicTest02["hoge"] = 20
print(dicTest02["ほげ"]) // Optional(10)
/* ダメな使い方
dicTest02 = ["ほげ":3] // keyに対してvalueを設定してあげる事
dicTest02 = ["hoge": 4] // "ほげ"は上書きされる??
print(dicTest02) // 全部表示
print(dicTest02["ほげ"])
*/
for val2 in dicTest02{
print(val2) // ("ほげ", 10)という表示
print(val2.0) // keyが表示される
print(val2.1) // valueが表示される (value = 1なのか?)
}
print("使い方3 2と同じだけど、<>で型宣言しても良いようだ")
// 空の辞書を作って追加していく
var dicTest03:[String:Int] = [:]
dicTest03["ほげ"] = 3
dicTest03["hoge"] = 4
print(dicTest03) // 両方表示される
print(dicTest03["hoge"]) // "hoge"のvalueである"4"が表示される
print(dicTest03["ほげ"]) // valueの3が表示される
for val3 in dicTest03{
print(val3)
print(val3.0)
print(val3.1)
}
print("要素をタプルで作って辞書に格納していく append使ってダメな例")
var dicTest04:[String:Int] = [:] // 空の辞書を作る
let a = ["ほげ",1]
let b = ["hoge", 2]
// dicTest04.append(a) // こういう使い方はできないみたい
print("appendで追加していく例 ...keyに追加されないので意図した動作ではない")
var dicList05 : [(id:String, name:String)] = []
let men1 = (id:"1", name:"hoge")
let men2 = (id:"2", name:"ほげ")
dicList05.append(men1)
dicList05.append(men2)
print(dicList05.count) // 2
print(dicList05) // [("1", "hoge"), ("2", "ほげ")]
print(dicList05[0]) // ("1", "hoge")
print(dicList05[1]) // ("2", "ほげ")
/*
// print(dicList["1"])
for (id,name) in dicList05 = { // タプルで取得はできないみたい
print(name)
}
*/
追加する場合は、"定義されていない要素" = "value"とするようです。
(appendとかは使わない??)
// 定義
var dicTest02:Dictionary<String,Int> = [:]
// 追加
dicTest02["ほげ"] = 10
dicTest02["hoge"] = 20
// 取得
print(dicTest02["ほげ"]) // Optional(10)
以下、いろいろ試したジャンクソース
//: Playground - noun: a place where people can play
import UIKit
var str = "Hello, playground"
print("使い方1 初期化と宣言しておいて取り出す")
let dicTest01 = [1:"テスト1", 2:"テスト2", 3:"テスト3"]
print(dicTest01) // [2: "テスト2", 3: "テスト3", 1: "テスト1"]
print(dicTest01[1]) // "テスト1"と表示される < keyがintになっている?
print(dicTest01.count)
for val in dicTest01{ // valueが取り出されて表示される(順番は不定みたい)
print(val) // (2, "テスト2") ...
}
print("使い方2 型指定して宣言、文字列をkeyとしてメンバを格納")
var dicTest02:Dictionary<String,Int> = [:]
dicTest02["ほげ"] = 10
dicTest02["hoge"] = 20
print(dicTest02["ほげ"]) // Optional(10)
/* ダメな使い方
dicTest02 = ["ほげ":3] // keyに対してvalueを設定してあげる事
dicTest02 = ["hoge": 4] // "ほげ"は上書きされる??
print(dicTest02) // 全部表示
print(dicTest02["ほげ"])
*/
for val2 in dicTest02{
print(val2) // ("ほげ", 10)という表示
print(val2.0) // keyが表示される
print(val2.1) // valueが表示される (value = 1なのか?)
}
print("使い方3 2と同じだけど、<>で型宣言しても良いようだ")
// 空の辞書を作って追加していく
var dicTest03:[String:Int] = [:]
dicTest03["ほげ"] = 3
dicTest03["hoge"] = 4
print(dicTest03) // 両方表示される
print(dicTest03["hoge"]) // "hoge"のvalueである"4"が表示される
print(dicTest03["ほげ"]) // valueの3が表示される
for val3 in dicTest03{
print(val3)
print(val3.0)
print(val3.1)
}
print("要素をタプルで作って辞書に格納していく append使ってダメな例")
var dicTest04:[String:Int] = [:] // 空の辞書を作る
let a = ["ほげ",1]
let b = ["hoge", 2]
// dicTest04.append(a) // こういう使い方はできないみたい
print("appendで追加していく例 ...keyに追加されないので意図した動作ではない")
var dicList05 : [(id:String, name:String)] = []
let men1 = (id:"1", name:"hoge")
let men2 = (id:"2", name:"ほげ")
dicList05.append(men1)
dicList05.append(men2)
print(dicList05.count) // 2
print(dicList05) // [("1", "hoge"), ("2", "ほげ")]
print(dicList05[0]) // ("1", "hoge")
print(dicList05[1]) // ("2", "ほげ")
/*
// print(dicList["1"])
for (id,name) in dicList05 = { // タプルで取得はできないみたい
print(name)
}
*/
NSDataとNSStringとbyte列??
NSURLSessionでjsonで取得したデータは"NSData"型で、byte data(のようなもの)のようです。
NSJSONSerializationでjsonの要素を取得したい場合はそのままNSDataを渡してあげれば良いのですが、
ちょっと加工したい場合はNSStringで処理を行うのが良さそうです。
NSData -> NSString -> NSData
という感じになります(これが最適なのかはわかりませんが...NSJSONSerializationに渡すNSDataに余計な文字があるとerrorになる事があったので、NSStringで適当に修正しようかという用途です)
今回のテストコードはデータを作る都合で(横着して) String -> NSData -> NSString -> 文字加工 の順になっていますが、
思っていた動作にはなっているようです。
byte配列でアクセスする場合はArray<Int8>でポインタのようにしてアクセスすると良い模様です。
NSDataに含まれる"()"を削除する例
//: Playground - noun: a place where people can play
import UIKit
var str = "(Hello)";
// String -> NSData
let data = str.dataUsingEncoding(NSUTF8StringEncoding)
// NSData -> NSString
let str2 = NSString(data:data!, encoding:NSUTF8StringEncoding)
// NSStringの文字列処理
var str3 = str2?.stringByReplacingOccurrencesOfString("(", withString: "")
str3 = str3?.stringByReplacingOccurrencesOfString(")", withString: "")
print(str3) // Helloと表示される...これを再度NSData化すればJSON処理できそう
// NSDataをbyte列として扱う
var buffer = Array<Int8>(count: data!.length, repeatedValue: 0)
data!.getBytes(&buffer, length: data!.length) // &でポインタ扱い
for byte in buffer {
// print("\(byte)")
let str = NSString(format:"%2X", byte) // 16進文字列変換
print(str)
}
NSJSONSerializationでjsonの要素を取得したい場合はそのままNSDataを渡してあげれば良いのですが、
ちょっと加工したい場合はNSStringで処理を行うのが良さそうです。
NSData -> NSString -> NSData
という感じになります(これが最適なのかはわかりませんが...NSJSONSerializationに渡すNSDataに余計な文字があるとerrorになる事があったので、NSStringで適当に修正しようかという用途です)
今回のテストコードはデータを作る都合で(横着して) String -> NSData -> NSString -> 文字加工 の順になっていますが、
思っていた動作にはなっているようです。
byte配列でアクセスする場合はArray<Int8>でポインタのようにしてアクセスすると良い模様です。
NSDataに含まれる"()"を削除する例
//: Playground - noun: a place where people can play
import UIKit
var str = "(Hello)";
// String -> NSData
let data = str.dataUsingEncoding(NSUTF8StringEncoding)
// NSData -> NSString
let str2 = NSString(data:data!, encoding:NSUTF8StringEncoding)
// NSStringの文字列処理
var str3 = str2?.stringByReplacingOccurrencesOfString("(", withString: "")
str3 = str3?.stringByReplacingOccurrencesOfString(")", withString: "")
print(str3) // Helloと表示される...これを再度NSData化すればJSON処理できそう
// NSDataをbyte列として扱う
var buffer = Array<Int8>(count: data!.length, repeatedValue: 0)
data!.getBytes(&buffer, length: data!.length) // &でポインタ扱い
for byte in buffer {
// print("\(byte)")
let str = NSString(format:"%2X", byte) // 16進文字列変換
print(str)
}
2017年1月10日火曜日
MapKit Viewのピン(annotation)をタップ動作
前に作った地図表示 + ピン (annotation)で、ピンをクリックしてアクションをする方法を調べてみました。
2つのdelegateを実装する事でピンのタイトルを取得できました
- ピンを配置する際のdelegate
- ピンがタップされる際のdelegate
delegateを実装する前準備(GUI操作)とViewControllerへの継承(コード記述)も必要でした
delegateを実装する
1. (際左ペインで)ViewController.swiftを選択し、左2番目ペインでView Controller Scene - View Controller - View - Disp Mapを選択(最後の名称は自分でつけたもの)
2. 際右ペインにOutlets (delegate) が表示されるので、◉をドラッグし、ViewControllerに接続する
3. ViewController.swiftを選択し、MKMapViewDelegateを継承する
class ViewController: UIViewController, MKMapViewDelegate {
^この部分
4. 以下のdelegateを追加
class ViewController: UIViewController, MKMapViewDelegate {
...中略...
// Called when the annotation was added
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.animatesDrop = true // 落下アニメーション
pinView?.canShowCallout = true // tapのdelegateにはコレが効いている
pinView?.draggable = true // ピンをドラッグ出来るようになる
pinView?.pinTintColor = UIColor.blueColor() // 色設定
let rightButton: AnyObject! = UIButton(type: UIButtonType.DetailDisclosure)
pinView?.rightCalloutAccessoryView = rightButton as? UIView
}
else {
pinView?.annotation = annotation
}
return pinView
}
// ピンをタップした際に呼ばれるdelegate
func mapView(mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
// どのピンがタップされたかを取得
let title = view.annotation?.title
if let point = title{ // "optional(横浜)"となるので、アンラップする http://qiita.com/maiki055/items/b24378a3707bd35a31a8
let place = "hello " + point!
print(place)
}
}
参考にさせていただきましたサイト
http://blog.koogawa.com/entry/2015/11/01/115728
http://dev.classmethod.jp/smartphone/ios-mapkit/
http://qiita.com/maiki055/items/b24378a3707bd35a31a8
ViewController.swiftの全体
//
// ViewController.swift
// mapTest03
//
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate { // ピン押下イベントを追加
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func gotoSpot(sender: AnyObject) {
execGotoSpot()
}
@IBOutlet weak var dispMap: MKMapView!
// ピンを表示するボタン押下
@IBAction func dispPin(sender: AnyObject) {
let ido = 35.454954
let keido = 139.631859
let title = "横浜"
execDispPin(ido, lng: keido, name: title)
}
// ピンを表示する
func execDispPin(lat:Double, lng:Double, name:String){
let annotation = MKPointAnnotation()
// 位置
annotation.coordinate = CLLocationCoordinate2DMake(lat, lng)
// タイトル
annotation.title = name
// ピンを置く
dispMap.addAnnotation(annotation)
}
// 指定の緯度経度に移動する
func execGotoSpot(){
// 横浜の緯度経度
let ido = 35.454954
let keido = 139.631859
let center = CLLocationCoordinate2D(latitude: ido, longitude: keido)
// 1500とかだとSIGABRTが発生する(範囲が広すぎるようだ)
let span = MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5)
let theRegion = MKCoordinateRegion(center: center, span: span)
dispMap.setRegion(theRegion, animated: true)
}
// 以下のdelegateを追加
// Called when the annotation was added
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.animatesDrop = true // 落下アニメーション
pinView?.canShowCallout = true // tapのdelegateにはコレが効いている
pinView?.draggable = true // ピンをドラッグ出来るようになる
pinView?.pinTintColor = UIColor.blueColor() // 色設定
let rightButton: AnyObject! = UIButton(type: UIButtonType.DetailDisclosure)
pinView?.rightCalloutAccessoryView = rightButton as? UIView
}
else {
pinView?.annotation = annotation
}
return pinView
}
// ピンをタップした際に呼ばれるdelegate
func mapView(mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
// どのピンがタップされたかを取得
let title = view.annotation?.title
if let point = title{ // "optional(横浜)"となるので、アンラップする http://qiita.com/maiki055/items/b24378a3707bd35a31a8
let place = "hello " + point!
print(place) // "hello 横浜"と表示される
}
}
}
2つのdelegateを実装する事でピンのタイトルを取得できました
- ピンを配置する際のdelegate
- ピンがタップされる際のdelegate
delegateを実装する前準備(GUI操作)とViewControllerへの継承(コード記述)も必要でした
delegateを実装する
1. (際左ペインで)ViewController.swiftを選択し、左2番目ペインでView Controller Scene - View Controller - View - Disp Mapを選択(最後の名称は自分でつけたもの)
2. 際右ペインにOutlets (delegate) が表示されるので、◉をドラッグし、ViewControllerに接続する
3. ViewController.swiftを選択し、MKMapViewDelegateを継承する
class ViewController: UIViewController, MKMapViewDelegate {
^この部分
4. 以下のdelegateを追加
class ViewController: UIViewController, MKMapViewDelegate {
...中略...
// Called when the annotation was added
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.animatesDrop = true // 落下アニメーション
pinView?.canShowCallout = true // tapのdelegateにはコレが効いている
pinView?.draggable = true // ピンをドラッグ出来るようになる
pinView?.pinTintColor = UIColor.blueColor() // 色設定
let rightButton: AnyObject! = UIButton(type: UIButtonType.DetailDisclosure)
pinView?.rightCalloutAccessoryView = rightButton as? UIView
}
else {
pinView?.annotation = annotation
}
return pinView
}
// ピンをタップした際に呼ばれるdelegate
func mapView(mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
// どのピンがタップされたかを取得
let title = view.annotation?.title
if let point = title{ // "optional(横浜)"となるので、アンラップする http://qiita.com/maiki055/items/b24378a3707bd35a31a8
let place = "hello " + point!
print(place)
}
}
参考にさせていただきましたサイト
http://blog.koogawa.com/entry/2015/11/01/115728
http://dev.classmethod.jp/smartphone/ios-mapkit/
http://qiita.com/maiki055/items/b24378a3707bd35a31a8
ViewController.swiftの全体
//
// ViewController.swift
// mapTest03
//
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate { // ピン押下イベントを追加
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func gotoSpot(sender: AnyObject) {
execGotoSpot()
}
@IBOutlet weak var dispMap: MKMapView!
// ピンを表示するボタン押下
@IBAction func dispPin(sender: AnyObject) {
let ido = 35.454954
let keido = 139.631859
let title = "横浜"
execDispPin(ido, lng: keido, name: title)
}
// ピンを表示する
func execDispPin(lat:Double, lng:Double, name:String){
let annotation = MKPointAnnotation()
// 位置
annotation.coordinate = CLLocationCoordinate2DMake(lat, lng)
// タイトル
annotation.title = name
// ピンを置く
dispMap.addAnnotation(annotation)
}
// 指定の緯度経度に移動する
func execGotoSpot(){
// 横浜の緯度経度
let ido = 35.454954
let keido = 139.631859
let center = CLLocationCoordinate2D(latitude: ido, longitude: keido)
// 1500とかだとSIGABRTが発生する(範囲が広すぎるようだ)
let span = MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5)
let theRegion = MKCoordinateRegion(center: center, span: span)
dispMap.setRegion(theRegion, animated: true)
}
// 以下のdelegateを追加
// Called when the annotation was added
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.animatesDrop = true // 落下アニメーション
pinView?.canShowCallout = true // tapのdelegateにはコレが効いている
pinView?.draggable = true // ピンをドラッグ出来るようになる
pinView?.pinTintColor = UIColor.blueColor() // 色設定
let rightButton: AnyObject! = UIButton(type: UIButtonType.DetailDisclosure)
pinView?.rightCalloutAccessoryView = rightButton as? UIView
}
else {
pinView?.annotation = annotation
}
return pinView
}
// ピンをタップした際に呼ばれるdelegate
func mapView(mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
// どのピンがタップされたかを取得
let title = view.annotation?.title
if let point = title{ // "optional(横浜)"となるので、アンラップする http://qiita.com/maiki055/items/b24378a3707bd35a31a8
let place = "hello " + point!
print(place) // "hello 横浜"と表示される
}
}
}
2017年1月9日月曜日
TableViewとNavigationControllerで画面遷移
TableViewでデータを選択 -> 画面遷移 というケースがよく使われるとの事なので試してみました。
画面1 : tableViewでリストを表示 (DataTableViewController.swift / User List Scene)
画面2 : tableViewで選択されたデータを受け取り、画面遷移 (ViewController.swift / View Controller Scene)
画面1は新規に作成、画面2はプロジェクト作成時に生成されたものです。
NavigationControllerを配置して、画面遷移を実施します。
1. SingleViewでprojectを作成
2. Main.Storyboardを選択し、Navigation Controllerを最初からあるViewControllerの左にドラッグドロップ
Navigation ControllerとRoot View Controller (Table View)の繋がった箱がコピーされる
(最初のView Controller含めて3つの箱が表示されている)
3. ↑で追加したNavigation Controllerを選択し、右ペインのAttributes(右ペイン上部の"-↓-“みたいなアイコンを選択しておく)のViewControllerの項目にある”Is Initial View Controller”をチェックする
最初のViewControllerの左にあった矢印が消えて、追加したNavigation Controllerの左に矢印が追加される (= アプリが起動した時に最初に表示するシーンになるという意味)
4. (左2番目ペインの)Root View Controller Scene - Root View Controller - Root View Controllerを選択し、タイトルを書き換える
“***リスト”など (オブジェクトはRootViewController - Table Viewになっている)
5. ( 〃 )Root View Controller - Table View - Table View Cell を選択
1. 右ペインのStyleをSubtitle とする (title + subtitleの表示になる)
2. 〃 Identifer(一つ下にある)を”Cell”と入力する (Cellでアクセス出来る?)
3. 〃 Accosoryを"Dsiclosure Indicator”を選択する (画面遷移の”>”表示が出る)
segueで接続
6. (左2番目のペイン)TableView - Cell を選択した状態で、Cellをcontrol押しのIBAction接続で”最初からあった”Viewに接続する
この時にダイアログが表示されるので”Selection Segue - show”を選択する
テーブルViewコントローラから最初のViewに矢印がひかれる
7. ↑でひっぱったsegueを選択し、identiferを入力する
showCellDataとか…これは後ほどswiftコードの識別子として使用する
Table Viewのカスタムクラス(***.swift)を作成
8. TableViewControllerのカスタムクラスを作成する
1. File -> New -> FileでiOS-Sourceを選択、Cocoa Touch Classを選択し、Nextを押す
2. Class名をつける (DataTableViewControllerとか)、subClassを”UITableViewContoller”を選択してNext
3. 置き場所はdefault(ViewController.swiftなどが置かれている場所)でよい
9. ↑で作ったカスタムclassをview(今回はリスト)と関連づける
1. storyboardを選択し、TableViewを選択、(GUIの)上アイコン左(RootViewContlller)を選択
2. 右ペインの左から2番目のアイコン(propertyっぽいやつ)を選択してClassから”DataTableViewController”を選択する << ****.swiftのclass名を選択するという意味
10. カスタムクラスにTableViewに表示させるデータを記載する
DataTableTableViewController.swiftを選択
1. tableに表示されるリストを書く (class直下で良い)
// セルに表示するデータ
let modelList = [
(company: "aaa", model1: "a01", model2: "a02"),
(company: "bbb", model1: "b01", model2: "b02"),
(company: "ccc", model1: "c01", model2: "c02"),
(company: "ddd", model1: "d01", model2: "d02")
]
2. コメントアウトされているtableViewメソッドを有効化して、rawのデータを返すコードを記載する
// tableViewのセルに表示する部分
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
// 元からあるコードのCellの識別子を書き換える
// Configure the cell… // 以下の部分は手書きで記載
let cellData = modelList[indexPath.row]
// cellのプロパティに設定
cell.textLabel?.text = cellData.company
cell.detailTextLabel?.text = cellData.model1
return cell // ここは元のコードのまま
}
11. データを渡す部分を有効化して記載
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
if segue.identifier == "showCellData” { // segueの識別子に合わせる事!
if let indexPath = self.tableView.indexPathForSelectedRow{
let modelData = modelList[indexPath.row]
(segue.destinationViewController as! ViewController).data = modelData
// 移動先にメンバ”data”を作る事(この時点で存在しない場合、メンバが無いerrorが出ている)
}
}
}
12. 受け渡しの個数、及びtable数を返している箇所を実装する
numberOfSectionsInTableView と tableView メソッドがreturn 0になっているので以下を返すように変更する
numberOfSectionsInTableView : return 1
tableView: return list.count
(これをやらないとtableに表示されない)
具体的には
// セクションの個数
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 0
}
// セクション内の行数
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
// return 0
return modelList.count
13. 表示するViewController.swift (tableViewから遷移される側)に渡されたデータを表示するコードを実装する
実際は、tableのデータを処理する部分。今回はサンプルなので、ラベルに渡されたデータを表示するだけのコードを記載
表示するViewControllerに、渡されたデータを表示するコードを記載する
// 渡されるデータを定義する (これが書かれていな買ったので、"12"ではエラーが出ていた)
var data:(company:String, model1:String, model2:String)?
// ラベルに接続するコード
func dispLabel(){
if let dispData = data {
Label1.text = dispData.company
Label2.text = dispData.model1
Label3.text = dispData.model2
}
}
@IBOutlet weak var Label1: UILabel!
@IBOutlet weak var Label2: UILabel!
@IBOutlet weak var Label3: UILabel!
(結構長いが...)とりあえず、上記実装で
- TableViewで選択したデータを、ViewControllerで表示
という動作が出来るようになりました。
注意点は
- 遷移先画面へのデータの受け渡しでは、受け側でデータを定義していないとエラーが出る(後で受け側に定義すれば出なくなる)
- TableViewの画面表示させるlistの定義と、仮実装・コメントされているスタブへの記述
Tableに適切なデータが表示されていない場合は、これが原因だったりしました
- swiftの記述で、identifierを参照するので、GUIに設定した内容を忘れないようにする
- DataTableViewController.swiftを生成するので、main.storyboardの画面にGUIで紐付けする
- NavigationControllerをGUIで配置したり、初期画面を設定したりするのを忘れない
辺りでしょうか
swiftのコードを記載します。
DataTableViewController.swift (DataTableViewControllerとして追加したクラス)
//
// DataTableTableViewController.swift
// TableView-Navigation01//
import UIKit
class DataTableTableViewController: UITableViewController {
// リストを追加
let modelList = [
(company: "aaa", model1: "a01", model2: "a02"),
(company: "bbb", model1: "b01", model2: "b02"),
(company: "ccc", model1: "c01", model2: "c02"),
(company: "ddd", model1: "d01", model2: "d02")
]
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
// セクションの個数を返すように中身を変更する
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
// return 0
return 1 // 変更
}
// セクション内の行数を返すコードに中身を変更する
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
// return 0
return modelList.count // 変更
}
// 元々コメントアウトされているコードを有効化して中に処理を書く
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) // param1をGUIで設定したIDに合わせる
// Configure the cell… // 以下の部分は手書きで記載
let cellData = modelList[indexPath.row]
// cellのプロパティに設定
cell.textLabel?.text = cellData.company
cell.detailTextLabel?.text = cellData.model1
// ここまで
return cell
}
/*
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
// MARK: - Navigation
// 以下を有効化して中身を記載(移動する前にデータを受け渡す)
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
// 以下のコードを記述する
if segue.identifier == "showCellData" {
// 行を取り出す
if let indexPath = self.tableView.indexPathForSelectedRow{
let modelData = modelList[indexPath.row] // 上で作ってある配列から行をインデックスとして取り出し
// (segue.destinationViewController as! ViewController).data = modelData
(segue.destinationViewController as! ViewController).data = modelData // 移動先にメンバ"data"を作る事
}
}
}
}
---
ViewController.swift (渡される側、そして元々あった画面に紐付けされている)
//
// ViewController.swift
// TableView-Navigation01
//
//
import UIKit
class ViewController: UIViewController {
// 渡す側のviewcontrollerから (segue.destinationViewController as! ViewController).dataとしてアクセスされる
var data:(company:String, model1:String, model2:String)? // 渡されるデータを定義する
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// 表示する関数を呼び出す
dispLabel()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// 暫定表示UI (GUIからIBOutletで紐付け)
@IBOutlet weak var label1: UILabel!
@IBOutlet weak var label2: UILabel!
@IBOutlet weak var label3: UILabel!
// ボタン押下で遷移元に戻る
@IBAction func returnButtonClick(sender: AnyObject) {
_ = navigationController?.popViewControllerAnimated(true)
}
// ラベルに表示するコード
func dispLabel(){
if let dispData = data{
label1.text = dispData.company
label2.text = dispData.model1
label3.text = dispData.model2
}
}
}
画面1 : tableViewでリストを表示 (DataTableViewController.swift / User List Scene)
画面2 : tableViewで選択されたデータを受け取り、画面遷移 (ViewController.swift / View Controller Scene)
画面1は新規に作成、画面2はプロジェクト作成時に生成されたものです。
NavigationControllerを配置して、画面遷移を実施します。
1. SingleViewでprojectを作成
2. Main.Storyboardを選択し、Navigation Controllerを最初からあるViewControllerの左にドラッグドロップ
Navigation ControllerとRoot View Controller (Table View)の繋がった箱がコピーされる
(最初のView Controller含めて3つの箱が表示されている)
3. ↑で追加したNavigation Controllerを選択し、右ペインのAttributes(右ペイン上部の"-↓-“みたいなアイコンを選択しておく)のViewControllerの項目にある”Is Initial View Controller”をチェックする
最初のViewControllerの左にあった矢印が消えて、追加したNavigation Controllerの左に矢印が追加される (= アプリが起動した時に最初に表示するシーンになるという意味)
4. (左2番目ペインの)Root View Controller Scene - Root View Controller - Root View Controllerを選択し、タイトルを書き換える
“***リスト”など (オブジェクトはRootViewController - Table Viewになっている)
5. ( 〃 )Root View Controller - Table View - Table View Cell を選択
1. 右ペインのStyleをSubtitle とする (title + subtitleの表示になる)
2. 〃 Identifer(一つ下にある)を”Cell”と入力する (Cellでアクセス出来る?)
3. 〃 Accosoryを"Dsiclosure Indicator”を選択する (画面遷移の”>”表示が出る)
segueで接続
6. (左2番目のペイン)TableView - Cell を選択した状態で、Cellをcontrol押しのIBAction接続で”最初からあった”Viewに接続する
この時にダイアログが表示されるので”Selection Segue - show”を選択する
テーブルViewコントローラから最初のViewに矢印がひかれる
7. ↑でひっぱったsegueを選択し、identiferを入力する
showCellDataとか…これは後ほどswiftコードの識別子として使用する
Table Viewのカスタムクラス(***.swift)を作成
8. TableViewControllerのカスタムクラスを作成する
1. File -> New -> FileでiOS-Sourceを選択、Cocoa Touch Classを選択し、Nextを押す
2. Class名をつける (DataTableViewControllerとか)、subClassを”UITableViewContoller”を選択してNext
3. 置き場所はdefault(ViewController.swiftなどが置かれている場所)でよい
9. ↑で作ったカスタムclassをview(今回はリスト)と関連づける
1. storyboardを選択し、TableViewを選択、(GUIの)上アイコン左(RootViewContlller)を選択
2. 右ペインの左から2番目のアイコン(propertyっぽいやつ)を選択してClassから”DataTableViewController”を選択する << ****.swiftのclass名を選択するという意味
10. カスタムクラスにTableViewに表示させるデータを記載する
DataTableTableViewController.swiftを選択
1. tableに表示されるリストを書く (class直下で良い)
// セルに表示するデータ
let modelList = [
(company: "aaa", model1: "a01", model2: "a02"),
(company: "bbb", model1: "b01", model2: "b02"),
(company: "ccc", model1: "c01", model2: "c02"),
(company: "ddd", model1: "d01", model2: "d02")
]
2. コメントアウトされているtableViewメソッドを有効化して、rawのデータを返すコードを記載する
// tableViewのセルに表示する部分
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
// 元からあるコードのCellの識別子を書き換える
// Configure the cell… // 以下の部分は手書きで記載
let cellData = modelList[indexPath.row]
// cellのプロパティに設定
cell.textLabel?.text = cellData.company
cell.detailTextLabel?.text = cellData.model1
return cell // ここは元のコードのまま
}
11. データを渡す部分を有効化して記載
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
if segue.identifier == "showCellData” { // segueの識別子に合わせる事!
if let indexPath = self.tableView.indexPathForSelectedRow{
let modelData = modelList[indexPath.row]
(segue.destinationViewController as! ViewController).data = modelData
// 移動先にメンバ”data”を作る事(この時点で存在しない場合、メンバが無いerrorが出ている)
}
}
}
12. 受け渡しの個数、及びtable数を返している箇所を実装する
numberOfSectionsInTableView と tableView メソッドがreturn 0になっているので以下を返すように変更する
numberOfSectionsInTableView : return 1
tableView: return list.count
(これをやらないとtableに表示されない)
具体的には
// セクションの個数
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 0
}
// セクション内の行数
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
// return 0
return modelList.count
13. 表示するViewController.swift (tableViewから遷移される側)に渡されたデータを表示するコードを実装する
実際は、tableのデータを処理する部分。今回はサンプルなので、ラベルに渡されたデータを表示するだけのコードを記載
表示するViewControllerに、渡されたデータを表示するコードを記載する
// 渡されるデータを定義する (これが書かれていな買ったので、"12"ではエラーが出ていた)
var data:(company:String, model1:String, model2:String)?
// ラベルに接続するコード
func dispLabel(){
if let dispData = data {
Label1.text = dispData.company
Label2.text = dispData.model1
Label3.text = dispData.model2
}
}
@IBOutlet weak var Label1: UILabel!
@IBOutlet weak var Label2: UILabel!
@IBOutlet weak var Label3: UILabel!
(結構長いが...)とりあえず、上記実装で
- TableViewで選択したデータを、ViewControllerで表示
という動作が出来るようになりました。
注意点は
- 遷移先画面へのデータの受け渡しでは、受け側でデータを定義していないとエラーが出る(後で受け側に定義すれば出なくなる)
- TableViewの画面表示させるlistの定義と、仮実装・コメントされているスタブへの記述
Tableに適切なデータが表示されていない場合は、これが原因だったりしました
- swiftの記述で、identifierを参照するので、GUIに設定した内容を忘れないようにする
- DataTableViewController.swiftを生成するので、main.storyboardの画面にGUIで紐付けする
- NavigationControllerをGUIで配置したり、初期画面を設定したりするのを忘れない
辺りでしょうか
swiftのコードを記載します。
DataTableViewController.swift (DataTableViewControllerとして追加したクラス)
//
// DataTableTableViewController.swift
// TableView-Navigation01//
import UIKit
class DataTableTableViewController: UITableViewController {
// リストを追加
let modelList = [
(company: "aaa", model1: "a01", model2: "a02"),
(company: "bbb", model1: "b01", model2: "b02"),
(company: "ccc", model1: "c01", model2: "c02"),
(company: "ddd", model1: "d01", model2: "d02")
]
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
// セクションの個数を返すように中身を変更する
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
// return 0
return 1 // 変更
}
// セクション内の行数を返すコードに中身を変更する
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
// return 0
return modelList.count // 変更
}
// 元々コメントアウトされているコードを有効化して中に処理を書く
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) // param1をGUIで設定したIDに合わせる
// Configure the cell… // 以下の部分は手書きで記載
let cellData = modelList[indexPath.row]
// cellのプロパティに設定
cell.textLabel?.text = cellData.company
cell.detailTextLabel?.text = cellData.model1
// ここまで
return cell
}
/*
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
// MARK: - Navigation
// 以下を有効化して中身を記載(移動する前にデータを受け渡す)
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
// 以下のコードを記述する
if segue.identifier == "showCellData" {
// 行を取り出す
if let indexPath = self.tableView.indexPathForSelectedRow{
let modelData = modelList[indexPath.row] // 上で作ってある配列から行をインデックスとして取り出し
// (segue.destinationViewController as! ViewController).data = modelData
(segue.destinationViewController as! ViewController).data = modelData // 移動先にメンバ"data"を作る事
}
}
}
}
---
ViewController.swift (渡される側、そして元々あった画面に紐付けされている)
//
// ViewController.swift
// TableView-Navigation01
//
//
import UIKit
class ViewController: UIViewController {
// 渡す側のviewcontrollerから (segue.destinationViewController as! ViewController).dataとしてアクセスされる
var data:(company:String, model1:String, model2:String)? // 渡されるデータを定義する
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// 表示する関数を呼び出す
dispLabel()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// 暫定表示UI (GUIからIBOutletで紐付け)
@IBOutlet weak var label1: UILabel!
@IBOutlet weak var label2: UILabel!
@IBOutlet weak var label3: UILabel!
// ボタン押下で遷移元に戻る
@IBAction func returnButtonClick(sender: AnyObject) {
_ = navigationController?.popViewControllerAnimated(true)
}
// ラベルに表示するコード
func dispLabel(){
if let dispData = data{
label1.text = dispData.company
label2.text = dispData.model1
label3.text = dispData.model2
}
}
}
2017年1月7日土曜日
MKPointAnnotationでMapKitViewにpinを表示してみる
一つ前の投稿に、以下のコードを追加しました (ピンのIBActionを追加してます)
// ピン置きボタン押下処理
@IBAction func dispPin(sender: AnyObject) {
let ido = 35.454954
let keido = 139.631859
let title = "横浜"
execDispPin(ido, lng: keido, name: title)
}
// ピン表示関数
func execDispPin(lat:Double, lng:Double, name:String){
let annotation = MKPointAnnotation()
// 位置
annotation.coordinate = CLLocationCoordinate2DMake(lat, lng)
// タイトル
annotation.title = name
// ピンを置く
dispMap.addAnnotation(annotation)
}
まとめるとこんな感じです
地図ボタン押す -> 地図が横浜でセンタリングされる
ピンボタンを押す -> 横浜にピンが配置される
地図のピンをクリックするとタイトルが表示されます
//
// ViewController.swift
// mapTest03
//
import UIKit
import MapKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func gotoSpot(sender: AnyObject) {
execGotoSpot()
}
@IBOutlet weak var dispMap: MKMapView!
// ピンを表示する
@IBAction func dispPin(sender: AnyObject) {
let ido = 35.454954
let keido = 139.631859
let title = "横浜"
execDispPin(ido, lng: keido, name: title)
}
func execDispPin(lat:Double, lng:Double, name:String){
let annotation = MKPointAnnotation()
// 位置
annotation.coordinate = CLLocationCoordinate2DMake(lat, lng)
// タイトル
annotation.title = name
// ピンを置く
dispMap.addAnnotation(annotation)
}
func execGotoSpot(){
// 横浜の緯度経度
let ido = 35.454954
let keido = 139.631859
let center = CLLocationCoordinate2D(latitude: ido, longitude: keido)
// 1500とかだとSIGABRTが発生する(範囲が広すぎるようだ)
let span = MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5)
let theRegion = MKCoordinateRegion(center: center, span: span)
dispMap.setRegion(theRegion, animated: true)
}
}
// ピン置きボタン押下処理
@IBAction func dispPin(sender: AnyObject) {
let ido = 35.454954
let keido = 139.631859
let title = "横浜"
execDispPin(ido, lng: keido, name: title)
}
// ピン表示関数
func execDispPin(lat:Double, lng:Double, name:String){
let annotation = MKPointAnnotation()
// 位置
annotation.coordinate = CLLocationCoordinate2DMake(lat, lng)
// タイトル
annotation.title = name
// ピンを置く
dispMap.addAnnotation(annotation)
}
まとめるとこんな感じです
地図ボタン押す -> 地図が横浜でセンタリングされる
ピンボタンを押す -> 横浜にピンが配置される
地図のピンをクリックするとタイトルが表示されます
//
// ViewController.swift
// mapTest03
//
import UIKit
import MapKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func gotoSpot(sender: AnyObject) {
execGotoSpot()
}
@IBOutlet weak var dispMap: MKMapView!
// ピンを表示する
@IBAction func dispPin(sender: AnyObject) {
let ido = 35.454954
let keido = 139.631859
let title = "横浜"
execDispPin(ido, lng: keido, name: title)
}
func execDispPin(lat:Double, lng:Double, name:String){
let annotation = MKPointAnnotation()
// 位置
annotation.coordinate = CLLocationCoordinate2DMake(lat, lng)
// タイトル
annotation.title = name
// ピンを置く
dispMap.addAnnotation(annotation)
}
func execGotoSpot(){
// 横浜の緯度経度
let ido = 35.454954
let keido = 139.631859
let center = CLLocationCoordinate2D(latitude: ido, longitude: keido)
// 1500とかだとSIGABRTが発生する(範囲が広すぎるようだ)
let span = MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5)
let theRegion = MKCoordinateRegion(center: center, span: span)
dispMap.setRegion(theRegion, animated: true)
}
}
MapKit Viewで地図を表示してみる
0. Single Viewでprojectを作る
1. プロジェクトルート -> TARGETS(左から2番目ペイン) -> General(tabのような位置)で “Linked Frameworks and libraries”(下の方)で”Mapkit.framework”を選択して下の”+”ボタンを押す
2. Main.storyboardで”Mapkit View”をドラッグし、画面全体に広げる
3. IBOutletでmapをcodeにつなげておく
この時点で、赤”!”のエラーが発生する(MkMapViewの定義が見つからない?)
"import MapKit" をファイルの最初のimport定義記載部分に書くとエラーはなくなる
4. ViewController.swiftに以下のコードを書いて、ボタンのIBAction等から呼び出す
func execGotoSpot(){
// 横浜の緯度経度
let ido = 35.454954
let keido = 139.631859
let center = CLLocationCoordinate2D(latitude: ido, longitude: keido)
// 1500とかだとSIGABRTが発生する(範囲が広すぎるようだ)
let span = MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5)
let theRegion = MKCoordinateRegion(center: center, span: span)
dispMap.setRegion(theRegion, animated: true)
}
まとめるとこんな感じ
//
// ViewController.swift//
import UIKit
import MapKit // 追加する
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func gotoSpot(sender: AnyObject) {
execGotoSpot() // 地図表示関数
}
@IBOutlet weak var dispMap: MKMapView!
func execGotoSpot(){
// 横浜の緯度経度
let ido = 35.454954
let keido = 139.631859
let center = CLLocationCoordinate2D(latitude: ido, longitude: keido)
// 1500とかだとSIGABRTが発生する(範囲が広すぎるようだ)
let span = MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5)
let theRegion = MKCoordinateRegion(center: center, span: span)
dispMap.setRegion(theRegion, animated: true)
}
}
1. プロジェクトルート -> TARGETS(左から2番目ペイン) -> General(tabのような位置)で “Linked Frameworks and libraries”(下の方)で”Mapkit.framework”を選択して下の”+”ボタンを押す
2. Main.storyboardで”Mapkit View”をドラッグし、画面全体に広げる
3. IBOutletでmapをcodeにつなげておく
この時点で、赤”!”のエラーが発生する(MkMapViewの定義が見つからない?)
"import MapKit" をファイルの最初のimport定義記載部分に書くとエラーはなくなる
4. ViewController.swiftに以下のコードを書いて、ボタンのIBAction等から呼び出す
func execGotoSpot(){
// 横浜の緯度経度
let ido = 35.454954
let keido = 139.631859
let center = CLLocationCoordinate2D(latitude: ido, longitude: keido)
// 1500とかだとSIGABRTが発生する(範囲が広すぎるようだ)
let span = MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5)
let theRegion = MKCoordinateRegion(center: center, span: span)
dispMap.setRegion(theRegion, animated: true)
}
まとめるとこんな感じ
//
// ViewController.swift//
import UIKit
import MapKit // 追加する
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func gotoSpot(sender: AnyObject) {
execGotoSpot() // 地図表示関数
}
@IBOutlet weak var dispMap: MKMapView!
func execGotoSpot(){
// 横浜の緯度経度
let ido = 35.454954
let keido = 139.631859
let center = CLLocationCoordinate2D(latitude: ido, longitude: keido)
// 1500とかだとSIGABRTが発生する(範囲が広すぎるようだ)
let span = MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5)
let theRegion = MKCoordinateRegion(center: center, span: span)
dispMap.setRegion(theRegion, animated: true)
}
}
JSONを確認出来るweb toolでRESTのデータを見てみる(2)
ちょっと複雑な例を見てみます
以前は、heartrails expressというサイトで時刻表データが取得できたのですが、見当たらなくなってしまったので、一つ前の投稿の参考urlで紹介されていた"つつじバス"を見てみます
(heartrails expressのAPIは2015.09頃"公開停止中"というtwitterのログがありました)
http://www.city.sabae.fukui.jp/users/tutujibus/web-api/web-api.html
リクエストURLで簡単そうな例を探すと、02の"路線毎の時刻表データ"が良さそうです
http://www.city.sabae.fukui.jp/users/tutujibus/web-api/02.html
リクエストURLを下記のようにしてデータを取得してみます
http://tutujibus.com/timetableLookup.php/?rosenid=2
結果を整形してみます...の前に、ざっくり構造を調べてみます
timetalbe : 以下の配列
bindid : 便番号 << この便番号毎に配列になっていて、中に時刻表配列が入っている
*** 中略 (ドキュメント参照)
list : 時刻表配列
{
time : 時刻
busstopid : バス停番号
}
binid : 次の便番号
*** 中略 (ドキュメント参照)
list : 時刻表配列
*** 以下同様に続く
となっているようです
{
"timetable": [
{
"binid": "1",
"konendaigakucd": "3",
"weekdaycd": "3",
"wintercd": "3",
"destination": "嚮陽会館",
"list": [
{
"time": "08:55:00",
"busstopid": "45"
},
// *** 中略 ***
{
"time": "09:21:00",
"busstopid": "61"
}
]
},
{
"binid": "2",
"konendaigakucd": "3",
"weekdaycd": "3",
"wintercd": "3",
"destination": "嚮陽会館",
"list": [
{
"time": "12:00:00",
"busstopid": "45"
},
// *** 中略 ***
{
"time": "12:26:00",
"busstopid": "61"
}
]
},
{
"binid": "3",
"konendaigakucd": "3",
"weekdaycd": "3",
"wintercd": "3",
"destination": "嚮陽会館",
"list": [
{
"time": "15:50:00",
"busstopid": "45"
},
// *** 中略 ***
{
"time": "16:16:00",
"busstopid": "61"
}
]
}
]
}
以前は、heartrails expressというサイトで時刻表データが取得できたのですが、見当たらなくなってしまったので、一つ前の投稿の参考urlで紹介されていた"つつじバス"を見てみます
(heartrails expressのAPIは2015.09頃"公開停止中"というtwitterのログがありました)
http://www.city.sabae.fukui.jp/users/tutujibus/web-api/web-api.html
リクエストURLで簡単そうな例を探すと、02の"路線毎の時刻表データ"が良さそうです
http://www.city.sabae.fukui.jp/users/tutujibus/web-api/02.html
リクエストURLを下記のようにしてデータを取得してみます
http://tutujibus.com/timetableLookup.php/?rosenid=2
結果を整形してみます...の前に、ざっくり構造を調べてみます
timetalbe : 以下の配列
bindid : 便番号 << この便番号毎に配列になっていて、中に時刻表配列が入っている
*** 中略 (ドキュメント参照)
list : 時刻表配列
{
time : 時刻
busstopid : バス停番号
}
binid : 次の便番号
*** 中略 (ドキュメント参照)
list : 時刻表配列
*** 以下同様に続く
となっているようです
{
"timetable": [
{
"binid": "1",
"konendaigakucd": "3",
"weekdaycd": "3",
"wintercd": "3",
"destination": "嚮陽会館",
"list": [
{
"time": "08:55:00",
"busstopid": "45"
},
// *** 中略 ***
{
"time": "09:21:00",
"busstopid": "61"
}
]
},
{
"binid": "2",
"konendaigakucd": "3",
"weekdaycd": "3",
"wintercd": "3",
"destination": "嚮陽会館",
"list": [
{
"time": "12:00:00",
"busstopid": "45"
},
// *** 中略 ***
{
"time": "12:26:00",
"busstopid": "61"
}
]
},
{
"binid": "3",
"konendaigakucd": "3",
"weekdaycd": "3",
"wintercd": "3",
"destination": "嚮陽会館",
"list": [
{
"time": "15:50:00",
"busstopid": "45"
},
// *** 中略 ***
{
"time": "16:16:00",
"busstopid": "61"
}
]
}
]
}
JSONを確認出来るweb toolでRESTのデータを見てみる
RESTで取得したjsonデータをペーストすると、整形してくれるサイトです。
java script(ローカル)で動いているそうなので、心配しなくても良さそう?です。
https://syncer.jp/json-prettyprint
API
wether hacks
http://weather.livedoor.com/weather_hacks/
こちらを整形してもらうと、以下の出力が得られました。
構造としては、
pinpointLocations : valueの配列
link : url
name : 都市名
の配列が続く
link : リクエストしたurl(長野市と思われる2020100になっている)
forecasts : 日付ごとの配列 (今日・明日の2つ)
dataLabel : 日付
telop : 概略
date : 日付
temperature : maxとminのobject
image : 図など
location : 場所の説明
中略
title : タイトル
desctiption : 天気概要
{
"pinpointLocations": [
{
"link": "http://weather.livedoor.com/area/forecast/2020100",
"name": "長野市"
},
{
"link": "http://weather.livedoor.com/area/forecast/2020111",
"name": "長野"
},
{
"link": "http://weather.livedoor.com/area/forecast/2020112",
"name": "鬼無里戸隠"
},
// *** 中略 ***
{
"link": "http://weather.livedoor.com/area/forecast/2060200",
"name": "栄村"
}
],
"link": "http://weather.livedoor.com/area/forecast/200010",
"forecasts": [
{
"dateLabel": "今日",
"telop": "曇のち雪",
"date": "2017-01-09",
"temperature": {
"min": null,
"max": {
"celsius": "6",
"fahrenheit": "42.8"
}
},
"image": {
"width": 50,
"url": "http://weather.livedoor.com/img/icon/14.gif",
"title": "曇のち雪",
"height": 31
}
},
{
"dateLabel": "明日",
"telop": "曇時々雪",
"date": "2017-01-10",
"temperature": {
"min": {
"celsius": "0",
"fahrenheit": "32.0"
},
"max": {
"celsius": "6",
"fahrenheit": "42.8"
}
},
"image": {
"width": 50,
"url": "http://weather.livedoor.com/img/icon/11.gif",
"title": "曇時々雪",
"height": 31
}
},
{
"dateLabel": "明後日",
"telop": "曇時々雪",
"date": "2017-01-11",
"temperature": {
"min": null,
"max": null
},
"image": {
"width": 50,
"url": "http://weather.livedoor.com/img/icon/11.gif",
"title": "曇時々雪",
"height": 31
}
}
],
"location": {
"city": "長野",
"area": "信越・北陸",
"prefecture": "長野県"
},
"publicTime": "2017-01-09T11:00:00+0900",
"copyright": {
"provider": [
{
"link": "http://tenki.jp/",
"name": "日本気象協会"
}
],
"link": "http://weather.livedoor.com/",
"title": "(C) LINE Corporation",
"image": {
"width": 118,
"link": "http://weather.livedoor.com/",
"url": "http://weather.livedoor.com/img/cmn/livedoor.gif",
"title": "livedoor 天気情報",
"height": 26
}
},
"title": "長野県 長野 の天気",
"description": {
"text": " 低気圧が関東の東海上を発達しながら東北東へ進んでいます。\n\n 長野県内は、曇りまたは晴れとなっています。\n\n 9日は、冬型の気圧配置となりますが、寒気の影響を受ける見込みです。\n このため、北部では、曇りで夜は雪となり、雷を伴う所があるでしょう。\n中部と南部では、晴れで夕方からは曇りとなり、中部では夜は雪の降る所が\nあるでしょう。\n\n 10日は、冬型の気圧配置が続きますが、寒気の影響を受ける見込みです\n。\n このため、北部では、曇りで朝晩は雪となり、夜は雷を伴う所があるでし\nょう。中部と南部では、晴れますが、夜は雲が広がり、乗鞍上高地地域では\n雪が降るでしょう。",
"publicTime": "2017-01-09T11:23:00+0900"
}
}
Web APIのサイト紹介
https://wp-d.org/2013/03/14/3348/
java script(ローカル)で動いているそうなので、心配しなくても良さそう?です。
https://syncer.jp/json-prettyprint
API
wether hacks
http://weather.livedoor.com/weather_hacks/
こちらを整形してもらうと、以下の出力が得られました。
構造としては、
pinpointLocations : valueの配列
link : url
name : 都市名
の配列が続く
link : リクエストしたurl(長野市と思われる2020100になっている)
forecasts : 日付ごとの配列 (今日・明日の2つ)
dataLabel : 日付
telop : 概略
date : 日付
temperature : maxとminのobject
image : 図など
location : 場所の説明
中略
title : タイトル
desctiption : 天気概要
{
"pinpointLocations": [
{
"link": "http://weather.livedoor.com/area/forecast/2020100",
"name": "長野市"
},
{
"link": "http://weather.livedoor.com/area/forecast/2020111",
"name": "長野"
},
{
"link": "http://weather.livedoor.com/area/forecast/2020112",
"name": "鬼無里戸隠"
},
// *** 中略 ***
{
"link": "http://weather.livedoor.com/area/forecast/2060200",
"name": "栄村"
}
],
"link": "http://weather.livedoor.com/area/forecast/200010",
"forecasts": [
{
"dateLabel": "今日",
"telop": "曇のち雪",
"date": "2017-01-09",
"temperature": {
"min": null,
"max": {
"celsius": "6",
"fahrenheit": "42.8"
}
},
"image": {
"width": 50,
"url": "http://weather.livedoor.com/img/icon/14.gif",
"title": "曇のち雪",
"height": 31
}
},
{
"dateLabel": "明日",
"telop": "曇時々雪",
"date": "2017-01-10",
"temperature": {
"min": {
"celsius": "0",
"fahrenheit": "32.0"
},
"max": {
"celsius": "6",
"fahrenheit": "42.8"
}
},
"image": {
"width": 50,
"url": "http://weather.livedoor.com/img/icon/11.gif",
"title": "曇時々雪",
"height": 31
}
},
{
"dateLabel": "明後日",
"telop": "曇時々雪",
"date": "2017-01-11",
"temperature": {
"min": null,
"max": null
},
"image": {
"width": 50,
"url": "http://weather.livedoor.com/img/icon/11.gif",
"title": "曇時々雪",
"height": 31
}
}
],
"location": {
"city": "長野",
"area": "信越・北陸",
"prefecture": "長野県"
},
"publicTime": "2017-01-09T11:00:00+0900",
"copyright": {
"provider": [
{
"link": "http://tenki.jp/",
"name": "日本気象協会"
}
],
"link": "http://weather.livedoor.com/",
"title": "(C) LINE Corporation",
"image": {
"width": 118,
"link": "http://weather.livedoor.com/",
"url": "http://weather.livedoor.com/img/cmn/livedoor.gif",
"title": "livedoor 天気情報",
"height": 26
}
},
"title": "長野県 長野 の天気",
"description": {
"text": " 低気圧が関東の東海上を発達しながら東北東へ進んでいます。\n\n 長野県内は、曇りまたは晴れとなっています。\n\n 9日は、冬型の気圧配置となりますが、寒気の影響を受ける見込みです。\n このため、北部では、曇りで夜は雪となり、雷を伴う所があるでしょう。\n中部と南部では、晴れで夕方からは曇りとなり、中部では夜は雪の降る所が\nあるでしょう。\n\n 10日は、冬型の気圧配置が続きますが、寒気の影響を受ける見込みです\n。\n このため、北部では、曇りで朝晩は雪となり、夜は雷を伴う所があるでし\nょう。中部と南部では、晴れますが、夜は雲が広がり、乗鞍上高地地域では\n雪が降るでしょう。",
"publicTime": "2017-01-09T11:23:00+0900"
}
}
Web APIのサイト紹介
https://wp-d.org/2013/03/14/3348/
2017年1月6日金曜日
XCode + Swift2の画面遷移とコード
Viewについては、"Main.storyboard"をGUI操作で画面を作っていくようです。
単一画面の場合は
1. Main.storyboardをクリック
View Controller Sceneが配置されている
2. View ControllerにUIパーツを貼っていく
3. IBAction / IBOutletでViewController.swiftとView controllerを紐付けする
4. ViewController.swiftにコードを書いていく
と言った手順で
- ViewController (View)
- *.swift (ソースコード)
を紐付けて作っていくようです。
画面が二つ以上の場合は、"Navigation Controller"を使う事で画面を切り替えていくようです。
1. Main.storyboard をクリック
View Controller Sceneが配置されている << ここまでは同じ
2. View Controller Sceneを選択
3. メニューの"Editor -> Embed In -> Navigation controller"を選択
> (Document outline = 左から2ペイン目に)Navigation Controller Sceneが追加される
> GUIでMain.Storyboardの"-> Navigation controller -> View Controller"に接続されている事を確認
※ Navigation controlleにより、View controller(defaultの画面)と2画面目を階層的にコントロールできる為に上記そうさをするとの事
4. 1画面目(View controller)の画面を作っていく
> "Bar Button Item"をドラッグするとNavigation Barの中にNavigation Itemが追加される(画面遷移に関連)
2画面目を作る
5. (際左ペインで)MainStory boardを選択
6. Object library(toolboxみたいなの)でview controllerを探して、story board(GUI画面)にドラッグドロップ
> 画面が追加される...但し、矢印は接続されていない
> Document outline (= 左から2ペイン目)にも"View controller Scene"が新たに追加される
Segueを追加する
7. 1画面目(最初からあった画面)から遷移する場合、1画面目をクリック
> 画面上の"View controller"の□が選択される
※ うまく行かなかったので、menu barのボタンからドラッグした
8. command key を押しながら追加した画面(2画面目)にドラッグドロップする
9. 黒い(segue用の)ポップアップが出るので"Show"を選択する
> これにより、1画面目から2画面目に矢印が接続される
> 2画面目上部にもNavigation Barが追加されている
10. Segue object(矢印部分)を選択して-^-(Atribute Inspector)の"Identifier"でSegueの名前を変えられるので、必要に応じて変更する
※ この状態では実行させても、(4で追加したコントロールをクリックして)画面遷移させようとしても出来ない。下記操作をする事
ViewControllerの追加(2画面めに対応した*.swiftの事)
11. Project Navigator(再左ペイン)でFile-> New -> New File をクリック
> "choose a template for your new file"ダイアログが表示される
12. iOS -> Source -> Cocoa Touch Classを選択してnext (上記ダイアログ)
13. クラス名を記載(***ViewControllerとか)
14. sub classをUI View Controllerにする
15. (言語はSwiftのままで)Next、そしてCreateボタん
> ***ViewController.swiftが生成される
ViewController(2画面めのGUI)と紐付けする
16. Main.storyboard -> 2画面目のViewController Scene -> ViewControllerを選択
17. (際右ペインを)Identifer Inspector(-^-の隣の□アイコン)とする
18. Custom classの項目のclassに****ViewControllerを記載する (***ViewController.swiftのクラス名)
> Document outline (= 左から2ペイン目)で"View controller scene"となっていた部分が*** View Controller Seceneに変わる
これで関連付け完了
やり方その1
2画面目から戻る (遷移時と同様、GUIで設定)
19. 決定ボタンなどを追加したら、同様にCtrl + ドラッグで1画面目にドラッグする
20. 同様にIDを設定
やり方その2
2画面目から戻る (コードで記述)
// コードで戻る (返り値対応で、_をつけるらしい) / ボタン押下で戻る
@IBAction func returnButtonAction(sender: AnyObject) {
_ = navigationController?.popViewControllerAnimated(true)
}
とりあえず、これで行ったり来たりは出来るようになった...
参考
https://iphone-app-tec.com/ios/tap_gesture.html
単一画面の場合は
1. Main.storyboardをクリック
View Controller Sceneが配置されている
2. View ControllerにUIパーツを貼っていく
3. IBAction / IBOutletでViewController.swiftとView controllerを紐付けする
4. ViewController.swiftにコードを書いていく
と言った手順で
- ViewController (View)
- *.swift (ソースコード)
を紐付けて作っていくようです。
画面が二つ以上の場合は、"Navigation Controller"を使う事で画面を切り替えていくようです。
1. Main.storyboard をクリック
View Controller Sceneが配置されている << ここまでは同じ
2. View Controller Sceneを選択
3. メニューの"Editor -> Embed In -> Navigation controller"を選択
> (Document outline = 左から2ペイン目に)Navigation Controller Sceneが追加される
> GUIでMain.Storyboardの"-> Navigation controller -> View Controller"に接続されている事を確認
※ Navigation controlleにより、View controller(defaultの画面)と2画面目を階層的にコントロールできる為に上記そうさをするとの事
4. 1画面目(View controller)の画面を作っていく
> "Bar Button Item"をドラッグするとNavigation Barの中にNavigation Itemが追加される(画面遷移に関連)
2画面目を作る
5. (際左ペインで)MainStory boardを選択
6. Object library(toolboxみたいなの)でview controllerを探して、story board(GUI画面)にドラッグドロップ
> 画面が追加される...但し、矢印は接続されていない
> Document outline (= 左から2ペイン目)にも"View controller Scene"が新たに追加される
Segueを追加する
7. 1画面目(最初からあった画面)から遷移する場合、1画面目をクリック
> 画面上の"View controller"の□が選択される
※ うまく行かなかったので、menu barのボタンからドラッグした
8. command key を押しながら追加した画面(2画面目)にドラッグドロップする
9. 黒い(segue用の)ポップアップが出るので"Show"を選択する
> これにより、1画面目から2画面目に矢印が接続される
> 2画面目上部にもNavigation Barが追加されている
10. Segue object(矢印部分)を選択して-^-(Atribute Inspector)の"Identifier"でSegueの名前を変えられるので、必要に応じて変更する
※ この状態では実行させても、(4で追加したコントロールをクリックして)画面遷移させようとしても出来ない。下記操作をする事
ViewControllerの追加(2画面めに対応した*.swiftの事)
11. Project Navigator(再左ペイン)でFile-> New -> New File をクリック
> "choose a template for your new file"ダイアログが表示される
12. iOS -> Source -> Cocoa Touch Classを選択してnext (上記ダイアログ)
13. クラス名を記載(***ViewControllerとか)
14. sub classをUI View Controllerにする
15. (言語はSwiftのままで)Next、そしてCreateボタん
> ***ViewController.swiftが生成される
ViewController(2画面めのGUI)と紐付けする
16. Main.storyboard -> 2画面目のViewController Scene -> ViewControllerを選択
17. (際右ペインを)Identifer Inspector(-^-の隣の□アイコン)とする
18. Custom classの項目のclassに****ViewControllerを記載する (***ViewController.swiftのクラス名)
> Document outline (= 左から2ペイン目)で"View controller scene"となっていた部分が*** View Controller Seceneに変わる
これで関連付け完了
やり方その1
2画面目から戻る (遷移時と同様、GUIで設定)
19. 決定ボタンなどを追加したら、同様にCtrl + ドラッグで1画面目にドラッグする
20. 同様にIDを設定
やり方その2
2画面目から戻る (コードで記述)
// コードで戻る (返り値対応で、_をつけるらしい) / ボタン押下で戻る
@IBAction func returnButtonAction(sender: AnyObject) {
_ = navigationController?.popViewControllerAnimated(true)
}
とりあえず、これで行ったり来たりは出来るようになった...
参考
https://iphone-app-tec.com/ios/tap_gesture.html
2017年1月5日木曜日
jsonのdataを取得して解析する
urlからdataを取得する辺りから書くと下記のような感じ
class ViewController: UIViewController,NSXMLParserDelegate {
@IBOutlet weak var jsonTextView: UITextView!
@IBAction func Button_GetJson(sender: AnyObject) {
// let url:NSURL = NSURL(string: "http://editors.ascii.jp/c-minamoto/swift/swift-5-data.xml")!
// let request = NSURLRequest(URL: url)
//make URL of google feed api
let urlString = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=http://rss.itmedia.co.jp/rss/2.0/news_bursts.xml&num=8"
let url = NSURL(string: urlString)
// var titles:String = ""
//download by NSSession
let task = NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler:{data, response, error in
//convert json data to dictionary
var dict:NSDictionary
do {
dict = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
//get responseData, feed, entries
let responseData = dict["responseData"] as! NSDictionary
let feed = responseData["feed"] as! NSDictionary
let entries = feed["entries"] as! NSArray
//extract entries
// print(entries.count)
var titles:String = ""
for entry in entries {
// print(entry["title"])
let title:String = entry["title"] as! String
titles += title + ":"
}
// print(titles)
dispatch_async(dispatch_get_main_queue()){
self.jsonTextView.text = titles
}
} catch {
print("error")
return
}
// print(dict)
})
task.resume()
// self.jsonTextView.text = titles
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
class ViewController: UIViewController,NSXMLParserDelegate {
@IBOutlet weak var jsonTextView: UITextView!
@IBAction func Button_GetJson(sender: AnyObject) {
// let url:NSURL = NSURL(string: "http://editors.ascii.jp/c-minamoto/swift/swift-5-data.xml")!
// let request = NSURLRequest(URL: url)
//make URL of google feed api
let urlString = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=http://rss.itmedia.co.jp/rss/2.0/news_bursts.xml&num=8"
let url = NSURL(string: urlString)
// var titles:String = ""
//download by NSSession
let task = NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler:{data, response, error in
//convert json data to dictionary
var dict:NSDictionary
do {
dict = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
//get responseData, feed, entries
let responseData = dict["responseData"] as! NSDictionary
let feed = responseData["feed"] as! NSDictionary
let entries = feed["entries"] as! NSArray
//extract entries
// print(entries.count)
var titles:String = ""
for entry in entries {
// print(entry["title"])
let title:String = entry["title"] as! String
titles += title + ":"
}
// print(titles)
dispatch_async(dispatch_get_main_queue()){
self.jsonTextView.text = titles
}
} catch {
print("error")
return
}
// print(dict)
})
task.resume()
// self.jsonTextView.text = titles
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
2017年1月3日火曜日
jsonのdataをswift2で解析する
取得するデータの構造は
responseData:
feed:
value
feeUrl : "value"
... // *** 以下"キー:value"のメンバが続く
entries: // *** ここがおめあて
value配列
...
とした場合、以下コードで最終亭なentriesキーのvalue配列が取得できました。
var dict:NSDictionary
dict = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
//get responseData, feed, entries
let responseData = dict["responseData"] as! NSDictionary // dictからresponseDataキーを探す
let feed = responseData["feed"] as! NSDictionary // responseData からfeedキーを探す
let entries = feed["entries"] as! NSArray // feedからentriesを探す..."entries"が配列として格納
entriesの配列の各titleを表示させる場合は以下になります。
//extract entries
// print(entries.count)
var titles:String = ""
for entry in entries {
// print(entry["title"])
let title:String = entry["title"] as! String
titles += title + ":"
}
// print(titles)
dispatch_async(dispatch_get_main_queue()){
self.jsonTextView.text = titles
}
responseData:
feed:
value
feeUrl : "value"
... // *** 以下"キー:value"のメンバが続く
entries: // *** ここがおめあて
value配列
...
とした場合、以下コードで最終亭なentriesキーのvalue配列が取得できました。
var dict:NSDictionary
dict = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
//get responseData, feed, entries
let responseData = dict["responseData"] as! NSDictionary // dictからresponseDataキーを探す
let feed = responseData["feed"] as! NSDictionary // responseData からfeedキーを探す
let entries = feed["entries"] as! NSArray // feedからentriesを探す..."entries"が配列として格納
entriesの配列の各titleを表示させる場合は以下になります。
//extract entries
// print(entries.count)
var titles:String = ""
for entry in entries {
// print(entry["title"])
let title:String = entry["title"] as! String
titles += title + ":"
}
// print(titles)
dispatch_async(dispatch_get_main_queue()){
self.jsonTextView.text = titles
}
2017年1月2日月曜日
Jsonで取得したデータは??
いろいろなページを参考にさせていただき、swiftでjsonを取得できました。
順序が逆になりますが、「実際はどんな風になっているか」を先に見てみます。
おそらく、"[]"については見えていないので、解る部分を見てみます。
取得したデータを字下げすると..(あと、注釈を追記)
{"responseData": // *** ここのキーに対して、以下がvalueになる
{"feed": // *** ここのキーに対して、以下がvalueになる
{ "feedUrl":"http://rss.itmedia.co.jp/rss/2.0/news_bursts.xml", // *** キーとvalueのペアが続く
"title":"ITmedia News 速報 最新記事一覧",
"link":"http://www.itmedia.co.jp/news/bursts/",
"author":"",
"description":"ITmedia News 速報 の最新記事一覧です。",
"type":"rss20",
"entries":[ // *** ここから"entries"キーに対するvalueの配列が続く
{ // *** "num=8"で要求したから? "entries"は8要素
"title":"Raspberry Piの「PIXEL」が旧型PCやMacで稼働可能に",
"link":"http://rss.rssad.jp/rss/artclk/XXtgw_wVjwMW/aa457f16b6ee2da4867bda91a84c3112?ul\u003dsWKI1zepQzDjpc7XC5rf2ewet1rxJmiV3BfQpFpgnr_Gr3.DNzTmu3CCs_zsy5TrxdEQvaf_o0e.p0eWYi3NUsxMHLApbJ70ELi0D_9ACLaN8lSZTT7.lFJN5cfjipmt5hi0Set",
"author":"",
"publishedDate":"Thu, 22 Dec 2016 14:18:00 -0800",
"contentSnippet":"小型コンピュータ「Raspberry Pi」のデスクトップ環境「PIXEL」のx86版が公開された。まだ実験的な段階だが、USBメモリに入れて起動ディスクとし、古いPCやMacでブートできる。\n",
"content":"\u003cp\u003e小型コンピュータ「Raspberry Pi」のデスクトップ環境「PIXEL」のx86版が公開された。まだ実験的な段階だが、USBメモリに入れて起動ディスクとし、古いPCやMacでブートできる。\n\u003cimg border\u003d\"0\" width\u003d\"1\" height\u003d\"1\" src\u003d\"http://rss.rssad.jp/rss/artimg/XXtgw_wVjwMW/aa457f16b6ee2da4867bda91a84c3112\"\u003e\u003c/p\u003e",
"categories":[]
}, // *** ここまでが"entries"キーに対するvalueの配列の一つ目、そして次のvalueが続く
...
まとめると、以下のような感じと思ってます
responseData:
feed:
value
feeUrl : "value"
... // *** 以下"キー:value"のメンバが続く
entries: // *** ここがおめあて
value配列
...
具体的にswiftで取得する方法は次回
順序が逆になりますが、「実際はどんな風になっているか」を先に見てみます。
おそらく、"[]"については見えていないので、解る部分を見てみます。
取得したデータを字下げすると..(あと、注釈を追記)
{"responseData": // *** ここのキーに対して、以下がvalueになる
{"feed": // *** ここのキーに対して、以下がvalueになる
{ "feedUrl":"http://rss.itmedia.co.jp/rss/2.0/news_bursts.xml", // *** キーとvalueのペアが続く
"title":"ITmedia News 速報 最新記事一覧",
"link":"http://www.itmedia.co.jp/news/bursts/",
"author":"",
"description":"ITmedia News 速報 の最新記事一覧です。",
"type":"rss20",
"entries":[ // *** ここから"entries"キーに対するvalueの配列が続く
{ // *** "num=8"で要求したから? "entries"は8要素
"title":"Raspberry Piの「PIXEL」が旧型PCやMacで稼働可能に",
"link":"http://rss.rssad.jp/rss/artclk/XXtgw_wVjwMW/aa457f16b6ee2da4867bda91a84c3112?ul\u003dsWKI1zepQzDjpc7XC5rf2ewet1rxJmiV3BfQpFpgnr_Gr3.DNzTmu3CCs_zsy5TrxdEQvaf_o0e.p0eWYi3NUsxMHLApbJ70ELi0D_9ACLaN8lSZTT7.lFJN5cfjipmt5hi0Set",
"author":"",
"publishedDate":"Thu, 22 Dec 2016 14:18:00 -0800",
"contentSnippet":"小型コンピュータ「Raspberry Pi」のデスクトップ環境「PIXEL」のx86版が公開された。まだ実験的な段階だが、USBメモリに入れて起動ディスクとし、古いPCやMacでブートできる。\n",
"content":"\u003cp\u003e小型コンピュータ「Raspberry Pi」のデスクトップ環境「PIXEL」のx86版が公開された。まだ実験的な段階だが、USBメモリに入れて起動ディスクとし、古いPCやMacでブートできる。\n\u003cimg border\u003d\"0\" width\u003d\"1\" height\u003d\"1\" src\u003d\"http://rss.rssad.jp/rss/artimg/XXtgw_wVjwMW/aa457f16b6ee2da4867bda91a84c3112\"\u003e\u003c/p\u003e",
"categories":[]
}, // *** ここまでが"entries"キーに対するvalueの配列の一つ目、そして次のvalueが続く
...
まとめると、以下のような感じと思ってます
responseData:
feed:
value
feeUrl : "value"
... // *** 以下"キー:value"のメンバが続く
entries: // *** ここがおめあて
value配列
...
具体的にswiftで取得する方法は次回
2017年1月1日日曜日
jsonって??
最近はXMLからJSONに移行しつつあるそうです。
(SOAP->REST, XML->JSONなんですかね)
urlからデータを取得すると複雑な感じですが、基本は下記のような感じだそうです。
[
{
"番号":0,"タイトル":"とある本","ISBN":12345678
},
{
"番号":1,"タイトル":"次に読む本","ISBN":2345678, "ユーザ":["mr a", "mr b", "miss a"]
},
...
]
読み方は以下が基本のようです
{...} オブジェクトの表記(カッコ内がオブジェクト)
key:value ペアをコロンで記述する。ペアが複数ある場合はカンマで区切る << "メンバー"というようです
["value a", "value b", value c"] valueを配列で表すことができる
こちらのページが参考になりました
http://dev.classmethod.jp/etc/concrete-example-of-json/
(SOAP->REST, XML->JSONなんですかね)
urlからデータを取得すると複雑な感じですが、基本は下記のような感じだそうです。
[
{
"番号":0,"タイトル":"とある本","ISBN":12345678
},
{
"番号":1,"タイトル":"次に読む本","ISBN":2345678, "ユーザ":["mr a", "mr b", "miss a"]
},
...
]
読み方は以下が基本のようです
{...} オブジェクトの表記(カッコ内がオブジェクト)
key:value ペアをコロンで記述する。ペアが複数ある場合はカンマで区切る << "メンバー"というようです
["value a", "value b", value c"] valueを配列で表すことができる
こちらのページが参考になりました
http://dev.classmethod.jp/etc/concrete-example-of-json/
登録:
投稿 (Atom)