Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Hack to choose the displayed carrier name in the iOS simulator
//
// Copyright (c) 2012-2015 Cédric Luthi / @0xced. All rights reserved.
//
#import <Foundation/Foundation.h>
#if TARGET_OS_SIMULATOR
static const char *fakeCarrier;
static const char *fakeTime;
#import <objc/runtime.h>
@interface XCDFakeCarrier : NSObject
@end
@implementation XCDFakeCarrier
/*
Runtime offsets for the -[UIStatusBarComposedData rawData] struct
struct {
BOOL itemIsEnabled[27];
BOOL timeString[64];
int gsmSignalStrengthRaw;
int gsmSignalStrengthBars;
BOOL serviceString[100];
...
}
See https://github.com/nst/iOS-Runtime-Headers/blob/master/Frameworks/UIKit.framework/UIStatusBarComposedData.h
*/
static NSUInteger timeStringOffset;
static NSUInteger timeStringSize;
static NSUInteger gsmSignalStrengthBarsOffset;
static NSUInteger gsmSignalStrengthBarsSize;
static NSUInteger serviceStringOffset;
static NSUInteger serviceStringSize;
+ (void) load
{
fakeCarrier = getenv("FAKE_CARRIER");
if (!fakeCarrier)
{
NSLog(@"You must set the FAKE_CARRIER environment variable");
return;
}
fakeTime = getenv("FAKE_TIME");
const Class UIStatusBarComposedData = objc_getClass("UIStatusBarComposedData");
const Method rawData = class_getInstanceMethod(UIStatusBarComposedData, sel_getUid("rawData"));
const char *typeEncoding = method_getTypeEncoding(rawData);
if (typeEncoding)
{
NSRegularExpression *typeEncodingRegularExpression = [NSRegularExpression regularExpressionWithPattern:@"\\^(\\{\\?=\\[\\d+[Bc]\\]\\[\\d+c\\]ii\\[\\d+c\\])" options:(NSRegularExpressionOptions)0 error:NULL];
NSString *typeEncodingString = @(typeEncoding);
NSTextCheckingResult *typeEncodingMatch = [typeEncodingRegularExpression firstMatchInString:typeEncodingString options:(NSMatchingOptions)0 range:NSMakeRange(0, typeEncodingString.length)];
if (typeEncodingMatch.numberOfRanges > 1)
{
NSString *partialTypeEncoding = [[typeEncodingString substringWithRange:[typeEncodingMatch rangeAtIndex:1]] stringByAppendingString:@"}"];
NSMethodSignature *methodSignature = [NSMethodSignature signatureWithObjCTypes:partialTypeEncoding.UTF8String];
NSString *parsedTypeEncoding = methodSignature.debugDescription;
NSRegularExpression *parsedTypeEncodingRegularExpression = [NSRegularExpression regularExpressionWithPattern:@"^ memory \\{offset = (\\d+), size = (\\d+)\\}" options:NSRegularExpressionAnchorsMatchLines error:NULL];
NSArray<NSTextCheckingResult *> *offsetMatches = [parsedTypeEncodingRegularExpression matchesInString:parsedTypeEncoding options:(NSMatchingOptions)0 range:NSMakeRange(0, parsedTypeEncoding.length)];
if (offsetMatches.count == 5)
{
timeStringOffset = [[parsedTypeEncoding substringWithRange:[offsetMatches[1] rangeAtIndex:1]] integerValue];
timeStringSize = [[parsedTypeEncoding substringWithRange:[offsetMatches[1] rangeAtIndex:2]] integerValue];
gsmSignalStrengthBarsOffset = [[parsedTypeEncoding substringWithRange:[offsetMatches[3] rangeAtIndex:1]] integerValue];
gsmSignalStrengthBarsSize = [[parsedTypeEncoding substringWithRange:[offsetMatches[3] rangeAtIndex:2]] integerValue];
serviceStringOffset = [[parsedTypeEncoding substringWithRange:[offsetMatches[4] rangeAtIndex:1]] integerValue];
serviceStringSize = [[parsedTypeEncoding substringWithRange:[offsetMatches[4] rangeAtIndex:2]] integerValue];
BOOL isTimeStringOK = timeStringOffset > 0 && timeStringSize > 0;
BOOL isSignalStrengthBarsOK = gsmSignalStrengthBarsOffset > 0 && gsmSignalStrengthBarsSize == sizeof(int);
BOOL isServiceStringOK = serviceStringOffset > 0 && serviceStringSize > 0;
if (isTimeStringOK && isSignalStrengthBarsOK && isServiceStringOK)
{
const SEL fakeSelector = @selector(fake_rawData);
const Method fakeRawData = class_getInstanceMethod(self, fakeSelector);
if (class_addMethod(UIStatusBarComposedData, fakeSelector, method_getImplementation(fakeRawData), typeEncoding))
{
method_exchangeImplementations(rawData, class_getInstanceMethod(UIStatusBarComposedData, fakeSelector));
NSLog(@"Using \"%s\" fake carrier", fakeCarrier);
return;
}
}
}
}
}
NSLog(@"XCDFakeCarrier failed to initialize");
}
- (void *) fake_rawData
{
char *rawData = [self fake_rawData];
BOOL isEmptyCarrier = [@(fakeCarrier ?: "") stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]].length == 0;
BOOL isEmptyTime = [@(fakeTime ?: "") stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]].length == 0;
if (isEmptyCarrier && isEmptyTime)
{
bzero(rawData, serviceStringOffset + serviceStringSize);
return rawData;
}
strlcpy(rawData + serviceStringOffset, fakeCarrier, serviceStringSize);
if (fakeTime)
strlcpy(rawData + timeStringOffset, fakeTime, timeStringSize);
int gsmSignalStrengthBars = 5;
memcpy(rawData + gsmSignalStrengthBarsOffset, &gsmSignalStrengthBars, gsmSignalStrengthBarsSize);
BOOL enableSignalBars = YES;
memcpy(rawData + 3, &enableSignalBars, sizeof(enableSignalBars));
BOOL enableBatteryLevelPercentage = YES;
memcpy(rawData + 8, &enableBatteryLevelPercentage, sizeof(enableBatteryLevelPercentage));
/*
0 center Time
1 right Do not Sisturb
2 left Airplane
3 left Signal Bars
4 left Carrier
5 left Wi-Fi
6 right Time
7 right Battery Logo
8 right Battery Level Percentage
9 right Battery Level Percentage
10 right Bluetooth Battery
11 right Bluetooth
12 right TTY
13 right Alarm
14 right Plus
15 unknown
16 right Location Service
17 right Rotation Lock
18 unknown
19 right AirPlay
20 right Siri
21 left Play
22 left VPN
23 left Call Forward
24 left Network Activity Indicator
25 left Black Square
*/
return rawData;
}
@end
#endif
@iosdeveloper

