指定されたIPアドレスの位置情報(geo location)を検索して、アラートダイアログ上に拡大レベルの異なる4つの地図を表示するAppleScriptです。
IP Goecodingのサービスはipinfo.ioを利用しています。ただ、この手のサービスは入れ替わりが激しいので、長期的に使い続けられることを期待できないと感じています(有償サービスは別)。
このズームレベルが異なる地図の同時表示Viewは、作成したときには「これは画期的!」「ものすごく使いやすい!」と、狂喜乱舞したものですが、他のユーザーに見せてデモしたら、
「実際には限定されたエリア内の位置データを見ることが多いので、World LevelとかCountry Levelのビューは無駄なことが多い」
「地球を侵略しに来た異星人には向いているが、地球人向けには冗長」
といった意見が多く、オクラ入りしていました。アラートダイアログでさまざまなデータを可視化する部品の整備計画時に倉庫から引っ張り出されてきたものです。
唯一、IPアドレスという「見ただけではどこの国のものだかわからない」(Class AのIPは別。17.のAppleとか)データを可視化するときにはバッチリ合っています。
macOS 10.12〜10.14で確認していますが、唯一、macOS 10.14.4上では初期状態でピンが表示されません。ピン自体は存在しているので、地図表示タイプを変更すると表示されるのですが、一体これはどうしたものか。仕様なのかバグなのかわかりません。
▲なぜか本Blogにロス市警からのアクセスが(汗)
▲macOS 10.12.6 Map
▲macOS 10.12.6 Satellite
▲macOS 10.12.6 Map + Satellite
▲macOS 10.13.6 Map
▲macOS 10.14.4 Map (Light Mode)
▲macOS 10.14.4 Map (Dark Mode)
AppleScript名:アラートダイアログ上に複数のNSBoxを作成してMKMapViewを表示 |
— Created 2019-03-11 by Takaaki Naganoya — 2019 Piyomaru Software use AppleScript version "2.5" use scripting additions use framework "Foundation" use framework "AppKit" use framework "MapKit" use framework "CoreLocation" property NSAlert : a reference to current application’s NSAlert property NSString : a reference to current application’s NSString property NSScreen : a reference to current application’s NSScreen property MKMapView : a reference to current application’s MKMapView property MKMapTypeHybrid : a reference to current application’s MKMapTypeHybrid property MKPointAnnotation : a reference to current application’s MKPointAnnotation property NSJSONSerialization : a reference to current application’s NSJSONSerialization property MKMapTypeSatellite : a reference to current application’s MKMapTypeSatellite property MKMapTypeStandard : a reference to current application’s MKMapTypeStandard property NSSegmentedControl : a reference to current application’s NSSegmentedControl property NSRunningApplication : a reference to current application’s NSRunningApplication property NSUTF8StringEncoding : a reference to current application’s NSUTF8StringEncoding property NSSegmentStyleTexturedRounded : a reference to current application’s NSSegmentStyleTexturedRounded property windisp : false property selSeg : 0 property aMapViewList : {} property segTitleList : {"Map", "Satellite", "Satellite + Map"} property returnCode : 0 set aClip to the clipboard –このへんてきとう set anIP to text returned of (display dialog "Input IP address to find its location" default answer aClip) set windisp to false set geoInfo to getGeoLocationByIPinfo(anIP) of me if geoInfo = missing value then error "Network Error" end if set aInfo to loc of geoInfo set aPos to offset of "," in aInfo set aLatitude to text 1 thru (aPos – 1) of aInfo set aLongitude to text (aPos + 1) thru -1 of aInfo set aWidth to 1000 set aHeight to 600 set aButtonMSG to "OK" set aMapViewList to {} set paramObj to {viewWidth:aWidth, viewHeight:aHeight, viewTitle:anIP, viewSubTitle:"IP-Geocoding Service by ipinfo.io", viewLat:aLatitude, viewLong:aLongitude} my performSelectorOnMainThread:"dispMapViewinDifferentScales:" withObject:(paramObj) waitUntilDone:true on dispMapViewinDifferentScales:paramObj set aWidth to (viewWidth of paramObj) as real set aHeight to (viewHeight of paramObj) as real set aLat to (viewLat of paramObj) as real set aLong to (viewLong of paramObj) as real set aTitle to (viewTitle of paramObj) as string set aSubTitle to (viewSubTitle of paramObj) as string set selSeg to 0 –NSViewをつくる set aView to current application’s NSView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight)) –各レベルのMapViewをBoxでつくる set wList to {{3, "🌏World Level Map"}, {5, "🏰Country Level Map"}, {10, "🏢City Level Map"}, {17, "🏠Town Level Map"}} set xPos to 0 repeat with i in wList copy i to {aLevelNum, aBoxTitle} –Boxをつくる set aBox to (current application’s NSBox’s alloc()’s initWithFrame:(current application’s NSMakeRect(xPos, 40, aWidth * 0.25, aHeight – 70))) (aBox’s setTitle:aBoxTitle) –MapView+Pinをつくる set aMapView to makeMKMapView(aWidth * 0.25, aHeight – 70, aLevelNum, aLat, aLong, aTitle) of me (aBox’s addSubview:aMapView) (aView’s addSubview:aBox) set the end of aMapViewList to aMapView set xPos to xPos + (aWidth * 0.25) end repeat –Segmented Controlをつくる set aSeg to makeSegmentedControl(segTitleList, aWidth, aHeight) of me aView’s addSubview:aSeg — set up alert set theAlert to NSAlert’s alloc()’s init() tell theAlert its setMessageText:aTitle its setInformativeText:aSubTitle its addButtonWithTitle:"OK" its addButtonWithTitle:"Cancel" its setAccessoryView:aView end tell — show alert in modal loop NSRunningApplication’s currentApplication()’s activateWithOptions:0 my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true if (my returnCode as number) = 1001 then error number -128 end dispMapViewinDifferentScales: on doModal:aParam set (my returnCode) to aParam’s runModal() end doModal: –MKMapViewをつくる on makeMKMapView(aWidth, aHeight, aZoomLevel, aLat, aLong, aTitle) set aMapView to MKMapView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight)) aMapView’s setMapType:(current application’s MKMapTypeStandard) aMapView’s setZoomEnabled:true aMapView’s setScrollEnabled:true aMapView’s setPitchEnabled:false aMapView’s setRotateEnabled:false aMapView’s setShowsCompass:true aMapView’s setShowsZoomControls:true aMapView’s setShowsScale:true aMapView’s setShowsUserLocation:true set aLocation to current application’s CLLocationCoordinate2DMake(aLat, aLong) aMapView’s setCenterCoordinate:aLocation zoomLevel:aZoomLevel animated:false aMapView’s setDelegate:me –MapにPinを追加 set anAnnotation to current application’s MKPointAnnotation’s alloc()’s init() anAnnotation’s setCoordinate:aLocation anAnnotation’s setTitle:aTitle aMapView’s addAnnotation:anAnnotation return aMapView end makeMKMapView –Make Segmented Control on makeSegmentedControl(titleList, aWidth, aHeight) set aLen to length of titleList set aSeg to NSSegmentedControl’s alloc()’s init() aSeg’s setSegmentCount:aLen set aCount to 0 repeat with i in titleList set j to contents of i (aSeg’s setLabel:j forSegment:aCount) set aCount to aCount + 1 end repeat aSeg’s setTranslatesAutoresizingMaskIntoConstraints:false aSeg’s setSegmentStyle:(NSSegmentStyleTexturedRounded) aSeg’s setFrame:(current application’s NSMakeRect(10, 5, 260, 30)) aSeg’s setTrackingMode:0 aSeg’s setTarget:me aSeg’s setAction:"clickedSeg:" aSeg’s setSelectedSegment:0 return aSeg end makeSegmentedControl –Segmented Control’s clicked event handler on clickedSeg:aSender set aSel to aSender’s selectedSegment() set selSeg to (aSel + 1) set mapList to {MKMapTypeStandard, MKMapTypeSatellite, MKMapTypeHybrid} set curMap to contents of item selSeg of mapList repeat with i in aMapViewList set aView to contents of i (aView’s setMapType:(curMap)) end repeat end clickedSeg: –http://ipinfo.io/developers on getGeoLocationByIPinfo(myIP) set aURL to "http://ipinfo.io/" & myIP set aRes to callRestGETAPIAndParseResults(aURL, 10) of me return aRes as record end getGeoLocationByIPinfo on callRestGETAPIAndParseResults(reqURLStr as string, timeoutSec as integer) set tmpData to (do shell script "curl -X GET \"" & reqURLStr & "\"") set jsonString to NSString’s stringWithString:tmpData set jsonData to jsonString’s dataUsingEncoding:(NSUTF8StringEncoding) set aJsonDict to NSJSONSerialization’s JSONObjectWithData:jsonData options:0 |error|:(missing value) if aJsonDict = missing value then return false return (aJsonDict as record) end callRestGETAPIAndParseResults on retURLwithParams(aBaseURL, aRec) set aDic to NSMutableDictionary’s dictionaryWithDictionary:aRec set aKeyList to (aDic’s allKeys()) as list set aValList to (aDic’s allValues()) as list set aLen to length of aKeyList set qList to {} repeat with i from 1 to aLen set aName to contents of item i of aKeyList set aVal to contents of item i of aValList set the end of qList to (NSURLQueryItem’s queryItemWithName:aName value:aVal) end repeat set aComp to NSURLComponents’s alloc()’s initWithString:aBaseURL aComp’s setQueryItems:qList set aURL to (aComp’s |URL|()’s absoluteString()) as text return aURL end retURLwithParams |