Get IP Address on iPhone | Objective-C or Swift - objective-c

I just found this code to get my iPhone's IP Address using Objective-C but it's kinda slow for the project I'm working on:
- (NSString*)getExternalIP{
NSString *externalIP = #"";
NSArray *ipItemsArray = [[NSArray alloc] init];
NSURL *iPURL = [NSURL URLWithString:#"http://www.dyndns.org/cgi-bin/check_ip.cgi"];
if (iPURL) {
NSError *error = nil;
NSString *theIpHtml = [NSString stringWithContentsOfURL:iPURL encoding:NSUTF8StringEncoding error:&error];
if (!error){
NSScanner *theScanner;
NSString *text = nil;
theScanner = [NSScanner scannerWithString:theIpHtml];
while ([theScanner isAtEnd] == NO) {
[theScanner scanUpToString:#"<" intoString:NULL] ;
[theScanner scanUpToString:#">" intoString:&text] ;
theIpHtml = [theIpHtml stringByReplacingOccurrencesOfString:[NSString stringWithFormat:#"%#>", text] withString:#" "] ;
ipItemsArray = [theIpHtml componentsSeparatedByString:#" "];
int an_Integer= (int)[ipItemsArray indexOfObject:#"Address:"];
externalIP =[ipItemsArray objectAtIndex: ++an_Integer];
}
return externalIP;
}
}
return #"error";}
Do you know an alternative solution or a way to fix this one?
NOTE: it has to work on Wi-fi and cellular.
Thanks!

I am found ip address using this way. First you can import two library.
#include <ifaddrs.h>
#include <arpa/inet.h>
then after you can use this action
- (NSString *)getIPAddress {
NSString *address = #"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
while(temp_addr != NULL) {
if(temp_addr->ifa_addr->sa_family == AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:#"en0"]) {
// Get NSString from C String
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
return address;
}
and call this action in your code like this way.
NSString *strYourIP = [self getIPAddress];
I hope this is use full to you....

Before using the code in the question, think about this for a bit:
What's going to happen if dyndns.org starts to lag?
In my experience, the response time of this service varies so badly that it's downright unusable for anything which might be performance sensitive. (I had response times varying from 0 sec to 50+ sec, tested on multiple decent connections.) It would be much better to find / set up a service for this purpose which is more reliable. If you have control over a web service for the application you're working with, I think it's trivial to add. (In PHP, it's a one-liner.)

Related

objective c gets EXC_BAD_ACCESS error on completionhandler

i'm new to objective-c, please bear with me if i ask stupid questions :)
The following is part of code i have to start vpn tunnel, but keeps getting EXC_BAD_ACCESS error
- (void)startTunnelWithOptions:(NSDictionary *)options completionHandler:(void (^)(BOOL * error))completionHandler {
vpnAdapter = [[OpenAdapter alloc] init];
vpnAdapter.delegate = self;
// get config
config = [[NSDictionary alloc] init];
NETunnelProviderProtocol *protocol = (NETunnelProviderProtocol *)self.protocolConfiguration;
config = protocol.providerConfiguration;
host = config[#"server"];
// Load config data
username = config[#"username"];
password = config[#"password"];
if(option != nil){
[vpnAdapter connect:host user:username pass:password add:YES completionHandler:^(BOOL success){
// return success;
completionHandler(&success); // Thread 2: EXC_BAD_ACCESS (code=1, address=0xbcc68f020)
}];
}else{
[vpnAdapter connect:host user:username pass:password add:NO completionHandler:^(BOOL success){
completionHandler(&success);
}];
}
}
here is connect method
- (void)connect: (NSString *) host user:(NSString *)username pass:(NSString *) password add:(Boolean) isAdd completionHandler:(void (^)(BOOL success)) completionHandler{
dispatch_queue_attr_t attributes = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_UTILITY, 0);
dispatch_queue_t connectQueue = dispatch_queue_create("me.ss-abramchuk.open-adapter.connection", attributes);
dispatch_async(connectQueue, ^{
// Call connect
//int ret=1;
NSArray* options = [NSArray arrayWithObjects:
#"--user", username,
host,
nil];
if(isAdd){
options = [NSArray arrayWithObjects:
#"--user", username,
#"--protocol", #"ad",
host,
nil];
}
//NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
//NSString *documentsDirectory = [paths objectAtIndex:0];
NSMutableArray *arguments = [NSMutableArray arrayWithCapacity:1+[options count]];
[arguments addObject:#"connect"];
[arguments addObjectsFromArray:options];
int argc = [arguments count];
char **argv = (char **)malloc(sizeof(char*) * (argc + 1));
[arguments enumerateObjectsUsingBlock:^(NSString *option, NSUInteger i, BOOL *stop) {
const char * c_string = [option UTF8String];
int length = (int)strlen(c_string);
char *c_string_copy = (char *) malloc(sizeof(char) * (length + 1));
strcpy(c_string_copy, c_string);
argv[i] = c_string_copy;
}];
argv[argc] = NULL;
const char *cfPass=[password UTF8String];
int ret = self.vpnClient->start2connect(argc, argv, cfPass);
BOOL result;
if (ret!=0){
result=false;
}
else {result = true;}
completionHandler(result);
});
}
all of these are from networkextension and while debugging, i found int ret = self.vpnClient->start2connect(argc, argv, cfPass);
seems not returning any value.
however, i confirmed that the start2connect method does return int value
so for now, anyone can help explain what's wrong?
thanks
The BOOL * is a pointer to a BOOL. We don’t use that pattern very often. We use it where the block needs to update a BOOL property somewhere, e.g. in enumerateMatchesinString, where you can update the boolean that stop points to in order to stop the enumeration.
But this is a completion handler, so there’s no point in passing a pointer to the boolean (one that presumably was on the stack, inviting problems). Just pass the boolean itself, not a pointer to it.
I would suggest that instead of:
- (void)startTunnelWithOptions:(NSDictionary *)options completionHandler:(void (^)(BOOL * error))completionHandler {
...
[vpnAdapter connect:host user:username pass:password add:YES completionHandler:^(BOOL success){
completionHandler(&success);
}];
...
}
That you want:
- (void)startTunnelWithOptions:(NSDictionary *)options completionHandler:(void (^)(BOOL success))completionHandler {
...
[vpnAdapter connect:host user:username pass:password add:YES completionHandler:^(BOOL success){
completionHandler(success);
}];
...
}
Note the block parameter isn’t BOOL * error but rather BOOL success and when it calls the completionHandler, there’s not & before success.
If there’s some reason you needed to update the BOOL, then that’s a different matter, but it doesn’t make sense in the context of a completion handler.

iOS Programmatically find IP Address [duplicate]

I would like to obtain my iPad's IP address programmatically.
How can I query the networking subsystem to find out what my IPv4 (and IPv6) addresses are?
PS: Can I disable IPv6 somehow?
The following code finds all IPv4 and IPv6 addresses on an iOS or OSX device. The first getIPAddress method acts more or less as the older code in this answer: you can prefer either one or the other type address, and it always prefers WIFI over cellular (obviously you could change this).
More interestingly it can return a dictionary of all addresses found, skipping addresses for not up interfaces, or addresses associated with loopback. The previous code as well as other solutions on this topic will not properly decode IPv6 (inet_ntoa cannot deal with them). This was pointed out to me by Jens Alfke on an Apple forum - the proper function to use is inet_ntop (look at the man page, and or refer to this inet_ntop article also provided by Jens.
The dictionary keys have the form "interface" "/" "ipv4 or ipv6".
#include <ifaddrs.h>
#include <arpa/inet.h>
#include <net/if.h>
#define IOS_CELLULAR #"pdp_ip0"
#define IOS_WIFI #"en0"
//#define IOS_VPN #"utun0"
#define IP_ADDR_IPv4 #"ipv4"
#define IP_ADDR_IPv6 #"ipv6"
- (NSString *)getIPAddress:(BOOL)preferIPv4
{
NSArray *searchArray = preferIPv4 ?
#[ /*IOS_VPN #"/" IP_ADDR_IPv4, IOS_VPN #"/" IP_ADDR_IPv6,*/ IOS_WIFI #"/" IP_ADDR_IPv4, IOS_WIFI #"/" IP_ADDR_IPv6, IOS_CELLULAR #"/" IP_ADDR_IPv4, IOS_CELLULAR #"/" IP_ADDR_IPv6 ] :
#[ /*IOS_VPN #"/" IP_ADDR_IPv6, IOS_VPN #"/" IP_ADDR_IPv4,*/ IOS_WIFI #"/" IP_ADDR_IPv6, IOS_WIFI #"/" IP_ADDR_IPv4, IOS_CELLULAR #"/" IP_ADDR_IPv6, IOS_CELLULAR #"/" IP_ADDR_IPv4 ] ;
NSDictionary *addresses = [self getIPAddresses];
NSLog(#"addresses: %#", addresses);
__block NSString *address;
[searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop)
{
address = addresses[key];
if(address) *stop = YES;
} ];
return address ? address : #"0.0.0.0";
}
- (NSDictionary *)getIPAddresses
{
NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8];
// retrieve the current interfaces - returns 0 on success
struct ifaddrs *interfaces;
if(!getifaddrs(&interfaces)) {
// Loop through linked list of interfaces
struct ifaddrs *interface;
for(interface=interfaces; interface; interface=interface->ifa_next) {
if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ ) {
continue; // deeply nested code harder to read
}
const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr;
char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ];
if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) {
NSString *name = [NSString stringWithUTF8String:interface->ifa_name];
NSString *type;
if(addr->sin_family == AF_INET) {
if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) {
type = IP_ADDR_IPv4;
}
} else {
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr;
if(inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) {
type = IP_ADDR_IPv6;
}
}
if(type) {
NSString *key = [NSString stringWithFormat:#"%#/%#", name, type];
addresses[key] = [NSString stringWithUTF8String:addrBuf];
}
}
}
// Free memory
freeifaddrs(interfaces);
}
return [addresses count] ? addresses : nil;
}
EDIT1: Code updated on May 16, 2014 (bug pointed out by lhunath, see comments). Loopback addresses now returned, but its easy for you to uncomment the test to exclude them yourself.
EDIT2: (by some unknown person): Improved further March 13, 2015: In case the user uses a VPN (regardless over WiFi or Cellular), the previous code would have failed. Now, it works even with VPN connections. VPN connections are given precedence over WiFi and Cell because that's how the device handles it. This should even work for Macs as the VPN connection on a Mac is also using IF utun0 but not tested.
EDIT3: (9/8/2016) Given the problems experienced by #Qiulang (see comments) with the VPN code (which someone else added), I've commented it out. If anyone knows definitively how to specify a user VPN please chime in with a comment.
In your implementation file .m ,
#import <ifaddrs.h>
#import <arpa/inet.h>
// Get IP Address
- (NSString *)getIPAddress {
NSString *address = #"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
while(temp_addr != NULL) {
if(temp_addr->ifa_addr->sa_family == AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:#"en0"]) {
// Get NSString from C String
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
return address;
}
Many existing solutions only consider wireless interfaces, which won't work for wired connections via an Ethernet adapter (ie. no Wifi or 3G); see this more recent solution which considers IP addresses obtained through wired interfaces as well.
iPad: How to get IP address programmatically WIRED (not via wireless)
Get IP address using Swift 3:
func getIPAddress() -> String {
var address: String = "error"
var interfaces: ifaddrs? = nil
var temp_addr: ifaddrs? = nil
var success: Int = 0
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(interfaces)
if success == 0 {
// Loop through linked list of interfaces
temp_addr = interfaces
while temp_addr != nil {
if temp_addr?.ifa_addr?.sa_family == AF_INET {
// Check if interface is en0 which is the wifi connection on the iPhone
if (String(utf8String: temp_addr?.ifa_name) == "en0") {
// Get NSString from C String
address = String(utf8String: inet_ntoa((temp_addr?.ifa_addr as? sockaddr_in)?.sin_addr))
}
}
temp_addr = temp_addr?.ifa_next
}
}
// Free memory
freeifaddrs(interfaces)
return address
}
#DavidH's answer works fine till I got this result from some 4G cellular network:
{
"lo0/ipv4" = "127.0.0.1";
"lo0/ipv6" = "fe80::1";
"pdp_ip0/ipv4" = "10.132.76.168";
"utun0/ipv6" = "fe80::72c3:e25e:da85:b730";
}
I am not using vpn so I have no idea why I had a utun0/ipv6.
--- Updated ---
I further debug this issue and found that I can get an fake vpn address even in other 4G networks (is this iOS bug??),
{
""awdl0/ipv6"" = ""fe80::c018:9fff:feb2:988"";
""en0/ipv6"" = ""fe80::181a:2e43:f91b:db2b"";
""lo0/ipv4"" = ""127.0.0.1"";
""lo0/ipv6"" = ""fe80::1"";
""pdp_ip0/ipv4"" = ""10.48.10.210"";
""utun0/ipv4"" = ""192.168.99.2"";
}
If I did use vpn I will get this:
{
"lo0/ipv4" = "127.0.0.1";
"lo0/ipv6" = "fe80::1";
"pdp_ip0/ipv4" = "10.49.187.23";
"utun0/ipv6" = "fe80::5748:5b5d:2bf0:658d";
"utun1/ipv4" = "192.168.99.2"; //the real one
}
So it is utun1 NOT utun0
Without figuring out why I will just have to drop vpn check :(
---- update ----
I raised a bug (28131847) to apple and replied with "Not all utun interfaces are for VPN. There are other OS features that use utun interfaces."
But when I asked how to get a valid vpn IP address then, their answer was rather disappointed, "You can go into Settings -> VPN and look at your VPN configuration to see if the VPN is active. In some cases you can see the assigned IP address there as well. We are now closing this bug report." :(
---- update 2016/11/04 ----
I hit the problem again and I need to further modify #DavidH's answer to fix it:
I was in 4G network and I got this address:
addresses: {
"awdl0/ipv6" = "fe80::98fd:e6ff:fea9:3afd";
"en0/ipv6" = "fe80::8dd:7d92:4159:170e";
"lo0/ipv4" = "127.0.0.1";
"lo0/ipv6" = "fe80::1";
"pdp_ip0/ipv4" = "10.37.212.102";
"utun0/ipv6" = "fe80::279c:ea56:a2ef:d128";
}
With his original answer I will get the wifi IP fe80::8dd:7d92:4159:170e, which was fake and connection failed.
So I modified the code to like,
[searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop)
{
if ((internetReach.isReachableViaWiFi && [key hasPrefix:IOS_WIFI]) ||
(internetReach.isReachableViaWWAN && [key hasPrefix:IOS_CELLULAR])) {
address = addresses[key];
if(address) *stop = YES;
}
} ];
The current solution doesn't return the en0 device on OS X, the following code uses the System Configuration Framework to get the interfaces then uses standard C functions to get the IP address.
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <net/if.h>
#define IFT_ETHER 0x6
#include <SystemConfiguration/SCDynamicStore.h>
+(void)getInterfaces
{
SCDynamicStoreRef storeRef = SCDynamicStoreCreate(NULL, (CFStringRef)#"FindCurrentInterfaceIpMac", NULL, NULL);
CFPropertyListRef global = SCDynamicStoreCopyValue (storeRef,CFSTR("State:/Network/Interface"));
id primaryInterface = [(__bridge NSDictionary *)global valueForKey:#"Interfaces"];
for (NSString* item in primaryInterface)
{
if(get_iface_address([item UTF8String]))
{
NSString *ip = [NSString stringWithUTF8String:get_iface_address([item UTF8String])];
NSLog(#"interface: %# - %#",item,ip);
} else
NSLog(#"interface: %#",item);
}
}
static char * get_iface_address (char *interface)
{
int sock;
uint32_t ip;
struct ifreq ifr;
char *val;
if (!interface)
return NULL;
/* determine UDN according to MAC address */
sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
perror ("socket");
return NULL;
}
strcpy (ifr.ifr_name, interface);
ifr.ifr_addr.sa_family = AF_INET;
if (ioctl (sock, SIOCGIFADDR, &ifr) < 0)
{
perror ("ioctl");
close (sock);
return NULL;
}
val = (char *) malloc (16 * sizeof (char));
ip = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr;
ip = ntohl (ip);
sprintf (val, "%d.%d.%d.%d",
(ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF);
close (sock);
return val;
}
This answer was inspired by #DavidH's answer. I fixed some issues, replaced inet_ntop with getnameinfo which allows a cleaner approach. Note that this yields a dictionary that maps an interface name to an array of IP addresses (an interface can have multiple IPv4 and IPv6's associated with it, technically). It does not distinguish between IPv4 and IPv6:
// Get all our interface addresses.
struct ifaddrs *ifAddresses;
if (getifaddrs( &ifAddresses ) != 0) {
NSLog( #"Couldn't get interface addresses: %d", errno );
return nil;
}
int error;
char host[MAX( INET_ADDRSTRLEN, INET6_ADDRSTRLEN )];
_ipAddressesByInterface = [NSMutableDictionary dictionaryWithCapacity:8];
for (struct ifaddrs *ifAddress = ifAddresses; ifAddress; ifAddress = ifAddress->ifa_next) {
if (!(ifAddress->ifa_flags & IFF_UP) || (ifAddress->ifa_flags & IFF_LOOPBACK))
// Ignore interfaces that aren't up and loopback interfaces.
continue;
if (ifAddress->ifa_addr->sa_family != AF_INET && ifAddress->ifa_addr->sa_family != AF_INET6)
// Ignore non-internet addresses.
continue;
if ((error = getnameinfo( ifAddress->ifa_addr, ifAddress->ifa_addr->sa_len, host, sizeof( host ), NULL, 0, NI_NUMERICHOST )) != noErr) {
// Couldn't to format host name for this address.
NSLog( #"Couldn't resolve host name for address: %s", gai_strerror( error ) );
continue;
}
NSString *ifName = [NSString stringWithCString:ifAddress->ifa_name encoding: NSUTF8StringEncoding];
NSMutableArray *ifIpAddresses = _ipAddressesByInterface[ifName];
if (!ifIpAddresses)
ifIpAddresses = _ipAddressesByInterface[ifName] = [NSMutableArray arrayWithCapacity:2];
[ifIpAddresses addObject:[NSString stringWithCString:host encoding: NSUTF8StringEncoding]];
}
freeifaddrs( ifAddresses );
return _ipAddressesByInterface;
Great solution for swift in This file which serves all the details.
In One of my app I need to fetch wifi IP address. I have used answers above, in swift 3 like this:
let WIFI_IF = "en0"
let UNKNOWN_IP_ADDRESS = ""
var addresses: [AnyHashable: Any] = ["wireless": UNKNOWN_IP_ADDRESS, "wired": UNKNOWN_IP_ADDRESS, "cell": UNKNOWN_IP_ADDRESS]
var interfaces: UnsafeMutablePointer<ifaddrs>? = nil
var temp_addr: UnsafeMutablePointer<ifaddrs>? = nil
var success: Int = 0
success = Int(getifaddrs(&interfaces))
if success == 0 {
temp_addr = interfaces
while temp_addr != nil {
if temp_addr?.pointee.ifa_addr == nil {
continue
}
if temp_addr?.pointee.ifa_addr.pointee.sa_family == UInt8(AF_INET) {
if (String(utf8String: (temp_addr?.pointee.ifa_name)!) == WIFI_IF) {
addresses["wireless"] = String(utf8String: inet_ntoa(((temp_addr?.pointee.ifa_addr as? sockaddr_in)?.sin_addr)!))
}
}
temp_addr = temp_addr?.pointee.ifa_next
}
}
In this code, It crashes because I have to check for nil in each statement I have used as optional with ?. So it is better for me to use given linked file in my class. It becomes easy for me to check now like:
class func getWifiIPAddress() -> String {
var wifiIp = ""
let WIFI_IF = "en0"
let allInterface = Interface.allInterfaces()
for interf in allInterface {
if interf.name == WIFI_IF {
if let address = interf.address {
if address.contains(".") {
wifiIp = address
break
}
}
}
}
return wifiIp
}
I have parsed string for "." because Interface Class returns two interface in my iPhone for en0 address like "fb00::" and address like "101.10.1.1"
I created a simple file for getting the ip address. I based this solution on # lundhjem's, #DavidH's and #Ihunath's answers. It considers wired connections. I haven't included VPN in this solution though.
PCNetwork.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
#interface PCNetwork : NSObject
+ (NSString *)getIPAddress; // Prefers IPv4
+ (NSString *)getIPAddress:(BOOL)preferIPv4;
+ (NSDictionary *)getIPAddresses;
#end
NS_ASSUME_NONNULL_END
PCNetwork.m
#import "PCNetwork.h"
#include <ifaddrs.h>
#include <arpa/inet.h>
#include <net/if.h>
#define IP_UNKNOWN #"0.0.0.0"
#define IP_ADDR_IPv4 #"ipv4"
#define IP_ADDR_IPv6 #"ipv6"
#implementation PCNetwork
#pragma mark - IP
+ (NSString *)getIPAddress {
return [self getIPAddress:YES];
}
+ (NSString *)getIPAddress:(BOOL)preferIPv4 {
NSArray *searchArray = [self getAllIFSearchArray:preferIPv4];
NSDictionary *addresses = [self getIPAddresses];
DLog(#"addresses: %#", addresses);
__block NSString *address = nil;
[searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop) {
address = addresses[key];
if(address) *stop = YES;
}];
return address ?: IP_UNKNOWN;
}
+ (NSDictionary *)getIPAddresses {
NSMutableDictionary *addresses = [NSMutableDictionary dictionary];
struct ifaddrs *interfaces;
BOOL success = !getifaddrs(&interfaces); // Retrieve the current interfaces : returns 0 on success
if (success) {
struct ifaddrs *temp_interface;
for (temp_interface = interfaces; temp_interface; temp_interface = temp_interface->ifa_next) { // Loop through linked list of interfaces
if (!(temp_interface->ifa_flags & IFF_UP) || (temp_interface->ifa_flags & IFF_LOOPBACK)) { // Ignore interfaces that aren't up and loopback interfaces.
continue;
}
if (!temp_interface->ifa_addr) {
continue;
}
const struct sockaddr_in *temp_addr = (const struct sockaddr_in*)temp_interface->ifa_addr;
if (temp_addr->sin_family == AF_INET || temp_addr->sin_family == AF_INET6) {
char addrBuf[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
NSString *name = [NSString stringWithUTF8String:temp_interface->ifa_name];
NSString *type = nil;
if (temp_addr->sin_family == AF_INET) {
if (inet_ntop(AF_INET, &temp_addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) {
type = IP_ADDR_IPv4;
}
} else {
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)temp_interface->ifa_addr; // AF_INET6
if (inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) {
type = IP_ADDR_IPv6;
}
}
if (type) {
NSString *key = [NSString stringWithFormat:#"%#/%#", name, type];
addresses[key] = [NSString stringWithUTF8String:addrBuf];
}
}
}
freeifaddrs(interfaces); // Free memory
}
return addresses.count ? addresses.copy : nil;
}
#pragma mark - Inter Frame Spacing
+ (NSArray *)getAllIFSearchArray:(BOOL)preferIPv4 {
NSArray *KNOWN_WIFI_IFS = #[#"en0"];
NSArray *KNOWN_WIRED_IFS = #[#"en1",#"en2",#"en3",#"en4"];
NSArray *KNOWN_CELL_IFS = #[#"pdp_ip0",#"pdp_ip1",#"pdp_ip2",#"pdp_ip3"];
NSMutableArray *searchArray = [NSMutableArray array];
// Add wifi
[searchArray addObjectsFromArray:[self getIFSearchArrayWith:KNOWN_WIFI_IFS preferIPv4:preferIPv4]];
// Add cell
[searchArray addObjectsFromArray:[self getIFSearchArrayWith:KNOWN_CELL_IFS preferIPv4:preferIPv4]];
// Add wired
[searchArray addObjectsFromArray:[self getIFSearchArrayWith:KNOWN_WIRED_IFS preferIPv4:preferIPv4]];
return searchArray.copy;
}
+ (NSArray *)getIFSearchArrayWith:(NSArray *)iFList preferIPv4:(BOOL)preferIPv4 {
NSMutableArray *searchArray = [NSMutableArray array];
for (NSString *iFType in iFList) {
if (preferIPv4) {
[searchArray addObject:[NSString stringWithFormat:#"%#/%#", iFType, IP_ADDR_IPv4]];
[searchArray addObject:[NSString stringWithFormat:#"%#/%#", iFType, IP_ADDR_IPv6]];
} else {
[searchArray addObject:[NSString stringWithFormat:#"%#/%#", iFType, IP_ADDR_IPv6]];
[searchArray addObject:[NSString stringWithFormat:#"%#/%#", iFType, IP_ADDR_IPv4]];
}
}
return searchArray.copy;
}
#end
in iOS 13.4.1 is not work for me .
i use this fix it.
+ (NSString *)getIPAddress{
NSArray *searchArray =
#[ IOS_VPN #"/" IP_ADDR_IPv4, IOS_VPN #"/" IP_ADDR_IPv6, IOS_WIFI #"/" IP_ADDR_IPv4, IOS_WIFI #"/" IP_ADDR_IPv6, IOS_4_3G #"/" IP_ADDR_IPv4, IOS_4_3G #"/" IP_ADDR_IPv6, IOS_CELLULAR #"/" IP_ADDR_IPv4, IOS_CELLULAR #"/" IP_ADDR_IPv6];
__block NSDictionary *addresses = [self getIPAddressArray];
__block NSString *address;
[searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop)
{
address = addresses[key];
if ([key rangeOfString:#"ipv6"].length > 0 && ![[NSString stringWithFormat:#"%#",addresses[key]] hasPrefix:#"(null)"] ) {
if ( ![addresses[key] hasPrefix:#"fe80"]) {
// isIpv6 = YES;
*stop = YES;
}
}else{
if([self isValidatIP:address]) {
*stop = YES;
}
}
} ];
return address ? address : #"error";
}
+ (NSString *)getIPType{
NSString *ipAddress = [self getIPAddress];
if ([self isValidatIP:ipAddress]) {
return #"04";//ipv4
}else{
return #"06";//ipv6
}
}
+ (NSDictionary *)getIPAddressArray{
NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8];
// retrieve the current interfaces - returns 0 on success
struct ifaddrs *interfaces;
if(!getifaddrs(&interfaces)) {
// Loop through linked list of interfaces
struct ifaddrs *interface;
for(interface=interfaces; interface; interface=interface->ifa_next) {
if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ ) {
continue; // deeply nested code harder to read
}
const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr;
char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ];
if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) {
NSString *name = [NSString stringWithUTF8String:interface->ifa_name];
NSString *type;
if(addr->sin_family == AF_INET) {
if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) {
type = IP_ADDR_IPv4;
}
} else {
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr;
if(inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) {
type = IP_ADDR_IPv6;
}
}
if(type) {
NSString *key = [NSString stringWithFormat:#"%#/%#", name, type];
addresses[key] = [NSString stringWithUTF8String:addrBuf];
}
}
}
// Free memory
freeifaddrs(interfaces);
}
return [addresses count] ? addresses : nil;
}
+ (BOOL)isValidatIP:(NSString *)ipAddress {
if (ipAddress.length == 0) {
return NO;
}
NSString *urlRegEx = #"^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
NSError *error;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:urlRegEx options:0 error:&error];
if (regex != nil) {
NSTextCheckingResult *firstMatch=[regex firstMatchInString:ipAddress options:0 range:NSMakeRange(0, [ipAddress length])];
if (firstMatch) {
NSRange resultRange = [firstMatch rangeAtIndex:0];
NSString *result=[ipAddress substringWithRange:resultRange];
//输出结果
NSLog(#"%#",result);
return YES;
}
}
return NO;
}

How to determine Internet Connection in Cocoa?

I need to determine if Internet Connection is available or not. I don't care how it is connected (WI-FI, Lan,etc..) . I need to determine, is Internet Connection available at all .
P.S. I found a way to check WI-FI connection. But I don't care how it is connected (I need to check all the ways that can be connected to Internet).
Something like (isConnected)
This code works for both iOS and OSX platforms, I hope.
#include <SystemConfiguration/SystemConfiguration.h>
static BOOL isInternetConnection()
{
BOOL returnValue = NO;
#ifdef TARGET_OS_MAC
struct sockaddr zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sa_len = sizeof(zeroAddress);
zeroAddress.sa_family = AF_INET;
SCNetworkReachabilityRef reachabilityRef = SCNetworkReachabilityCreateWithAddress(NULL, (const struct sockaddr*)&zeroAddress);
#elif TARGET_OS_IPHONE
struct sockaddr_in address;
size_t address_len = sizeof(address);
memset(&address, 0, address_len);
address.sin_len = address_len;
address.sin_family = AF_INET;
SCNetworkReachabilityRef reachabilityRef = SCNetworkReachabilityCreateWithAddress(NULL, (const struct sockaddr*)&address);
#endif
if (reachabilityRef != NULL)
{
SCNetworkReachabilityFlags flags = 0;
if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
{
BOOL isReachable = ((flags & kSCNetworkFlagsReachable) != 0);
BOOL connectionRequired = ((flags & kSCNetworkFlagsConnectionRequired) != 0);
returnValue = (isReachable && !connectionRequired) ? YES : NO;
}
CFRelease(reachabilityRef);
}
return returnValue;
}
Take a look at the SCNetworkReachability reference. This is a C API, so it's not as easy to use as a single method call, but it does a great job of notifying your app when a particular address becomes reachable or unreachable over the network.
The broad outline is you'll create an object with SCNetworkReachabilityCreateWithAddress or SCNetworkReachabilityCreateWithName, and then add it to the run loop with SCNetworkReachabilityScheduleWithRunLoop. When the reachability is determined and when it changes, the callback function you supply will be called. You can use that to update the state of your application.
Apple supplies an example app that shows how to use this (although it's designed for iOS, not Mac OS X)
One way to do it is :
// Check whether the user has internet
- (bool)hasInternet {
NSURL *url = [[NSURL alloc] initWithString:#"http://www.google.com"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:5.0];
BOOL connectedToInternet = NO;
if ([NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]) {
connectedToInternet = YES;
}
//if (connectedToInternet)
//NSLog(#"We Have Internet!");
[request release];
[url release];
return connectedToInternet;
}

Accessing IP Address with NSHost

I am trying to get the IP Address using NSHost. With the NSHost object I can use the addresses method to access an array of objects one of which is the IP Address. I fear though that the IP Address may change position in the array from one machine to the other. Is there a way to access this information in a universal way?
There was an attempt to answer this question in a previous post, but as you can see it falls short.
IP Address? - Cocoa
Here is my code:
+(NSString *) ipAddress {
NSHost * h = [[[NSHost currentHost] addresses] objectAtIndex:1];
return h ;
}
The only thing I can think of is to use something like "http://www.dyndns.org/cgi-bin/check_ip.cgi" others may have a better way.
This is an example,(i.e a quick cobbled together code)
NSUInteger an_Integer;
NSArray * ipItemsArray;
NSString *externalIP;
NSURL *iPURL = [NSURL URLWithString:#"http://www.dyndns.org/cgi-bin/check_ip.cgi"];
if (iPURL) {
NSError *error = nil;
NSString *theIpHtml = [NSString stringWithContentsOfURL:iPURL
encoding:NSUTF8StringEncoding
error:&error];
if (!error) {
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];
}
NSLog(#"%#",externalIP);
} else {
NSLog(#"Oops... g %d, %#",
[error code],
[error localizedDescription]);
}
}
[pool drain];
return 0;}
I have used this on many machines without problems.
-(void) getIPWithNSHost{
NSArray *addresses = [[NSHost currentHost] addresses];
for (NSString *anAddress in addresses) {
if (![anAddress hasPrefix:#"127"] && [[anAddress componentsSeparatedByString:#"."] count] == 4) {
stringAddress = anAddress;
break;
} else {
stringAddress = #"IPv4 address not available" ;
}
}
//NSLog (#"getIPWithNSHost: stringAddress = %# ",stringAddress);
}
NSString *stringAddress; is declared else where
I wanted to update my original answer on getting an external ip.
There is not much change but I wanted to show how to get and parse the HTML with use NSXMLDocument and Xquary
This also gives a small illustration of how you can parse HTML by getting the nodes. Which in my opinion is more straight forward. Although NSXMLDocument is initially for XML it will parse the HTML DOM tree
NSString *externalIP;
///--DYNDNS.ORG URL
NSURL *iPURL = [NSURL URLWithString:#"http://www.dyndns.org/cgi-bin/check_ip.cgi"];
if (iPURL) {
NSError *err_p = nil;
//--use NSXMLDocument to get the url:(*Requests NSXMLNode to preserve whitespace characters (such as tabs and carriage returns) in the XML source that are not part of node content*)
NSXMLDocument * xmlDoc = [[NSXMLDocument alloc] initWithContentsOfURL:iPURL
options:(NSXMLNodePreserveWhitespace|
NSXMLNodePreserveCDATA)
error:&err_p];
if (xmlDoc == nil) {
//-- That did not work so lets see if we can change the malformed XML into valid XML during processing of the document.
xmlDoc = [[NSXMLDocument alloc] initWithContentsOfURL:iPURL
options:NSXMLDocumentTidyXML
error:&err_p];
}
if (!err_p) {
NSError * error;
//-- We will use XQuary to get the text from the child node. Dyndns.org page is very simple. So we just need to get the Body text.
NSString *xpathQueryTR = #"//body/text()";
//-- we get the first node's string value. We use string value to in effect cast to NSString.
//We the seperate the string into components using a space. and obtain the last object in the returned array.
//--This gives us the IP string without the "Current IP Address:" string.
externalIP = [[[[[xmlDoc nodesForXPath:xpathQueryTR error:&error]objectAtIndex:0] stringValue]componentsSeparatedByString:#" "]lastObject];
if (!error) {
NSLog(#"%#",externalIP);
}else {
NSLog(#"Oops... g %ld, %#",
(long)[error code],
[error localizedDescription]);
}
}else {
NSLog(#"Oops... g %ld, %#",
(long)[err_p code],
[err_p localizedDescription]);
}
}
Made an utility class to find the IP addresses. Minimalistic approach. You can robustify it with more conditions or regex checking.
NSLog(#"Addresses: %#", [[NSHost currentHost] addresses]);
This is the list returned by NSHost
"fe80::1610:9fff:fee1:8c2f%en0",
"192.168.212.61",
"fe80::2829:3bff:fee6:9133%awdl0",
"fe80::e54b:8494:bbc8:3989%utun0",
"fd68:cc16:fad8:ded9:e54b:8494:bbc8:3989",
"10.11.51.61",
"::1",
"127.0.0.1",
"fe80::1%lo0"
Test method,
- (void)testHost {
NSLog(#"Addresses: %#", [[NSHost currentHost] addresses]);
for (NSString *s in [[NSHost currentHost] addresses]) {
IPAddress *addr = [[IPAddress alloc] initWithString:s];
if (![addr isLocalHost] && [addr isIPV4]) {
// do something
}
}
}
IPAddress.h
#import <Foundation/Foundation.h>
#interface IPAddress : NSObject
#property (nonatomic, strong) NSString *IPAddress;
- (id)initWithString:(NSString *)ipaddress;
- (BOOL)isLocalHost;
- (BOOL) isIPV4;
- (BOOL) isIPV6;
#end
IPAddress.m
#import "IPAddress.h"
#implementation IPAddress
- (id)initWithString:(NSString *)ipaddress {
self = [super init];
if (self) {
self.IPAddress = ipaddress;
}
return self;
}
- (BOOL)isLocalHost {
if (self.IPAddress == nil) return NO;
if ([#"127.0.0.1" compare:self.IPAddress options:NSCaseInsensitiveSearch] == NSOrderedSame) {
return YES;
}
if ([#"localhost" compare:self.IPAddress options:NSCaseInsensitiveSearch] == NSOrderedSame) {
return YES;
}
if ([#"::1" compare:self.IPAddress options:NSCaseInsensitiveSearch] == NSOrderedSame) {
return YES;
}
return NO;
}
- (BOOL) isIPV4 {
NSArray *ar = [self.IPAddress componentsSeparatedByString:#"."];
if (ar.count == 4) {
return YES;
}
return NO;
}
- (BOOL) isIPV6 {
if (![self isIPV4]) {
if ([self.IPAddress rangeOfString:#":"].location != NSNotFound) {
return YES;
}
}
return NO;
}
#end
As the answers to the question you mention above have said, there are a variety of IP addresses that a single machine can have. If that is what you want, then you might be better off using the names method of NSHost to get an array of names, which you can then filter for the suffix (i.e *.lan) to get the name of the host you want with this name. In my case. the .lan address returns my network ip address as a dotted quad.
If you want to find the external ip address, then this is a good answer to look at.
My first Answer is to supply the Private IP address assigned to the Machine on private network from say your router.
If you want to see the public IP, which is the one facing the internet. Normally assigned by your service provider. You may want to look at the answer by Jim Dovey --> here
I tested it and it worked well, but read the rest of the comments and answers which point to ambiguities in trying to get a public IP.
You can create a category on NSHost and do something like this:
#import <arpa/inet.h>
#import <ifaddrs.h>
#import <net/if.h>
.h
+ (NSDictionary *) interfaceIP4Addresses;
+ (NSDictionary *) interfaceIP6Addresses;
+ (NSDictionary *) interfaceIPAddresses;
.m
typedef NS_ENUM(NSUInteger, AddressType) {
AddressTypeBoth = 0,
AddressTypeIPv4 = 1,
AddressTypeIPv6 = 2
};
#implementation SomeClass
#pragma mark - Helper Methods:
+ (NSDictionary *) _interfaceAddressesForFamily:(AddressType)family {
NSMutableDictionary *interfaceInfo = [NSMutableDictionary dictionary];
struct ifaddrs *interfaces;
if ( (0 == getifaddrs(&interfaces)) ) {
struct ifaddrs *interface;
for ( interface=interfaces; interface != NULL; interface=interface->ifa_next ) {
if ( (interface->ifa_flags & IFF_UP) && !(interface->ifa_flags & IFF_LOOPBACK) ) {
const struct sockaddr_in *addr = (const struct sockaddr_in *)interface->ifa_addr;
if ( addr && addr->sin_family == PF_INET ) {
if ( (family == AddressTypeBoth) || (family == AddressTypeIPv4) ) {
char ip4Address[INET_ADDRSTRLEN];
inet_ntop( addr->sin_family, &(addr->sin_addr), ip4Address, INET_ADDRSTRLEN );
[interfaceInfo setObject:[NSString stringWithUTF8String:interface->ifa_name]
forKey:[NSString stringWithUTF8String:ip4Address]];
} } else if ( addr && addr->sin_family == PF_INET6 ) {
if ( (family == AddressTypeBoth) || (family == AddressTypeIPv6) ) {
char ip6Address[INET6_ADDRSTRLEN];
inet_ntop( addr->sin_family, &(addr->sin_addr), ip6Address, INET6_ADDRSTRLEN );
[interfaceInfo setObject:[NSString stringWithUTF8String:interface->ifa_name]
forKey:[NSString stringWithUTF8String:ip6Address]];
} }
}
} freeifaddrs( interfaces );
} return [NSDictionary dictionaryWithDictionary:interfaceInfo];
}
#pragma mark - Class Methods:
+ (NSDictionary *) interfaceIP4Addresses { return [self _interfaceAddressesForFamily:AddressTypeIPv4]; }
+ (NSDictionary *) interfaceIP6Addresses { return [self _interfaceAddressesForFamily:AddressTypeIPv6]; }
+ (NSDictionary *) interfaceIPAddresses { return [self _interfaceAddressesForFamily:AddressTypeBoth]; }
#end
This works really fast and well. If you need other info or to monitor then use System Configuration framework.

IP Address? - Cocoa

How would I make a GUI program that displays your Ip address with a click of a button? Please, no difficult explanations, I just started Cocoa not long ago.
Thanks,
Kevin
You can get IP address through two ways:
1- if you want to get the local ip address on the current used netwrok, you can use the following method to retrive it:
-(NSString *)getIPAddress
{
NSString *address = #"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0)
{
// Loop through linked list of interfaces
temp_addr = interfaces;
while(temp_addr != NULL)
{
if(temp_addr->ifa_addr->sa_family == AF_INET)
{
// Get NSString from C String
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
return address;
}
2- if you want to get the external IP address then you need to use the following method:
-(NSString*)getIP
{
NSUInteger an_Integer;
NSArray * ipItemsArray;
NSString *externalIP;
NSURL *iPURL = [NSURL URLWithString:#"http://www.dyndns.org/cgi-bin/check_ip.cgi"];
if (iPURL) {
NSError *error = nil;
NSString *theIpHtml = [NSString stringWithContentsOfURL:iPURL encoding:NSUTF8StringEncoding error:&error];
if (!error) {
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];
}
NSLog(#"%#",externalIP);
} else {
NSLog(#"Oops... g %d, %#", [error code], [error localizedDescription]);
}
}
return externalIP;
}
For determining the IP address, I found
this.
As for making it into a Cocoa app, add an NSTextField (label) to your main window in Interface Builder, put in a button, add in an application controller (a subclass of NSObject that you make), put in the outlet and the action, do the proper connenctions, and in the "get IP" method, put in that code and set the value for the label's stringValue.
You can use [[NSHost currentHost] address], but it won't always display what you like. On my system, for example, it gives my IPv6 address.
EDIT: On my system, [[[NSHost currentHost] addresses] objectAtIndex:0] has my IPv4 address.
[[NSHost currentHost] addresses] will get you an array of IPs. Read the documentation for NSHost.
As for displaying that in a GUI, I recommend getting Aaron Hillegass' book Cocoa Programming for Mac OS X, or any Cocoa beginners book should teach that.
I just wrote this, may need some work but seems to work well on my machine...
- (NSString *)getLocalIPAddress
{
NSArray *ipAddresses = [[NSHost currentHost] addresses];
NSArray *sortedIPAddresses = [ipAddresses sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
numberFormatter.allowsFloats = NO;
for (NSString *potentialIPAddress in sortedIPAddresses)
{
if ([potentialIPAddress isEqualToString:#"127.0.0.1"]) {
continue;
}
NSArray *ipParts = [potentialIPAddress componentsSeparatedByString:#"."];
BOOL isMatch = YES;
for (NSString *ipPart in ipParts) {
if (![numberFormatter numberFromString:ipPart]) {
isMatch = NO;
break;
}
}
if (isMatch) {
return potentialIPAddress;
}
}
// No IP found
return #"?.?.?.?";
}
We can use hostWithName: method with current host name. This will return only single local IPv4 and IPv6 IP, which we can filter easily.
We can get the current system host name using [[NSHost currentHost] name].
+(NSString *)getLocalIPAddress{
NSArray *ipAddresses = [[NSHost hostWithName:[[NSHost currentHost] name]] addresses];
for (NSString *ipAddress in ipAddresses) {
if ([ipAddress componentsSeparatedByString:#"."].count == 4) {
return ipAddress;
}
}
return #"Not Connected.";
}
So, this will solve all the problems mentions in comments of other answers. Also, this significantly work more faster than other solution mention here.