Swift와 Hexaville에서 역 탐색 API를 만들어 보았습니다.

안녕하세요.
니지 박스에서 네이티브 앱을 개발하는 경우가 많습니다 @ochim.

동기 부여


  • 위도 경도에서 근처의 역을 취득하는 API를 찾아 보았지만, 간편하게 사용할 수 없다.

  • SimpleAPI 라든지 https가 아니다
  • 서버 측 Swift를 사용해보고 싶습니다

  • 준비



  • Hexaville 설치.
  • curl -L https://rawgit.com/noppoMan/Hexaville/master/install.sh | bash
    source ~/.bashrc
    

  • 역 데이터.jp에서 역 데이터 다운로드 (회원 등록 필요)

  • Hexaville는 간단하게 말하면, Swift를 위한 현대 웹 응용 기구 및 엔진입니다. Swift로 만든 웹 앱을 AWS Lambda와 ApiGateway에서 실행하는 것을 컨셉으로 하고 있다고 합니다. 자세한 내용은 링크 대상

    환경


  • Mac OS 10.12.6
  • Swift 4.0
  • Xcode 9.2

  • 프로젝트 만들기


    hexaville generate NearStations
    cd NearStations
    swift package generate-xcodeproj
    

    이제 xcodeproj 파일이 생성되므로 나중에 Xcode에서 개발할 수 있습니다.

    이번 소스 구성





    구현



    로직 부분을 노출합니다.

    Convert.swift
    import Foundation
    import HexavilleFramework
    
    struct Convert {
    
        static func convertCSV() -> [[String]] {
            do {
                let asset = AssetLoader.shared.availableAbsolutePathForAssets()
                let csvPath = "\(asset!)/station20171109free.csv"
                let csvStr = try String(contentsOfFile:csvPath, encoding:String.Encoding.utf8)
    
                var result: [[String]] = []
                let rows = csvStr.components(separatedBy: .newlines)
                for row in rows {
                    let columns = row.components(separatedBy: ",")
                    result.append(columns)
                }
                result.remove(at: result.count-1)
    
                return result
    
            } catch {
                return []
            }
        }
    }
    

    역 데이터의 csv를 받아서 배열화하고 있습니다.

    Station.swift
    import Foundation
    
    struct Station {
    
        func radians (deg: Double) -> Double {
            return deg * Double.pi / 180
        }
    
        func rectangularCoordinateSystem (lat: Double, lng: Double) -> (Double,Double,Double) {
            let h = radians(deg:lat)
            let t = radians(deg:lng)
            let x = cos(h) * cos(t)
            let y = cos(h) * sin(t)
            let z = sin(h)
            return (x, y, z)
        }
    
        func calcDistance(lat1: Double, lng1: Double, lat2: Double, lng2: Double) -> Double{
            let Re = 6378.137 // 地球の半径
            let (x1, y1, z1) = rectangularCoordinateSystem(lat:lat1, lng:lng1)
            let (x2, y2, z2) = rectangularCoordinateSystem(lat:lat2, lng:lng2)
            return Re * acos(x1*x2 + y1*y2 + z1*z2)
        }
    
        /** 付近の駅を取得 **/
        func getNearStations (lat: Double, lng: Double) -> [[String:String]] {
    
            let stations = Convert.convertCSV()
    
            var array: [[String:String]] = []
            for station:[String] in stations {
                var dic :[String:String] = [:]
                let distance = calcDistance(lat1:lat, lng1:lng, lat2:atof(station[10]), lng2:atof(station[9]))
                dic["km"] = String(format:"%f", distance)
                dic["name"] = station[2]
                array.append(dic)
            }
            array = array.sorted(by: { $0["km"]! < $1["km"]! })
            return array[0...2].map{$0}
        }
    
    }
    

    getNearStations() 로 부근의 역을 가까운 순서로 3건 취득하고 있습니다.
    두 지점의 위도 경도에서 거리를 계산하는 데 사용 된 방법은 여기

    동작 확인



    로컬에서 실행 및 확인



    니지 박스가 들어있는 건물에서 시도해 봅시다. 위도: 35.660944, 경도: 139.775199



    좋아!
    부근의 역 3건의 이름과 거리를 표시하고 있습니다.

    이대로 배포하거나 곳 입니다만,
    호흡 곤란했기 때문에 배포는 다음에 따로 유지됩니다.

    소스 코드를 github에 올렸습니다. 여기

    참고


  • Lambda에서 가장 가까운 역 검색 API를 만들어 보았습니다.
    이 페이지의 Javascript를 Swift로 다시 작성한 느낌입니다. 감사합니다!
  • 서버리스 서버측 Swift와 Hexaville

  • 배포했습니다.



    다른 기사

    좋은 웹페이지 즐겨찾기