How to hide statusbar icons in iOS - ios

I want to create a simple mobilesubstrate tweak that hides and shows status bar icons like battery or Carrier or wifi signal indecator. I've seen libstatusbar project but i can't find out how to hide iOS's icons. Is there any other way to do this without the use of this library? I just want to hide and show the default icons

Not possible using public API. You can only hide the entire status bar, not only certain elements of it.
For jailbreak, take a look at:
https://github.com/nst/iOS-Runtime-Headers/blob/master/Frameworks/UIKit.framework/UIStatusBarItem.h
In particularly, look at the following methods:
+ (BOOL)itemType:(int)arg1 idiom:(int)arg2 appearsInRegion:(int)arg3;
+ (BOOL)itemType:(int)arg1 idiom:(int)arg2 canBeEnabledForData:(id)arg3 style:(id)arg4;
These methods are consulted whether iterms should appear or not. Return NO here to disable items.

Here is what I use in my tweak:
int itemToHide = 0;
[[objc_getClass("SBStatusBarStateAggregator") sharedInstance] beginCoalescentBlock];
[[objc_getClass("SBStatusBarStateAggregator") sharedInstance] _setItem:itemToHide enabled:NO];
[[objc_getClass("SBStatusBarStateAggregator") sharedInstance] endCoalescentBlock];
Only problem - iOS uses integer values for status bar items and they're different on different iOS versions. You could test every iOS version and store values for each one of them but I found a better way.
I hook SBStatusBarStateAggregator _setItem:(int)arg1 enabled:(BOOL)arg2 method. Then I call one of the SBStatusBarStateAggregator -(void)_update**** methods. For example, let's say I want to find location icon index. I call SBStatusBarStateAggregator -(void)_updateLocationItem method. It then will call hooked SBStatusBarStateAggregator _setItem:(int)arg1 enabled:(BOOL)arg2 where I will store the index.
I also hook SBStatusBarStateAggregator -(void)_notifyItemChanged:(int)arg. This method is called as part of SBStatusBarStateAggregator -(void)_update**** call. When determing status bar icon index I simply ignore calls to it by returning without calling original implementation.
And if you want to permanently hide some of the icons you still need to hook SBStatusBarStateAggregator _setItem:(int)arg1 enabled:(BOOL)arg2 and SBStatusBarStateAggregator -(void)_notifyItemChanged:(int)arg in order to ignore any iOS attempts to show hidden icons. For example, signal level and data/time are reanabled every time they're updated.
That's all for iOS 7. On iOS 5-6 API is different but I use pretty much the same approach. To hide status bar item
int itemToHide = 0;
[[objc_getClass("SBStatusBarDataManager") sharedDataManager] setStatusBarItem:itemToHide enabled:NO];
I hook SBStatusBarDataManager -(void)updateStatusBarItem:(int)item to determine icon index and then call SBStatusBarDataManager -(void)_locationStatusChange in case of location icon.

Ok. Here is solution.
In your plist file add row:
View controller-based status bar appearance : NO
Make a category on UINavigationBar with this content:
#import "UINavigationBar+StatusBar.h"
#import
#implementation UINavigationBar (StatusBar)
+ (void)load
{
[self swizzleOriginalSelectorWithName:#"layoutSubviews" toSelectorWithName:#"my_layoutSubviews"];
}
- (void)my_layoutSubviews
{
[self my_layoutSubviews];
[self setFrame:CGRectMake(0, 0, self.frame.size.width, 64)];
}
+ (void)swizzleOriginalSelectorWithName:(NSString *)origName toSelectorWithName:(NSString *)swizzleName
{
Method origMethod = class_getInstanceMethod([self class], NSSelectorFromString(origName));
Method newMethod = class_getInstanceMethod([self class], NSSelectorFromString(swizzleName));
method_exchangeImplementations(origMethod, newMethod);
}
#end
This will increase navigation bar for 20pt.
Then, make your custom view for status bar.
e.g.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self makeCustomSatusBar];
// Override point for customization after application launch.
return YES;
}
- (void)makeCustomSatusBar
{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
UIColor *statusBarColor = [UIColor blackColor];
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.window.frame.size.width, 20)];
view.layer.zPosition = INT_MAX;
view.backgroundColor = [UIColor clearColor];
// Making time label
NSDateFormatter *formatter = [NSDateFormatter new];
formatter.dateFormat = #"HH:mm";
UILabel *timeLabel = [UILabel new];
timeLabel.text = [formatter stringFromDate:[NSDate date]];
timeLabel.textColor = statusBarColor;
timeLabel.font = [UIFont systemFontOfSize:12];
[timeLabel sizeToFit];
timeLabel.center = CGPointMake(view.frame.size.width/2, view.frame.size.height/2);
[view addSubview:timeLabel];
//
// make other indicators you need...
//...
[self.window addSubview:view];
}
And you will have something like this:
Note, that you need to update values of your custom view every time (i.e. time label, battery, etc..) , so it would be better to make a separate class for your status bar, and make a infinite timer with 1 sec of tick and do your updates in timer's action.

