InAppSettingsKit and Storyboard: how to put a back button? - iphone

I'm using the ARC version of the InAppSettingsKit framework (https://github.com/tibr/InAppSettingsKit) to put the settings bundle into my application with Storyboard. I have managed to get the settings work but it shows the settings and I can't go back to the menus of my app.
Any Suggestion? Thanks.

Maybe this will help someone else
I used the main branch with storyboards and the -fno-objc-arc flag but it should be the same solution
I am not sure how you got the back button in your picture above because my button shows as done.
I created a subclass called
#interface SettingsViewController : IASKAppSettingsViewController <IASKSettingsDelegate>
I linked the storyboard to use this class instead of the IASKAppSettingsViewController I added the ShowDoneButton = YES
#implementation SettingsViewController
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
self.delegate = self;
self.showDoneButton = YES;
}
return self;
}
My setup is storyboards with
a modal segue.
a settings button on my main view which links to a navigation controller and a grouped table view

Related

setFinishedSelectedImage:withFinishedUnselectedImage: + Storyboards

I have my interface completely laid out with Storyboards (including the UITabBarController and all corresponding views).
Now comes the time to customize the Tab Bar. Since I have icons that are already set to the correct colour, I can't use [[UITabBar appearance] setTintColor:] (it just keeps looking wrong).
Turns out I'm supposed to use setFinishedSelectedImage:withFinishedUnselectedImage: on the specific UITabBarItem's.
Is it possible to use this method from the AppDelegate (where the rest of my global customization occurs)? How does the AppDelegate know which UITabBar to target?
If instead, I'm supposed to customize each UITabBarItem from each UIViewController, how do I reference the UITabBar (or "root view controller"?) and then specific item from the UIViewController?
Any help would be greatly appreciated.
Thanks!
In viewDidLoad of your UIViewController instances, you can do
[self.tabBarItem setFinishedSelectedImage: withFinishedUnselectedImage:]
Try this
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[self.tabBarItem setFinishedSelectedImage:[UIImage imageNamed:#"t1s"] withFinishedUnselectedImage:[UIImage imageNamed:#"t1"]];
[self.tabBarItem setTitle:#"Title"];
}
return self;
}
Also, delete image in tabbar item from storyboard view

How to correctly integrate InAppSettingsKit with Storyboard in a TabBar?

I have been trying for a while now, but I can't figure out how to integrate InAppSettingsKit in an App, that uses Storyboard and a TabBar.
I've got my tab bar defined in a Storyboard, now I want one tab to have this InAppSettingsKit as the root view. Is this possible after all?
Thanks everyone.
Well, after trying various things, I figured out, that my problem actually was, that I put all the IASK-stuff into a static library (and I had no Settings Bundle). After moving all the code and nibs to the same project as the MainStoryboard, it worked by adding a TableView Controller to my storyboard and settings its custom class to IASKAppSettingsViewController.
Alternatively, if you want button handlers and other custom code, do following:
Create a class derived from UITableViewController
Modify the header file to derive from IASKAppSettingsViewController
<IASKSettingsDelegate> Remove all methods but the initWithCoder and the
settingsViewControllerDidEnd protocol (or make calls to super). This
is so that the default UITableVC code doesn't override IASK
functionality. Be sure to stick self.delegate = self; into the
initWithCoder to get the buttons to work.
//SettingsViewController.h
#import "IASKAppSettingsViewController.h"
#interface SettingsViewController : IASKAppSettingsViewController <IASKSettingsDelegate>
#end
//SettingsViewController.m
// ...
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
self.delegate = self;
}
return self;
}
#pragma mark -
#pragma mark IASKAppSettingsViewControllerDelegate protocol
- (void)settingsViewControllerDidEnd:(IASKAppSettingsViewController*)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
Set custom class of the table view in storyboard to
your class

View is not adjusting itself after hiding Tabbar

