3

On a recent application that I am developing user location is essential. To get the location of the user we are using a location manager. Unfortunately this only works if the user has location services enabled and gives permission to access it.

If the user does not give permission we are only left we a couple of ip services that are not very accurate. I am trying to find a way that I can have approximate user location without location services enabled and that it is better that the ip services.

The only promising API is the Google Maps Geolocation API, which claims that it can get user location using cell towers and wifi nodes.

I tried to find a library or a way that I can use that on iOS and preferably Swift without success. Can anyone help?

Brian
  • 14,610
  • 7
  • 35
  • 43
zirinisp
  • 9,971
  • 5
  • 32
  • 38
  • 1
    If you basically break into the user's location data after they have refused to give it to you, your app will not make it to the app store. If you want general purpose information, use the locales set by the user. – Quantaliinuxite Feb 29 '16 at 16:49
  • If location services are disabled then the best you will do in iOS is IP address. The Google API requires details of visible cell towers and/or wifi networks which you can't get on iOS so it too will just fall back to ip and as @Quantaliinuxite said, if the user wanted your app to have their location they would give it to you – Paulw11 Feb 29 '16 at 19:53
  • @Quantaliinuxite I am not looking to break into the user's location data, as I am aware that the application will be refused. I was just trying to find if there is a better solution than the IP Address. Google Geolocation API looked promising, but since you cannot get the required details (as Paulw11 mentioned) for it to function, then it cannot be used. – zirinisp Mar 01 '16 at 12:14

2 Answers2

2

I'm using the user's timezone to get an approximate location, which I only use to set my apps theme and map style (it's a navigation app) based on sun-up or sun-down.

I use below function and have a plist 'lookup table'. The coordinates in lookup table are central coordinates for that timezone. So, if a user it outside his own timezone it will give you the 'wrong' location.

func getLastKnownLocationFromTimeZone() {
    var timeZonesArray: NSMutableArray!
    if let path = Bundle.main.path(forResource: "NSTimeZoneCoordinates", ofType: "plist") {
        timeZonesArray = NSMutableArray(contentsOfFile: path)
        for timeZoneDictionary in timeZonesArray {
            if let tzDic = timeZoneDictionary as? NSDictionary {
                if let timeZoneName = tzDic["NSTimeZoneName"] as? String {
                    if timeZoneName == TimeZone.autoupdatingCurrent.identifier {
                        let lat = tzDic["Lat"] as! String
                        let lon = tzDic["Lon"] as! String
                        lastKnownLocation = CLLocation(latitude: lat.doubleValue(), longitude: lon.doubleValue())
                        return
                    }
                }
            }
        }

    }
}

plist sample:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <dict>
        <key>Lat</key>
        <string>5.316667</string>
        <key>Lon</key>
        <string>-4.033333</string>
        <key>NSTimeZoneName</key>
        <string>Africa/Abidjan</string>
    </dict>
    <dict>
        <key>Lat</key>
        <string>5.55</string>
        <key>Lon</key>
        <string>-0.2</string>
        <key>NSTimeZoneName</key>
        <string>Africa/Accra</string>
    </dict>
    <dict>
        <key>Lat</key>
        <string>8.980603</string>
        <key>Lon</key>
        <string>38.757761</string>
        <key>NSTimeZoneName</key>
        <string>Africa/Addis_Ababa</string>
    </dict>
    <dict>
        <key>Lat</key>
        <string>36.752887</string>
        <key>Lon</key>
        <string>3.042048</string>
        <key>NSTimeZoneName</key>
        <string>Africa/Algiers</string>
    </dict>
    <dict>
        <key>Lat</key>
        <string>15.333333</string>
        <key>Lon</key>
        <string>38.933333</string>
        <key>NSTimeZoneName</key>
        <string>Africa/Asmara</string>
    </dict>
    <dict>
        <key>Lat</key>
        <string>12.65</string>
        <key>Lon</key>
        <string>-8</string>
        <key>NSTimeZoneName</key>
        <string>Africa/Bamako</string>
    </dict>
    <dict>
        <key>Lat</key>
        <string>4.366667</string>
        <key>Lon</key>
        <string>18.583333</string>
        <key>NSTimeZoneName</key>
        <string>Africa/Bangui</string>
    </dict>
    <dict>
        <key>Lat</key>
        <string>13.453056</string>
        <key>Lon</key>
        <string>-16.5775</string>
        <key>NSTimeZoneName</key>
        <string>Africa/Banjul</string>
    </dict>
    <dict>
        <key>Lat</key>
        <string>11.881655</string>
        <key>Lon</key>
        <string>-15.617794</string>
        <key>NSTimeZoneName</key>
        <string>Africa/Bissau</string>
    </dict>
    <dict>
        <key>Lat</key>
        <string>-15.786111</string>
        <key>Lon</key>
        <string>35.005833</string>
        <key>NSTimeZoneName</key>
        <string>Africa/Blantyre</string>
    </dict>
    <dict>
        <key>Lat</key>
        <string>-4.267778</string>
        <key>Lon</key>
        <string>15.291944</string>
        <key>NSTimeZoneName</key>
        <string>Africa/Brazzaville</string>
    </dict>
    <dict>
        <key>Lat</key>
        <string>-3.383333</string>
        <key>Lon</key>
        <string>29.366667</string>
        <key>NSTimeZoneName</key>
        <string>Africa/Bujumbura</string>
    </dict>
    <dict>
        <key>Lat</key>
        <string>30.119799</string>
        <key>Lon</key>
        <string>31.537</string>
        <key>NSTimeZoneName</key>
        <string>Africa/Cairo</string>
    </dict>
    <dict>
        <key>Lat</key>
        <string>33.57311</string>
        <key>Lon</key>
        <string>-7.589843</string>
        <key>NSTimeZoneName</key>
        <string>Africa/Casablanca</string>
    </dict>
    <dict>
        <key>Lat</key>
        <string>35.889387</string>
        <key>Lon</key>
        <string>-5.321346</string>
        <key>NSTimeZoneName</key>
        <string>Africa/Ceuta</string>

Sorry, it's too long to paste the whole plist here. If you want it leave a comment.

guido
  • 2,792
  • 1
  • 21
  • 40
0

Unfortunately there is no way to do that, as the operating system does not provide access to any alternative methods of determining the location of the user (cell towers, etc).

To be honest this makes sense, as if the user wanted the application to have access to his location he would have given us permission.

That is the reason Google Geolocation API cannot work on iOS.

The only workaround is using IP Address, but the accuracy there is almost country wide.

zirinisp
  • 9,971
  • 5
  • 32
  • 38