may be you just need this?
[[UIApplication sharedApplication] setStatusBarHidden:YES]
And if you want just empty view on top of 20pt height, then make that and add to UIWindow, and shift down subview of UIWindow for 20 pt

Related

Forcing app to use Apple Keyboard in iOS 8

How can I get my app's UITextfields to only use the Apple keyboard in iOS 8? I do not want to allow third party keyboards, period. I understand it may be bad user experience so please don't discuss that point with me :)
I know I can set the securedEntry property to true to force the Apple keyboard (http://www.imore.com/custom-keyboards-ios-8-explained). Maybe iOS 8 will let me set this property and NOT mask the text?
Apple provides an API for exactly that. Put this in your AppDelegate
- (BOOL)application:(UIApplication *)application
shouldAllowExtensionPointIdentifier:(NSString *)extensionPointIdentifier
{
if ([extensionPointIdentifier isEqualToString:#"com.apple.keyboard-service"]) {
return NO;
}
return YES;
}
This is the cleanest and documented way to do it :)
By setting a UITextView or UITextField's property of Secure Text Entry to YES, custom keyboards will not be shown by default and can also not be toggled to.
This will also, unfortunately, hide key press information as well as over-ride and disable auto caps and auto correct and spelling suggestions. So you have to toggle is back off to NO after you're done forcibly making the user use Apple keyboard.
Toggling this property on and then off can force the Apple Keyboard to be the first key that displays by default.
NOW, the user will still be able to press the global key so you have two options:
•One, you can just let them and detect if they do using [[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(inputModeDidChange:) name:#"UITextInputCurrentInputModeDidChangeNotification"
object:nil]; and just reloop the secureTextEntry code above and force switch back to Apple default keyboard (unprofessional method, but very easy to program). (*Note! This will also prevent users from being able to use the dictation keyboard (clicking the microphone icon button next to the space bar), unless you use undocumented code to detect if it's dictation or not (which does exist and has supposedly passed Apple validation on a few accounts. Info on this can be found here)
Or
•Two: to use UIWindows to get ONTOP of the default keyboard and add a UIWindow with userInteractionEnabled set to YES covering where that key is location (this will take a few conditional statements to make sure you're covering the right "change keyboard key" for every possibility. (i.e. landscape keyboard iPhone4, portrait keyboard iPhone5, etc).
Here is some demo code though of it working for portrait keyboards (iphone5 and iphone4)
viewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITextFieldDelegate> {
UITextField *theTextField;
UIWindow *statusWindow;
}
#end
viewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
theTextField = [[UITextField alloc] initWithFrame:CGRectMake(50, 50, 50, 250)];
[theTextField becomeFirstResponder];
theTextField.secureTextEntry = YES;//turn back OFF later (like in `viewDidAppear`) and reset textField properties to YES (like auto correct, auto caps, etc).
theTextField.delegate = self;
[self.view addSubview:theTextField];
//UIWindow *statusWindow; MUST be defined in .h file!
statusWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
statusWindow.frame = CGRectMake(37, self.view.frame.size.height-47, 45, 45);
statusWindow.windowLevel = UIWindowLevelStatusBar;
statusWindow.hidden = NO;
statusWindow.backgroundColor = [UIColor clearColor];
UIButton *keyboardCover = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 45, 45)];
keyboardCover.backgroundColor = [UIColor redColor];
[statusWindow addSubview:keyboardCover];
//statusWindow.alpha = 1.00;
statusWindow.userInteractionEnabled = YES;
[statusWindow makeKeyAndVisible];
}
-(void)viewDidAppear:(BOOL)animated {
[theTextField resignFirstResponder];
theTextField.secureTextEntry = NO;
theTextField.autocorrectionType = 2;//ON
theTextField.autocapitalizationType = 2;//ON
theTextField.spellCheckingType = 2;//ON
[theTextField becomeFirstResponder];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Here is an example of what that code will look like... I was using a custom keyboard, when I launched the app it forced me over to the Apple keyboard, then put a red square over the "change keyboard" button, which made it impossible for me to click the button to change the keyboard. (the red square can be changed to be anything of course like a blank key or the globe icon in a faded (disabled) state.)
To the best of my knowledge, there is no way to do this. However, if you're willing to put in the effort, you could create your own custom input view that mimics the standard Apple keyboard, and use that instead. For more on input views, refer to the documentation.

IOS7 : uisearchdisplaycontroller always show scope bar

Basically what I'm trying to achieve is to have my scope bar to never disappear.
Environment : IOS 7, storyboard, inside a view controller I have a "search bar and search display controller" and a separate tableview (the searchbar is not inside the table)
Inside the view controller.h
#property (nonatomic, strong) IBOutlet UISearchBar *candySearchBar;
Inside the view controller.m
#synthesize candySearchBar;
What I tried : inside a custom search bar class
- (void) setShowsScopeBar:(BOOL) showsScopeBar
{
if ([self showsScopeBar] != showsScopeBar) {
[super invalidateIntrinsicContentSize];
}
[super setShowsScopeBar:showsScopeBar];
[super setShowsScopeBar: YES]; // always show!
NSLog(#"setShowsScopeBar searchbar");
NSLog(#"%hhd", showsScopeBar);
}
and
searchBarDidEndEditing
Same thing in the view controller, but then
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[candySearchBar setShowsScopeBar:YES];
[candySearchBar sizeToFit];
}
I hope my question is clear, I tried many solutions posted all over the internet, most of them talk about the setshowsscopebar, but it doesn't seem to work. The output of the log in setshowscopebar is 1, but the scopebar is still not shown.
I still consider myself to be new to the code, the fault can still be a newbie mistake.
edit : another piece of code in the view controller, as you can see i'm searching blind:
-(void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller{
self.searchDisplayController.searchBar.showsCancelButton = YES;
self.searchDisplayController.searchBar.showsScopeBar = YES;
controller.searchBar.showsScopeBar = TRUE;
controller.searchBar.frame = CGRectMake(0, 149, 768, 88);
UIButton *cancelButton;
UIView *topView = self.searchDisplayController.searchBar.subviews[0];
for (UIView *subView in topView.subviews) {
if ([subView isKindOfClass:NSClassFromString(#"UINavigationButton")]) {
cancelButton = (UIButton*)subView;
}
}
if (cancelButton) {
//Set the new title of the cancel button
[cancelButton setTitle:#"Cancel" forState:UIControlStateNormal];
[cancelButton setEnabled:YES];
controller.searchBar.showsScopeBar = YES;
//candySearchBar.scopeButtonTitles = [NSArray arrayWithObjects:#"Flags", #"Listeners", #"Stations", nil];
}
NSLog(#"%#",NSStringFromCGRect(controller.searchBar.frame));
NSLog(#"%#",NSStringFromCGRect(controller.searchBar.bounds));
NSLog(#"%hhd#",controller.searchBar.hidden);
}
The code you tried will not work in iOS7 onward because apple has changed it behavior of UISearchBar to hide the scope when return to normal view. Add this method to your custom searchBar class.
-(void)layoutSubviews
{
[super layoutSubviews];
if([[UIDevice currentDevice].systemVersion floatValue]>=7.0) {
//Get search bar with scope bar to reappear after search keyboard is dismissed
[[[[self.subviews objectAtIndex:0] subviews] objectAtIndex:0] setHidden:NO];
[self setShowsScopeBar:YES];
}
}
Directly accessing object at index may crash the app in iOS6 because of difference in view hierarchy between iOS6 and iOS7, to avoid this, add this inside if condition only when its iOS7.
In addition this is also required in the custom search bar class
-(void) setShowsScopeBar:(BOOL)showsScopeBar {
[super setShowsScopeBar:YES]; //Initially make search bar appear with scope bar
}
I have the same issue. Perhaps it is something that has changed in iOS7 since showing the scope bar is supposed to be the default behaviour. You can verify this in the section "Creating an Optional Scope Bar to Filter Results" of the following tutorial:
http://www.raywenderlich.com/16873/how-to-add-search-into-a-table-view
Hopefully someone has a solution for this; otherwise we will have to look for a workaround.
initialize set scope bar NO
[self.searchBar setShowsScopeBar:NO];
[self.searchBar sizeToFit];
//default scope bar selection
self.searchBar.selectedScopeButtonIndex=3;
unselect/remove tick from scopeBar checkbox
It's possible (but hacky) to do this without a custom searchBar, in a pretty similar way to what CoolMonster suggests.
In your TableViewController, this will show the ScopeBar after a search ends:
- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller
{
//Show the scopeBars
controller.searchBar.showsScopeBar = YES;
//Resize the searchBar to show ScopeBar
controller.searchBar.frame = CGRectMake(0, 0, 320, 88);
if([[UIDevice currentDevice].systemVersion floatValue]>=7.0) {
[[[[controller.searchBar.subviews objectAtIndex:0] subviews] objectAtIndex:0] setHidden:NO];
}
}
Then, since you probably want it to appear before you search, add this line to the TableViewController's viewDidLoad:
[self searchDisplayControllerDidEndSearch:self.searchDisplayController];
For the record, after getting this to work, I ended up using a separate segmented control instead of the approach above for several reasons, not least of which was that touching the ScopeBar of a SearchBar, once you get it to display, launches the search display tableView, which makes of sense if you're using it the recommended way. However, since I wanted the ScopeBar to work without launching the search tableview, for me it made more sense just to use my own segmented control and add it to my tableHeaderView under the searchBar.

Changing background image of UINavigationBar in ios < 5

I have a problem to change the background image of a UINavigationBar for IOS version < 5. I read already about one good solution, which is based on method swizzling, but the problem of this solution is when I add the image it covers everything include the buttons on a navigation bar.
I found a solution which partially worked for me it is base on a following code:
#interface UINavigationBar (UINavigationBarCategory)
-(void)setBackgroundImage:(UIImage*)image withTag:(NSInteger)bgTag;
-(void)resetBackground:(NSInteger)bgTag;
#end
#implementation UINavigationBar (UINavigationBarCategory)
-(void)setBackgroundImage:(UIImage*)image withTag:(NSInteger)bgTag{
if(image == NULL){ //might be called with NULL argument
return;
}
UIImageView *aTabBarBackground = [[UIImageView alloc]initWithImage:image];
aTabBarBackground.frame = CGRectMake(0,0,self.frame.size.width,self.frame.size.height);
aTabBarBackground.tag = bgTag;
[self addSubview:aTabBarBackground];
//[self sendSubviewToBack:aTabBarBackground];
[aTabBarBackground release];
}
-(void)setRightButton:(UIButton*)button withTag:(NSInteger)bgTag{
if(button == NULL){ //might be called with NULL argument
return;
}
[self addSubview:button];
}
/* input: The tag you chose to identify the view */
-(void)resetBackground:(NSInteger)bgTag {
[self sendSubviewToBack:[self viewWithTag:bgTag]];
}
#end
I used this Category in my ViewWillAppear methods like this:
-(void) viewWillAppear:(BOOL)animated {
UIImage *backgroundImage = [UIImage imageNamed:#"background_confernce_import_logo"];
if ([self.navigationController.navigationBar respondsToSelector:#selector(setBackgroundImage:forBarMetrics:)])
{
[self.navigationController.navigationBar setBackgroundImage:backgroundImage forBarMetrics:UIBarMetricsDefault];
}
else{
[[self.navigationController navigationBar] setBackgroundImage:backgroundImage withTag:8675309];
}
}
In else clause I call setBackgroundImage. It is ok, but the problem is that if I have a right button on navigation bar of page 1 for example and go to page 2 after come back to page 1 the button is disappear. I should change the background image of navigation bar in every page in my application like this in viewWillAppear method where I put the new image.
Any help will be appreciated. Under IOS 5 there are no such problem, but it should work on both versions.
I hate to say it, but your approach (adding a subview to hold the background) will not work exactly for the reason you mention. Each time the navigation bar is redrawn, the subview will not keep its z-order (and thus it will cover other UI elements). This behavior is described by other sources (see this, e.g.)
If you don't want to use swizzling, you could override drawRect in a category, so that the background is always drawn correctly. (this last option has the drawback that any navigation bar in your app will be drawn with the same background). This is a sample code I use:
#implementation UINavigationBar (CustomBackground)
- (void)drawRect:(CGRect)rect {
UIImage *image = [UIImage imageNamed: #"back.png"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
#end
A different approach could be:
subclassing UINavigationBar;
overriding drawRect;
in Interface Builder, set the class of your navigation bar object to your UINavigationBar subclass.
I haven't tried it, but it should work.
As per request, here comes my slightly naughty and not really polished hack. This is really just for making the OP happy. The right answer was given by sergio.
UINavigationBar+CustomDraw.m
NSString *gNavbarBackgroundImageName = #"default_navbar_background.png";
#implementation UINavigationBar (CustomBackground)
- (void)drawRect:(CGRect)rect
{
if (gNavbarBackgroundImageName != nil)
{
UIImage *image = [UIImage imageNamed:gNavbarBackgroundImageName];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
}
#end
UINavigationBar+CustomDraw.h
extern NSString *gNavbarBackgroundImageName;
And here comes the example usage in two view controllers...
FooViewController.m
#import "UINavigationBar+CustomDraw.h"
#implementation FooViewController
- (void)viewWillAppear:(BOOL)animated
{
gNavbarBackgroundImageName = #"foo_navbar_background.png";
[self.navigationController.navigationBar setNeedsDisplay];
}
#end
BarViewController.m
#import "UINavigationBar+CustomDraw.h"
#implementation BarViewController
- (void)viewWillAppear:(BOOL)animated
{
gNavbarBackgroundImageName = #"bar_navbar_background.png";
[self.navigationController.navigationBar setNeedsDisplay];
}
#end
Now let us assume you want to show a non-styled navigation bar, for example when displaying a Facebook login page (as provided by their SDK).
Use this to prevent any custom drawing:
gNavbarBackgroundImageName = nil;
Note Some of Apple's components use the UINavigationBar at places you might not have thought of. For example, the MPMoviePlayerController uses a custom navigation bar for displaying the upper part of its UI - so that would be another case where you want to prevent custom drawing.

How to reload a UISplitViewController object when settings have changed?

I've looked at the Apple appPrefs code sample, but that seems to be for navigation controllers only. I'm working with an iPad UISplitViewController that has simple root and detail VCs.
I can change certain settings (colors, date formats, etc) but currently, I have to restart the app to have the changes effected. I would prefer not to have to restart the app.
I'm using a system of loading the settings when the app starts each time. I can get a notification system to work, but I don't know how to reload the view controllers.
Any ideas how to do this (I guess reload the views somehow).
Thanks for any tips/advice. I can post some code if relevant.
If you use settings bundle to manage preferences from the Settings app:
From what you said in your question, you already know how to get a notification(UIApplicationDidBecomeActiveNotification) when your app becomes active, right?
If so, the only problem left is how to reload your view after you receive the notification. Other than UITableView, which can be easily reloaded by calling [tableView reloadData], you have to reload your view by assigning values to the UI controls that you want to reload just as you set them up initially. Say you have a UILabel label you want to reload with the newly set preference value, you just write code like this:
- (void)reloadView {
label.text = [[NSUserDefaults standardUserDefaults] stringForKey:#"PreferenceKey"];
self.view.background = …
[self.tableView reloadData];
}
- (void)reloadViewOnAppActivation:(NSNotification *)notif {
[self reloadView];
}
If you are using in app preferences setting:
If the preferences view controller does not display simultaneously with the SplitViewController. Reload your views in their controllers' viewWillAppear: methods:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self reloadView]; // See the definition of reloadView above
}
Otherwise, make the SplitViewController the delegate of, or assign it to an ivar of, the preferences view controller, and notify it of the preferences changes when appropriate — immediately after changing any single preference if you prefer in realtime update, or after all the changes are done if you prefer batch update:
// SplitViewController methods:
- (void)preferencesAreChanged {
[self reloadView]; // See the definition of reloadView above
}
// Preferences view controller methods:
// Immediate update, use a preference controlled by a `UISegmentedControl` as an example
- (void)viewDidLoad {
[super viewDidLoad];
…
[segmentedControl addTarget:self action:#selector(xPreferenceTogglingAction:) forControlEvents:UIControlEventValueChanged];
…
}
- (IBAction)xPreferenceTogglingAction:(id)sender {
// Update the x preference.
…
[delegate preferencesAreChanged];
}
// Batch update
- (void)viewWillDisappear:(BOOL)animated {
[delegate preferencesAreChanged];
[super viewWillDisappear:animated];
}
So, to help others, I will post how I (with help from Apple) solved this.
In both root and detail view controllers, I added in styles based on user settings:
"Warm Tones", "Cool Tones", "Leather" etc. These translate to code like this:
switch (styleKey) {
case 0: // BASIC
fontName = #"Copperplate";
fontSize = 16;
selectedBarColor = [UIColor lightGrayColor];
selectedTintColor = [UIColor lightGrayColor];
selectedFontColor = [UIColor darkGrayColor];
backgroundColor = [UIColor whiteColor];
selectedHighlightColor = UITableViewCellSelectionStyleGray;
backgroundImage = nil;
detailBackgroundImage = nil;
break;
Then, whenever a color/style/font is called, I used something like this:
cell.selectionStyle = selectedHighlightColor;
cell.backgroundColor = backgroundColor;
This allowed me to change the settings and styles, but I still had to restart the app each time to see the changes.
The fix turned out to be simple.
Settings the styles changed the values of the constants (e.g. fontColor) - but I wasn't actually changing the fields.
So at the end of the switch statements, all I added was something like this:
self.tableView.backgroundColor = backgroundColor;
self.navigationController.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:backgroundImage]];
self.navigationController.navigationBar.tintColor = selectedBarColor;
self.tableView.separatorColor = selectedTintColor;
I had to do this in both view controllers.
Also, all this code was part of a routine (changeSettings).
This method is being observed to look for changes.
The way I handled the in-app preference look and feel (a modal VC) was to use the terrific InAppSettingsKit.
I hope this helps others. Most of you will find this a no-brainer I expect, but - having not much brain left - it took me two weeks to figure it out.

MTLocation how-to

Hi I just came across MTLocation here: https://github.com/darkseed/MTLocation.
I want to use a locate me button in my app which will be located in navigation bar and when pressed will move the map to current location.
The author proposes to use the code like this:
// Configure Location Manager
[MTLocationManager sharedInstance].locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[MTLocationManager sharedInstance].locationManager.distanceFilter = kCLDistanceFilterNone;
[MTLocationManager sharedInstance].locationManager.headingFilter = 5; // 5 Degrees
// create locate-me item
MTLocateMeBarButtonItem *locateMeItem = [[[MTLocateMeBarButtonItem alloc] initWithLocationStatus:MTLocationStatusIdle] autorelease];
// set delegate that is called when mode of Button changes
locateMeItem.delegate = [MTLocationManager sharedInstance];
// add target-action
[locateMeItem addTarget:self action:#selector(myCustomSelector:) forControlEvents:UIControlEventTouchUpInside];
// disable heading
locateMeItem.headingEnabled = NO;
// create array with ToolbarItems
NSArray *toolbarItems = [NSArray arrayWithObject:locateMeItem];
// set toolbar items
[self.toolbar setItems:toolbarItems animated:NO];
which is great to show a locate me button in toolbar but how can we make this work to show current location through gps? I guess tha we have to implement myCustomSelector method but I do not know how. Any help?
Make sure that you have
self.mapView.showsUserLocation = YES;
And then implement myCustomSelector:, for example like this:
- (void) myCustomSelector:(MTLocateMeBarButtonItem*) button {
[self.mapView setCenterCoordinate:self.mapView.userLocation.location.coordinate];
}
You'll need to take care of a proper functionality at different button modes (whether MTLocateMeBarButton is Idle, or something else), but that should give you a direction.

Resources