I have a UITabbar having 5 tabs like this
Now I want to hide the UITabbar when taps on the Feed Tab. I want to show the full screen there. I am able to hide the tabbar but the UIView of Feed screen is not adjusting itself and I can see the white space at the place of UITabBar. I set the frame of view after hiding the UITabbar but it is also not working. How can I get the object of UITabbarController in the UIViewController classes which are added on the UITabbar so that I can call the delegate methods of UITabbarController. For instance, how can I have the object of UITabbarController in Feed Class.Please Help! If I am not clear please let me know.
Thanks-
Adding to Ariel answer, you need to set "hidesBottomBarWhenPushed" property to YES,when you are loading it from the nib.
As " initWithCoder"-Method is called if you are loading from the nib, you need to set that property there only.
Hope this will help you out.
Try to add self.hidesBottomBarWhenPushed = YES; inside of -(id)initWithCoder:(NSCoder *)aDecoder; of the Feed class implementation like so:
-(id)initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
if(self){
self.hidesBottomBarWhenPushed = YES;
//more of your initialization code...
}
return self;
}
It should be in -(id)initWithCoder:(NSCoder *)aDecoder; and not -(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil; as your view is loaded from the .xib file by the application.
Try to set self.navigationController.view.frame size when you hide the tabbar.
You can get the fullscreen size with [[UIScreen mainScreen] bounds].

Initialization for ViewController under NavController in TabBarController

I have the relatively common setup of a TabBarController whose tabs contain NavigationControllers which have TableViewControllers as their roots. I'm trying to perform some logic on initialization of one of these TableViewControllers but can't seem to find what init function gets called.
My goal is to add a listener in the TableViewController (that I have subclassed) which can respond to events by updating the navigationController.tabBarItem.badgeVluew property.
I've tried putting code into initWithStyle: as well as init but neither of them end up getting called. I've also tried putting it in viewDidLoad, but that only gets called once the controller actually appears (I need to have it happen as soon as the controller is loaded / as soon as the tab bar item shows up).
Does anyone know where I would put this code for it to happen on initialization of the controller?
Also, this is all set up through interface builder / NIBs. I'm not adding the nav controller or tableviewcontroller manually, which is why it's not clear what init function I need to override.
If you select one of your UITabBarItems in IB, you will see 'View loaded from "YourView"'. Click into this "gray" View. In the Inspector window you will see in the Attributes Tab (the tab on the left) the title and the NIB name which will be loaded (lets call it "YourNibName").
Now select the right tab of the inspector (Identity) and change the Classname (Combo next to Class) to your "YourViewController" class, which you must create in xcode. Don't use the standard ViewController, which is already selected. The InterfaceBuilder loads your nib and attaches it to your ViewController.
Open YourNibName and change FilesOwner's Class (Inspector, right Tab) to "YourViewController", too.
Your TabBar's NIB contains a FilesOwner, too. Create a ViewController for this FilesOwner and set its Class to this Controller (i.e. TabBarController)
In "TabBarController" you can find out which Tab was selected by using this code:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
if ([viewController.nibName isEqualToString:#"NIBName1"]){
// Do something here, if you like. (i.e. Save the state in a string or int)
}
if ([viewController.nibName isEqualToString:#"NIBNAme2"]){
// Do something here, if you like. (i.e. Save the state in a string or int)
}
...
}
Here you can do something "global" or preinitialize something. This is ONE thing you can do.
INIT OF YOUR VIEWS:
If you select a Tab and the view (which is handled by YourViewController) will be shown for the first time, "viewDidLoad" will be called in "YourViewController"
- (void)viewDidLoad {
// Here you can add views programatically
[self.view addSubview:myNavigationController.view];
[self.view bringSubviewToFront:myNavigationController.view];
// And if you like, do some INIT here
[super viewDidLoad];
}
I hope this is what your question was about.
Now something about the badge. It's a hack, but works fine for me.
Header file:
Add an outlet to your controller, which is representing your TabBarController:
#interface yourController : UIViewController <UITabBarControllerDelegate> {
UITabBarController *tabBarController;
}
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
#end
Connect this outlet in IB with your TabBar.
Implementation:
In your TabBarControllerClass you can overwrite 'initWithNibName':
#synthesize tabBarController;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
// Do some init here
// select your desired item (it will be loaded)
// then you can assign the badge
tabBarController.selectedIndex = 1;
tabBarController.selectedViewController.tabBarItem.badgeValue = #"222";
// and select the item you will start with
tabBarController.selectedIndex = 0;
// if you like you can add a notification, which you can activate from anywhere else
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(itemBadgeChanged:)
name:#"itemBadgeChangedNotification"
object:nil];
}
return self;
}
if you don't use nib, use '- (void)loadView { ... }' instead.
You are using a subclass of the TabBar controller, maybe you can use 'self.selectedIndex = 1;' instead of 'tabBarController.selectedIndex = 1;', and so on. Just try this out
Hope this helps!

