I found this sample code to get all local IP addresses, but I don't find an easy solution to get the public IP.
A legacy class from Apple allowed to do that ... but it's legacy ...
I found this sample code to get all local IP addresses, but I don't find an easy solution to get the public IP.
A legacy class from Apple allowed to do that ... but it's legacy ...
I have used ALSystemUtilities in the past. You basically have to make a call externally to find this out.
+ (NSString *)externalIPAddress {
// Check if we have an internet connection then try to get the External IP Address
if (![self connectedViaWiFi] && ![self connectedVia3G]) {
// Not connected to anything, return nil
return nil;
}
// Get the external IP Address based on dynsns.org
NSError *error = nil;
NSString *theIpHtml = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://www.dyndns.org/cgi-bin/check_ip.cgi"]
encoding:NSUTF8StringEncoding
error:&error];
if (!error) {
NSUInteger an_Integer;
NSArray *ipItemsArray;
NSString *externalIP;
NSScanner *theScanner;
NSString *text = nil;
theScanner = [NSScanner scannerWithString:theIpHtml];
while ([theScanner isAtEnd] == NO) {
// find start of tag
[theScanner scanUpToString:@"<" intoString:NULL] ;
// find end of tag
[theScanner scanUpToString:@">" intoString:&text] ;
// replace the found tag with a space
//(you can filter multi-spaces out later if you wish)
theIpHtml = [theIpHtml stringByReplacingOccurrencesOfString:
[ NSString stringWithFormat:@"%@>", text]
withString:@" "] ;
ipItemsArray = [theIpHtml componentsSeparatedByString:@" "];
an_Integer = [ipItemsArray indexOfObject:@"Address:"];
externalIP =[ipItemsArray objectAtIndex:++an_Integer];
}
// Check that you get something back
if (externalIP == nil || externalIP.length <= 0) {
// Error, no address found
return nil;
}
// Return External IP
return externalIP;
} else {
// Error, no address found
return nil;
}
}
Source from ALSystemUtilities
It's as simple as this:
NSString *publicIP = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"https://icanhazip.com/"] encoding:NSUTF8StringEncoding error:nil];
publicIP = [publicIP stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]]; // IP comes with a newline for some reason
You have to query an external server to find out the public IP. Either set up your own server (1 line of php code) or use one of the many available ones which return the IP as plain text or json upon http query. Like for example http://myipdoc.com/ip.php .
For those of us using Swift, here's my translation of Andrei's answer with the addition of NSURLSession to run it in the background. To check the network, I use Reachability.swift. Also, remember to add dyndns.org to NSExceptionDomains
for NSAppTransportSecurity
in your info.plist
.
var ipAddress:String?
func getIPAddress() {
if reachability!.isReachable() == false {
return
}
guard let ipServiceURL = NSURL(string: "http://www.dyndns.org/cgi-bin/check_ip.cgi") else {
return
}
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(ipServiceURL, completionHandler: {(data, response, error) -> Void in
if error != nil {
print(error)
return
}
let ipHTML = NSString(data: data!, encoding: NSUTF8StringEncoding) as? String
self.ipAddress = self.scanForIPAddress(ipHTML)
})
task.resume()
}
func scanForIPAddress(var ipHTML:String?) -> String? {
if ipHTML == nil {
return nil
}
var externalIPAddress:String?
var index:Int?
var ipItems:[String]?
var text:NSString?
let scanner = NSScanner(string: ipHTML!)
while scanner.atEnd == false {
scanner.scanUpToString("<", intoString: nil)
scanner.scanUpToString(">", intoString: &text)
ipHTML = ipHTML!.stringByReplacingOccurrencesOfString(String(text!) + ">", withString: " ")
ipItems = ipHTML!.componentsSeparatedByString(" ")
index = ipItems!.indexOf("Address:")
externalIPAddress = ipItems![++index!]
}
if let ip = externalIPAddress {
print("External IP Address: \(ip)")
}
return externalIPAddress
}
You can call a public IP address lookup services to get this? I have set up http://ipof.in as a service that returns the device IP address as JSON / XML or plain text. You can find them here
For JSON with GeoIP data
http://ipof.in/json
https://ipof.in/json
For XML response
http://ipof.in/xml
https://ipof.in/xml
For plain text IP address
http://ipof.in/txt
https://ipof.in/txt
I find both Andrei and Tarek's answers helpful. Both are relying a web URL to query the "public IP" of the iOS/OS X device.
However, there is an issue with this approach in some part of the world where URL such as "http://www.dyndns.org/cgi-bin/check_ip.cgi" is censored as in andrei's answer:
NSString *theIpHtml = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://www.dyndns.org/cgi-bin/check_ip.cgi"]
encoding:NSUTF8StringEncoding
error:&error];
In this case, we will need to use an "uncensored" URL within the region such as http://1212.ip138.com/ic.asp
Note that the web URL could use a different HTML and encoding than what Andrei's answer could parse - in the URL above, some very gentle changes can fix it by using kCFStringEncodingGB_18030_2000 for http://1212.ip138.com/ic.asp
NSURL* externalIPCheckURL = [NSURL URLWithString: @"http://1212.ip138.com/ic.asp"];
encoding:NSUTF8StringEncoding error:nil];
NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
NSString *theIpHtml = [NSString stringWithContentsOfURL: externalIPCheckURL
encoding: encoding
error: &error];
I use ipify and with no complaints.
NSURL *url = [NSURL URLWithString:@"https://api.ipify.org/"];
NSString *ipAddress = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
NSLog(@"My public IP address is: %@", ipAddress);