From apple's documentation
Important: In addition to hardware not being available, the user has
the option of denying an application’s access to location service
data. During its initial uses by an application, the Core Location
framework prompts the user to confirm that using the location service
is acceptable. If the user denies the request, the CLLocationManager
object reports an appropriate error to its delegate during future
requests. You can also check the application’s explicit authorization
status using the authorizationStatus method.
So even if there exist some tricky way to avoid permission, you will be rejected at review stage.
What other way do you suggest to guess what country the user is
located?
You can get this information by using ip address.
Swift 4 - Get device's IP Address:
Add #include<ifaddrs.h> in your bridging header.
This is the framework needed to get IP address.
class func getIPAddress() -> String? {
var address: String?
var ifaddr: UnsafeMutablePointer<ifaddrs>? = nil
if getifaddrs(&ifaddr) == 0 {
var ptr = ifaddr
while ptr != nil {
defer { ptr = ptr?.pointee.ifa_next }
let interface = ptr?.pointee
let addrFamily = interface?.ifa_addr.pointee.sa_family
if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {
if let name: String = String(cString: (interface?.ifa_name)!), name == "en0" {
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
getnameinfo(interface?.ifa_addr, socklen_t((interface?.ifa_addr.pointee.sa_len)!), &hostname, socklen_t(hostname.count), nil, socklen_t(0), NI_NUMERICHOST)
address = String(cString: hostname)
}
}
}
freeifaddrs(ifaddr)
}
return address
}
Get country using ip address
You could start by trying http://ip-api.com/json, which returns a JSON as explained on their API page.
You can then convert this JSON string to a dictionary and access the data.
func getIpLocation(completion: @escaping(NSDictionary?, Error?) -> Void)
{
let url = URL(string: "http://ip-api.com/json")!
var request = URLRequest(url: url)
request.httpMethod = "GET"
URLSession.shared.dataTask(with: request as URLRequest, completionHandler:
{ (data, response, error) in
DispatchQueue.main.async
{
if let content = data
{
do
{
if let object = try JSONSerialization.jsonObject(with: content, options: .allowFragments) as? NSDictionary
{
completion(object, error)
}
else
{
// TODO: Create custom error.
completion(nil, nil)
}
}
catch
{
// TODO: Create custom error.
completion(nil, nil)
}
}
else
{
completion(nil, error)
}
}
}).resume()
}
This function returns the dictionary or an error (after you resolve the TODO's). The completion is called on the main thread assuming you'll use the result to update the UI. If not, you can remove the DispatchQueue.main.async { }.