How to disable the edit button that appears in the more section of a UITabBarController?

In my application (based on the Tab bar application XCode template) I use a UITabBarController to display a list of different sections of the application that the user can access.
By default, the UITabBarController displays a 'More' button in the tab bar when there are more than 5 items. Also, it allows the user to select the items that he want to be visible in the tab bar.
Currently I can't implement saving and loading the state of the tab bar controller, so I want to disable the 'Edit' button.
Is there any way to disable/hide the 'Edit' bar button that appears on the 'More' navigation controller of UITabBarController?
I tried:
tabBarController.moreNavigationController.navigationBar.topItem.rightBarButtonItem = nil;
and
tabBarController.moreNavigationController.navigationBar.topItem.rightBarButtonItem.enabled = NO;
but they don't seem to work.
Become a delegate of moreNavigationController (it is a UINavigationController) and add this:
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated {
UINavigationBar *morenavbar = navigationController.navigationBar;
UINavigationItem *morenavitem = morenavbar.topItem;
/* We don't need Edit button in More screen. */
morenavitem.rightBarButtonItem = nil;
}
Now it won't appear. The key thing to consider is that Edit button appears not after controller creation, but before displaying the view, and we should sit silently till that moment and then, when the controller is going to display the screen, we will knock the button out so that it won't have a chance to create it again. :)
customizableViewControllers is an array; set it to the empty array to disable all editing.
tabBarController.customizableViewControllers = [NSArray arrayWithObjects:nil];
tabBarController .customizableViewControllers = nil;
i have tried and here's a example.
In AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Add the tab bar controller's view to the window and display.
[self.window addSubview:tabBarController.view];
[self.window makeKeyAndVisible];
//setting delegate to disable edit button in more.
tabBarController.moreNavigationController.delegate = self;
return YES;
}
to remove the "Edit" Button
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
UINavigationBar *morenavbar = navigationController.navigationBar;
UINavigationItem *morenavitem = morenavbar.topItem;
/* We don't need Edit button in More screen. */
morenavitem.rightBarButtonItem = nil;
}
In your AppDelegate.h
#interface TestAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate, UINavigationControllerDelegate>
correct me if i'm wrong.
I was able to get this working with the following code. I created a CustomTabViewController and then modified my Tab Bar Controller's Class Identity in Interface Builder to use this custom class. Here is the code that it uses (.h and .m file contents). The key is setting the property to nil, which causes the Edit button to not be displayed. For details see: http://developer.apple.com/library/ios/documentation/uikit/reference/UITabBarController_Class/Reference/Reference.html#//apple_ref/occ/instp/UITabBarController/customizableViewControllers
"If the array is empty or the value of this property is nil, the tab bar does not allow any items to be rearranged."
#import <UIKit/UIKit.h>
#interface CustomTabBarController : UITabBarController {
}
#end
#import "CustomTabBarController.h"
#implementation CustomTabBarController
- (void)viewDidLoad
{
self.customizableViewControllers = nil;
[super viewDidLoad];
}
#end
This can be achieved like such. It is not the most elegant solution, but It Works™.
// Optional UITabBarControllerDelegate method
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
[self performSelector:#selector(removeEdit) withObject:nil afterDelay:.0001];
}
- (void)removeEdit
{
tabBarController.moreNavigationController.navigationBar.topItem.rightBarButtonItem = nil;
}
Simply add a line of code in life cycle method i.e. application did finish launching:
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
tabBarController.customizableViewControllers=nil;
}
#m4rkk & #lan terrell that code does not work.
I wasn't able to get it so I just disable the navigation bar altogether.
tabBarController.moreNavigationController.navigationBar.hidden = YES;
I don't know about iOS4, but it matters if you put the code in viewDidLoad vs viewWillAppear.
Ie., this will work.
- (void)viewWillAppear:(BOOL)animated
{
self.customizableViewControllers = nil;
}
If you use NavigationController as your 1st ViewController and press one of the button to enter UITabBarController. Then apart from adding the code below,
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated
{
UINavigationBar *morenavbar = navigationController.navigationBar;
UINavigationItem *morenavitem = morenavbar.topItem;
/* We don't need Edit button in More screen. */
morenavitem.rightBarButtonItem = nil;
}
you need to add this "if statement" to avoid the edit button shows up when you first click the 5th ViewControllers and above.
if (self.selectedIndex >= 4)
{
self.customizableViewControllers = nil;
}
At the ones working with Xcode greater than 4.0 (I'm working on Xcode 4.2 for Snow Leopard):
Check at first where do you change the array of views the last time. I think it doesn't matter in which method you set your customizableView-Array to nil. Apples description says:
Important: Adding or removing view controllers in your tab bar interface also resets the array of customizable view controllers to the default value, allowing all view controllers to be customized again. Therefore, if you make modifications to the viewControllers property (either directly or by calling the setViewControllers:animated: method) and still want to limit the customizable view controllers, you must also update the array of objects in the customizableViewControllers property.
It worked for me, so please try it out.
I found this description here: link to the description on developer.apple.com at chapter "Preventing the Customization of Tabs".
An iPhone 6 Plus will allow more buttons on the tab bar in landscape mode than in portrait. Unfortunately this means it resets the customizableViewControllers array whenever the device is rotated, and none of the answers here worked for me.
I already had my own UITabBarController subclass and overriding the setter and getter methods for customizableViewControllers was the only reliable way to remove the Edit button from the More screen:
- (NSArray *)customizableViewControllers
{
return nil;
}
- (void)setCustomizableViewControllers:(NSArray*)controllers
{
//do nothing
}
This is a late addition but I think it is a helpful contribution. Aleks N's answer can create a situation where the rightBarButtonItem is removed for every view controller under the "More Tab" (as Bao Lei mentioned). I would like to recommend using Bao Lei's Code, but with the difference of implenting it it the didShowViewController delegate method.
As his code exists now, users tapping the "More" tab to return to the base UIMoreViewController table can cause rightBarButtonItem's belonging to other viewControllers to be set to nil.
- (void)navigationController:(UINavigationController *)navigationController
didShowViewController:(UIViewController *)viewController
animated:(BOOL)animated
{
if (navigationController.viewControllers.count == 1)
{
UINavigationBar *morenavbar = navigationController.navigationBar;
UINavigationItem *morenavitem = morenavbar.topItem;
/* We don't need Edit button in More screen. */
morenavitem.rightBarButtonItem = nil;
}
}
The distinction is small but it took me a considerable amount of time to find this bug.
Aleks N's answer works, but I'd like to modify a little bit
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated
{
if (navigationController.viewControllers.count == 1)
{
UINavigationBar *morenavbar = navigationController.navigationBar;
UINavigationItem *morenavitem = morenavbar.topItem;
/* We don't need Edit button in More screen. */
morenavitem.rightBarButtonItem = nil;
}
}
Since this delegate method is called every time when a view controller is pushed or popped on this view stack. When we are pushing other views onto this "More" view controller, we don't want to do this.
The only solution that worked for me
self.moreNavigationController.navigationBar.topItem?.rightBarButtonItem?.title = ""
self.moreNavigationController.navigationBar.topItem?.rightBarButtonItem?.isEnabled = false
I tried most of these solutions and was running into an issue where the edit button would return when rotating the device. The rotation would reset back to the first view controller, then when i returned to the more view controller, the edit button was there. The best solution was to become the UITabBarControllerDelegate and set the right bar button to nil anytime the more view controller became the selected view controller. This is working for iOS 11-12.
final class DashboardController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
delegate = self
}
}
extension DashboardController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
if viewController == moreNavigationController {
moreNavigationController.navigationBar.topItem?.rightBarButtonItem = nil
}
}
}