This comment has been minimized.

Show comment
Hide comment
@iosdeveloper

iosdeveloper Jul 2, 2012

Nice for taking screenshots or recording screencasts. Does even run on device!

Nice for taking screenshots or recording screencasts. Does even run on device!

@ksm

This comment has been minimized.

Show comment
Hide comment
@ksm

ksm Jan 29, 2013

Doesn't work on iOS Simulator 6.0, at least for me. (Failed to initialize).

ksm commented Jan 29, 2013

Doesn't work on iOS Simulator 6.0, at least for me. (Failed to initialize).

@0xced

This comment has been minimized.

Show comment
Hide comment
@0xced

0xced Mar 21, 2013

It is now working on iOS 6.0 and 6.1.

Owner

0xced commented Mar 21, 2013

It is now working on iOS 6.0 and 6.1.

@AriX

This comment has been minimized.

Show comment
Hide comment
@AriX

AriX Apr 6, 2013

Nice job on this, great hack.

AriX commented Apr 6, 2013

Nice job on this, great hack.

@twe4ked

This comment has been minimized.

Show comment
Hide comment
@twe4ked

twe4ked Apr 23, 2013

Perfect, thanks for this!

twe4ked commented Apr 23, 2013

Perfect, thanks for this!

@Jules2010

This comment has been minimized.

Show comment
Hide comment
@Jules2010

Jules2010 May 9, 2013

I'm getting this error ld: 2 duplicate symbols for architecture i386, any ideas>

