How to spoof different carriers in iOS? - ios

Is it possible to spoof network providers just like it is possible to spoof locations in iOS?
I have an app that will get a user's ISO country code using Core Location, however I would like a fallback for when the user doesn't authorize location services for my app.
I have a function that is called in order to set a user's country according to their carrier; see below.
- (void)carrierBasedLocationSet {
if (DefaultCountryCode && ![DefaultCountryCode isEqualToString:#"Default"]) {
////NSLog(#"Skip Carrier Based Location set : DefaultCountryCode is [%#]", DefaultCountryCode);
return;
}
/***********************************
* Set country code based on Carrier
***********************************/
CTTelephonyNetworkInfo *networkInfo = [[CTTelephonyNetworkInfo alloc] init];
Carrier = [networkInfo subscriberCellularProvider];
NSString *isoCountryCode = Carrier.isoCountryCode;
if (isoCountryCode == nil || isoCountryCode.length == 0) {
isoCountryCode = [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode];
}
self.ISO_CountryCode = [isoCountryCode uppercaseString];
self.CarrierBased_ISO_Country = self.ISO_CountryCode;
}
This code works and produces US, which is where I am located. However, I want to test this out for different countries. Simply editing the product scheme to spoof a location in Australia, for example, does not give me back the AU country code and still gives me US.
Does anyone know if what I am trying to do is possible? Getting a user's location is essential to my application and I am unsure of another alternative.

Related

How to check contact source in CNContact swift?

In Contact apps there's group like "iCloud", "yahoo", "gmail". In swift, is it possible to fetch contact from gmail source only?
Tested code. Hope it will solve your problem...
func getAppropriateName(for container: CNContainer?) -> String? {
var name = ""
if (container?.name == "Card") || container?.name == nil {
name = "iCloud"
}
else if (container?.name == "Address Book") {
name = "Google"
}
else if (container?.name == "Contacts") {
name = "Yahoo"
}
else {
name = "Facebook"
}
return name
}
iCloud/yahoo/gmail etc are CNContainer. Gmail/iCloud is of type CNContainerTypeCardDAV. So first you need to fetch all contacts, and then filter the array based on the CNContainerType of that contact. But unfortunately, we cannot identify which CardDav is it, i.e iCloud/Gmail.
Please see more details here: How do we know which CNContainer represents iCloud?
You can achieve this by looking at Contacts framework runtime headers here: https://github.com/JaviSoto/iOS10-Runtime-Headers/tree/master/Frameworks/Contacts.framework
You can call them by performSelector message. It's a bit messy, but works.
Generally what you have to do is following:
CNContactStore* store = [CNContactStore new];
// fetch accounts that sync contacts with your device (array of CNAccount)
// since CNAccount class isn't available by default, we treat it as NSObject for our puproses
NSArray* accounts = [store performSelector:#selector(accountsMatchingPredicate:error:) withObject:nil withObject:nil];
// you can iterate through this array, I just use first one for this example
NSObject* account = [accounts firstObject];
// get identifier of the account for NSPredicate we use next
NSString* accountId = [account performSelector:#selector(identifier)];
// Display name of the account (aka Yahoo, Gmail etc.)
NSString* accountName = [account performSelector:#selector(_cnui_displayName)];
// NSPredicate that help us to get corresponding CNContainer
NSPredicate* containerPredicate = [[CNContainer class] performSelector:#selector(predicateForContainersInAccountWithIdentifier:) withObject:accountId];
// Fetching CNContainer
CNContainer* container = [[store containersMatchingPredicate:containerPredicate error:nil] firstObject];
After that it's all about general usage of CNContainers.
Hope it will help.
PS. It works on iOS 10, for future versions you should check for Contacts.framework runtime changes.
PPS. I didn't check on swift, but should work either.
Sorry for my english.
Good luck :)

iOS Convert phone number to international format

In my iOS app I have to convert a phone number (taken in the contacts) and convert it in international format (to send SMS automatically with an extern library). I saw libPhoneNumber but the problem is that we have to enter the country code, and the app have to work in all (almost) countries, so I don't know what is the user's country.
Here is how the library works :
let phoneUtil = NBPhoneNumberUtil()
let phoneNumberConverted = try phoneUtil.parse("0665268242", defaultRegion: "FR") // So I don't know the country of the user here
print(try? phoneUtil.format(phoneNumberConverted, numberFormat: NBEPhoneNumberFormat.INTERNATIONAL))
formattedPhoneNumberSubstring takes a partial phone number string and formats it as the beginning of a properly formatted international number, e.g. "16463" turns to "+1 646-3".
NSString *formattedPhoneNumberSubstring(NSString *phoneNumber) {
NBPhoneNumberUtil *phoneUtil = [NBPhoneNumberUtil sharedInstance];
phoneNumber = [phoneUtil normalizeDigitsOnly:phoneNumber];
NSString *nationalNumber;
NSNumber *countryCode = [phoneUtil extractCountryCode:phoneNumber nationalNumber:&nationalNumber];
if ([countryCode isEqualToNumber:#0])
return phoneNumber;
NSString *regionCode = [[phoneUtil regionCodeFromCountryCode:countryCode] objectAtIndex:0];
NSString *paddedNationalNumber = [nationalNumber stringByPaddingToLength:15 withString:#"0" startingAtIndex:0];
NSString *formatted;
NSString *formattedSubstr;
for (int i=0; i < paddedNationalNumber.length; i++) {
NSError *error = nil;
formattedSubstr = [phoneUtil format:[phoneUtil parse:[paddedNationalNumber substringToIndex:i] defaultRegion:regionCode error:&error]
numberFormat:NBEPhoneNumberFormatINTERNATIONAL error:&error];
if (getExtraCharacters(formattedSubstr) > getExtraCharacters(formatted)) // extra characters means more formatted
formatted = formattedSubstr;
}
// Preparing the buffer for phoneNumber
unichar phoneNumberBuffer[phoneNumber.length+1];
[phoneNumber getCharacters:phoneNumberBuffer range:NSMakeRange(0, phoneNumber.length)];
// Preparing the buffer for formatted
unichar formattedBuffer[formatted.length+1];
[formatted getCharacters:formattedBuffer range:NSMakeRange(0, formatted.length)];
int j=0;
for(int i = 0; i < phoneNumber.length && j < formatted.length; i++) {
while(formattedBuffer[j] != phoneNumberBuffer[i]) j++;
j++;
}
return [formatted substringToIndex:j];
}
You can get the region using either the users locale or the users geo position.
See stackoverflow question get device location country code for more details.
If you don’t know the country code of a phone number, you can’t generate the international format of it.
You could try using the location of the phone or its region settings to guess the country code, but it won’t be reliable. For example, my phone number is Spanish, I’m currently in Italy and my region is set to New Zealand. My contact list contains numbers from all over the world, and if they weren’t entered in international format there would be no way to guess what country code to use for each number.
If you absolutely have to guess, the best approach might be to think about how the phone would interpret the numbers in the contact list itself. This would require you to determine the country code of the phone’s SIM card. See this answer to a related question for a way of doing that, or here’s some Swift code I’ve used:
let networkInfo = CTTelephonyNetworkInfo()
if let carrier = networkInfo.subscriberCellularProvider {
NSLog("Carrier: \(carrier.carrierName)")
NSLog("ISO: \(carrier.isoCountryCode)")
NSLog("MCC: \(carrier.mobileCountryCode)")
NSLog("MNC: \(carrier.mobileNetworkCode)")
}
The ISO country code can be used to look up a country code for dialling; an example table is in the answer linked above.

if statements and stringWithFormat

I need to know if there is a way to use if statements to display certain nsstrings, depending on whether or not that NSString contains any data.
I have an nsstringcalled visitorInfo.
The string uses data from other strings (i.e. which operating system the user is running) and displays that info. Here is an example of what I'm talking about:
NSString *visitorInfo = [NSString stringWithFormat:#"INFO\n\nVisitor Location\n%#\n\nVisitor Blood Type\n\%#", _visitor.location, _visitor.bloodType];
And it would display like this:
INFO
Location
Miami, FL
Blood Type
O positive
However, I have several pieces of data that only load if the user chooses to do so. i.e their email address.
This section of code below would do what I want, but my visitorInfo string contains tons of different strings, and if I use this code below, then it won't load any of them if the user chooses not to submit his blood type.
if ([self.visitor.bloodType length] > 0) {
NSString *visitorInfo = [NSString stringWithFormat:#"INFO\n\nVisitor Location\n%#\n\nVisitor Blood Type\n\%#", _visitor.location, _visitor.bloodType];
}
So basically if their is data stored in bloodType then i went that code to run, but if there isn't any data I only want it to skip over bloodType, and finish displaying the rest of the data.
Let me know if you have any more questions
Additional details. I'm using an NSString for a specific reason, which is why I'm not using a dictionary.
Just build up the string as needed using NSMutableString:
NSMutableString *visitorInfo = [NSMutableString stringWithFormat:#"INFO\n\nVisitor Location\n%#, _visitor.location];
if ([self.visitor.bloodType length] > 0) {
[visitorInfo appendFormat:#"\n\nVisitor Blood Type\n\%#", _visitor.bloodType];
}
You can check if a string has any data in it by using the following
if([_visitor.location length]<1){
//This means there's no data and is a better way of checking, rather than isEqualToString:#"".
}else{
//there is some date here
}
** EDIT - (just re-reading your question, sorry this answer is dependant on _visitor.location being a string in the first place)*
I hope this helps
Try this -
NSString *str = #"INFO";
if (_visitor.location) {
str = [NSString stringWithFormat:#"\n\nVisitor Location\n%#",_visitor.location];
}
if (_visitor.bloodType) {
str = [NSString stringWithFormat:#"\n\nVisitor Blood Type\n\%#",_visitor.bloodType];
}

iOS Facebook SDK - getting user location

Using FBLoginView I am able to log in users and get a FBGraphUser object which holds data in the following structure:
FBGraphUser
|---username
|---email
|---id<FBGraphPlace> location
|---place_name
|---id<FBGraphLocation> location
|---city
|---street
|---latitude/longitude
See Facebook's documentation for a better picture :)
I am able to get user's FBGraphPlace location with correct place_name data but the FBGraphLocation comes null.
I'd like access to this data, and this is where I'm stumped. I ensured the user's location information is publicly visible, and I set the readPermissions of FBLoginView to include #"user_location".
Does anyone know where I could be making my mistake? Thanks!
Edit - Solution: My Facebook address field was empty. I mistook 'current city' for address.
Try to do this:
id<FBGraphUser> fbUser = (id<FBGraphUser>)user;
id<FBGraphPlace> fbPlace = [fbUser location];
id<FBGraphLocation> fbLocation = [fbPlace location];
NSString * userCity = [fbLocation city];
NSString * userCountry = [fbLocation country];
NSString * userZip = [fbLocation zip];
You are currently accessing the name property of the FBGraphPlace which is giving you an NSString representation of the place. What you want to do instead is access the location property which is an FBGraphLocation. This object has properties for the various components you want.
But i'm not sure this is what you need.

Postal Code Validation in iOS

I am developing an app for iOS 7 in which I want to retrieve user location details.
Now I also want postal code of user. And I want to check on only that page that postal code entered by the user is valid or not.
I want to validate for US and UK.
How to achieve this?
For India, you can use the below method to validate the pincode
-(BOOL)isValidPinCode:(NSString*)pincode {
NSString *pinRegex = #"^[0-9]{6}$";
NSPredicate *pinTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", pinRegex];
BOOL pinValidates = [pinTest evaluateWithObject:pincode];
return pinValidates;
}
For US, you can use
^\d{5}(-\d{4})?$
For UK, use this
^([A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW])\ [0-9][ABD-HJLNP-UW-Z]{2}|(GIR\ 0AA)|(SAN\ TA1)|(BFPO\ (C\/O\ )?[0-9]{1,4})|((ASCN|BBND|[BFS]IQQ|PCRN|STHL|TDCU|TKCA)\ 1ZZ))$
Swift 3.0
For US, you can use the below method to validate the ZipCode
func validZipCode(postalCode:String)->Bool{
let postalcodeRegex = "^[0-9]{5}(-[0-9]{4})?$"
let pinPredicate = NSPredicate(format: "SELF MATCHES %#", postalcodeRegex)
let bool = pinPredicate.evaluate(with: postalCode) as Bool
return bool
}
You can use this answer to get postal code.
Get the Zip Code of the Current Location - iPhone SDK
As for validation, it will depend on the country the postal code is in, but this may be a good starting point.
how to validate Zipcode for US or Canada in iOS?

Resources