I'm getting this error ld: 2 duplicate symbols for architecture i386, any ideas>

@Jules2010

This comment has been minimized.

Show comment
Hide comment
@Jules2010

Jules2010 May 9, 2013

Never mind, I ended up putting some code into a h file and imported that into my app delegate which solved the problem :)

Never mind, I ended up putting some code into a h file and imported that into my app delegate which solved the problem :)

@DaveM1

This comment has been minimized.

Show comment
Hide comment
@DaveM1

DaveM1 Sep 16, 2013

Hi, this is awesome, but I can't figure out how to display the cellular bar strength and eliminate the WiFi signal Icon. Anyone have insight?

Thanks!

DaveM1 commented Sep 16, 2013

Hi, this is awesome, but I can't figure out how to display the cellular bar strength and eliminate the WiFi signal Icon. Anyone have insight?

Thanks!

@ksuther

This comment has been minimized.

Show comment
Hide comment
@ksuther

ksuther May 10, 2014

A rough example of how to customize other parts of the status bar is available here: https://github.com/ksuther/StatusBarCustomization

ksuther commented May 10, 2014

A rough example of how to customize other parts of the status bar is available here: https://github.com/ksuther/StatusBarCustomization

@KrauseFx

This comment has been minimized.

Show comment
Hide comment
@mpvosseller

This comment has been minimized.

Show comment
Hide comment
@mpvosseller

mpvosseller Apr 13, 2015

Looks like this broke with iOS 8.3.

Looks like this broke with iOS 8.3.

@muhammadbassio

This comment has been minimized.

Show comment
Hide comment
@muhammadbassio

muhammadbassio May 23, 2015

@mpvoseller
Replace statusBarDataInfo with the below & it should work in 8.3 :)

NSDictionary *statusBarDataInfo = @{ @"^{?=[26c][64c]ii[100c]": @"fake_rawData",
                                         // use B instead of c for 64-bit
                                         @"^{?=[26B][64c]ii[100c]": @"fake_rawData" };

@mpvoseller
Replace statusBarDataInfo with the below & it should work in 8.3 :)

NSDictionary *statusBarDataInfo = @{ @"^{?=[26c][64c]ii[100c]": @"fake_rawData",
                                         // use B instead of c for 64-bit
                                         @"^{?=[26B][64c]ii[100c]": @"fake_rawData" };
@0xced

This comment has been minimized.

Show comment
Hide comment
@0xced

0xced Nov 27, 2015

It’s working again for iOS 8 and 9 and should even be future proof now!

Owner

0xced commented Nov 27, 2015

It’s working again for iOS 8 and 9 and should even be future proof now!

@Pranoy1c

This comment has been minimized.

Show comment
Hide comment
@Pranoy1c

Pranoy1c Nov 27, 2015

how to make it work on iPhone 6s? It tried to make it 64 bit like:

NSDictionary *statusBarDataInfo = @{ @"^{?=[25B][64B]ii[100B]": @"fake_rawData",
                                     // use B instead of c for 64-bit
                                     @"^{?=[25B][64c]ii[100c]": @"fake_rawData" };

but didn't work :(

how to make it work on iPhone 6s? It tried to make it 64 bit like:

NSDictionary *statusBarDataInfo = @{ @"^{?=[25B][64B]ii[100B]": @"fake_rawData",
                                     // use B instead of c for 64-bit
                                     @"^{?=[25B][64c]ii[100c]": @"fake_rawData" };

but didn't work :(

@0xced

This comment has been minimized.

Show comment
Hide comment
@0xced

0xced Nov 27, 2015

@Pranoy1c It’s not about the iPhone 6S, it’s about the iOS version. Please try updating to the latest version of the gist.

Owner

0xced commented Nov 27, 2015

@Pranoy1c It’s not about the iPhone 6S, it’s about the iOS version. Please try updating to the latest version of the gist.

@honkmaster

This comment has been minimized.

Show comment
Hide comment
@honkmaster

honkmaster Jul 8, 2017

Any update for iOS 11?

Any update for iOS 11?

@legendero

This comment has been minimized.

Show comment
Hide comment
@legendero

legendero Dec 20, 2017

does it still work?

does it still work?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment