I have an app with a tab bar controller. One of these views is a table view. There is a method to set the badge of this view in the tab bar. This works...but only when the user touches this view and not right on launching the app. So I tried to use this method in appDelegate...but this doesn`t work.
my method in the view:
#property (strong) NSMutableArray *cars;
//some code here
-(void)SelectBadge
{
int r = [_cars count];
if (r == 0) {
self.navigationController.tabBarItem.badgeValue = 0;
}
else {
self.navigationController.tabBarItem.badgeValue = [NSString stringWithFormat:#"%d", r];
}
[self.tableView reloadData];
}
I tried to put this method in my appDelegate file:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
CarList *Instance = [[CarList alloc] init];
[Instance SelectBadge];
}
Thanks to all your answers beforehand.
The way I see it is you are creating a new intance of CarList in this - (void)applicationDidBecomeActive:(UIApplication *)application method. So In selectBadge function the self.navigationController.tabBarItem.badgeValue = someValue; will be setting badge value for some other instance.
Try addressing the correct instance. If you can access the UITabBarController instance then you can do this:
UITabBar *tabBar = mTabBarController.tabBar;
UITabBarItem *someItem = [tabBar.items objectAtIndex:0];////You can put your interested tabBarItem index
someItem. badgeValue = #"100";
Assuming your ViewControllers are loaded from a StoryBoard, call your function to update the tabBarItem badgeValue in 'initWithCoder:' of the ViewController whose tabBarItem badgeValue you want to update. The ViewControllers that are associated with tabs in the TabBarController are initialized when the TabBar loads.
The code could look something like this:
- (id) initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
NSString* badgeValue = [self calculateBadgeValue]; //your method
self.tabBarItem.badgeValue = badgeValue;
return self;
}
If you do this, the badge should update when the TabBar becomes visible.
Related
I have no idea how I should correctly name the title but I know exactly what my problem is (I will eventually edit the title later).
I am pretty new to Objective-C and I am still learning.
So, I have a class that contains a tableView (I will call it ClassA) and another with a normal UIView (ClassB). What I want to do, is to let a button appear when a row is selected.
I created in my ClassB.h file:
+(id)sharedInstance;
#property (retain, nonatomic) IBOutlet UIButton *btn;
-(void) showBtn :(BOOL) show;
And in my ClassB.m file:
#synthesize btn;
static ClassB *this = nil;
(+id) sharedInstance {
if(!this) {
#synchronized (self) {
this = [[ClassB alloc] init];
}
}
return this;
}
-(void)viewDidLoad {
[self showBtn:NO] //because I only want to let it appear when a row is selected.
[self.view addSubview:btn];
}
-(void) showBtn :(BOOL) show { // I called this method in classA.
if (show == NO) {
btn.hidden = YES;
} else {
btn.hidden = NO;
}
}
So when I launch my app, the button is hidden and stays hidden when I select a row. I debugged, and found that btn is nil when I called the method in ClassA. After some research, I found that the method is called for another instance, so here my question, what can I do, to get it called for the right instance?
EDIT
Here part of my ClassA.m
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSInteger row = [indexPath row];
[[ClassB sharedInstance] showBtn:YES];
}
Observation: The ClassB is a UIViewController which is wrong. UIViewControllers have viewDidLoad.
Implementation Suggestion:
The correct implementation for the requirement would be that you create a custom cell with a button. Hide the button in awakeFromNib method. in didSelectRowAtIndex set the cell.button.isHidden = YES.
This should alone take care of the requirement mentioned above.
I've been working with the Apple sample code for viewing documents from here:
https://developer.apple.com/library/ios/samplecode/DocInteraction/Listings/ReadMe_txt.html
I have removed all the bits I don't need and got it working pretty much how I would like it to. The problem is I don't want users to have access to the "Actions" menu on the top right of the Document Controller. This appears every time you select a document from the list:
Ideally I would like to remove the button all together, though if I could disable it or disable all the options inside it that would also suffice. I found this question:
Open in + UIDocumentInteractionController : how to filter options in SDK iOS 6 (canPerformActions is deprecated)
But I couldn't figure out how to use the suggestion to disable the options inside the menu. I have uploaded the modified sample code here:
http://plasma.servebeer.com/DocSampleCode.zip
One final note is this will not be going on the App Store it is for private, personal use, so if there is an unofficial way then I would be interested in knowing that too.
Any help would be greatly appreciated, thanks in advance.
Plasma
Use UINavigationControllerDelegate
#interface DITableViewController () <UIDocumentInteractionControllerDelegate, UINavigationControllerDelegate>
Assign navigationController delegate to self
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationController.delegate = self;
}
Change documentInteractionControllerViewControllerForPreview
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)interactionController {
return self.navigationController;
}
Add this UINavigationControllerDelegate method
// Called when the navigation controller shows a new top view controller via a push, pop or setting of the view controller stack.
- (void)navigationController:(UINavigationController*)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if ([viewController isKindOfClass:[QLPreviewController class]]) {
viewController.navigationItem.rightBarButtonItem = nil;
}
}
Update for MP4 files
In MP4 files the action button is on the UIToolbar
- (void)navigationController:(UINavigationController*)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if ([viewController isKindOfClass:[QLPreviewController class]]) {
viewController.navigationItem.rightBarButtonItem.customView = [[UIView alloc] init];
UIBarButtonItem *item = viewController.toolbarItems.firstObject;
item.customView = [[UIView alloc] init];
}
}
N.B. This might not work in future versions of iOS
After creating QLPreviewController class you would need to set rightBarButtonItem to nil. Code snippet:
QLPreviewController *previewController = [[QLPreviewController alloc] init];
previewController.navigationItem.rightBarButtonItem = nil;
I did download project and after execution "Action" button was shown not in the top navigation item, but in the toolbar. Then in this case you would need to subclass QLPreviewController and override viewWillAppear as shown below.
#implementation ExViewController
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSMutableArray *a = [NSMutableArray arrayWithArray:#[]];
for (NSUInteger i = 0; i < self.toolbarItems.count; i++) {
if (i == 0) {
continue;
}
[a addObject:self.toolbarItems[i]];
}
}
#end
If you want to hide button the give answers will not work for iOS 10.0 and above in Swift language. You can use WKWebView. Hope it will save your time.
Okay it seems like I have made some mistakes and I did not get it with pointer and initializations by now...
Here is the problem :
I have a UIViewController for a registration process called : RegisterViewController
It calls a method in its ViewDidLoad :
[self performSelector:#selector(activateUsernamePopover) withObject:nil afterDelay:0.1];
This method looks like this :
- (void) activateUsernamePopover {
PopoverViewController *popcontroller = [[PopoverViewController alloc] init];
popcontroller.title = nil;
[popcontroller setPopoverText:#"Test"];
FPPopoverController *popover = [[FPPopoverController alloc] initWithViewController:popcontroller];
popover.arrowDirection = FPPopoverArrowDirectionUp;
popover.border = NO;
popover.tint = MgoGreyTint;
[popover setShadowsHidden:true];
[popover presentPopoverFromView:_usernameInput]; }
This will made a Popover visible. This works great.
But I Do have a few more TextFields where I want to show a Popover with a different text.
So I made a method in the PopoverViewController called setPopoverText :
- (void)setPopoverText:(NSString *)text {
[_popoverLabel setText:text];
[_popoverLabel setNeedsDisplay]; }
I call it in my activateUsernamePopover method :
[popcontroller setPopoverText:#"Test"];
And there is the problem.
I can log the text in the PopoverViewControllers method setPopoverText its fine.
But it did not change the text. I logged the _popoverLabel like this :
NSLog(#"%#",_popoverLabel);
and its (null).
I know there is some issue with the pointer or the instance of PopoverViewController I am working with, but objective c is not that clear to me yet.
Anyone got some answers for me ?
How can I change the Text of that UILabel ?
I also could imagine giving the Text to the Controller while instancing it.
Something like that :
PopoverViewController *popcontroller = [[PopoverViewController alloc] initWithPopoverText:#"Test"];
But I don´t know how. I don´t need to change the Text while the popover is visible. It will be released when the user taps in the TextField or elsewhere.
Thanks so far.
Since the UILabel is not created yet when you call init method. the way to do it is to keep text in the NSString property.
In you PopoverViewController, create the init method like this
#interface ViewController : UIViewController
- (id)initWithPopoverText:(NSString *)text;
#end
In the implementation file, keep hold of the text in the property and on viewDidLoad, you could set the text to the label.
#interface PopoverViewController ()
#property (nonatomic) NSString *popoverText;
#end
#implement PopoverViewController
- (id)initWithPopoverText:(NSString *)text {
self = [super init];
if (self) {
_popoverText = text;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
//set label.text here
self.popoverLabel.text = self.popoverText;
}
#end
I am new to iPad development. I know how to use images for Page view controller. My problem is i have 3 charts which i have done in three view controllers.. How can i combine all the view controllers in a single page view controller. I have for now kept three view controllers.
I have tried lot of tutorials but none explains me how to use three view controllers
I have done like this now but this is wrong
-(IBAction)handleSwipeLeft:(UISwipeGestureRecognizer*)sender {
LastLearningSessionViewController *last=[[LastLearningSessionViewController alloc]init];
[self presentViewController:last animated:YES completion:nil];
}
From what I can see it appears you may have done this slightly wrong.
First you need to create a controller for the UIPageViewController, that is a datasource and delegate.
Please note all code has been written directly to the answer and has not been tested.
MyUIPageViewController.h
#interface
MyUIPageViewController : UIViewController <UIPageViewControllerDataSource, UIPageViewControllerDelegate>
{
NSNumber *currentIndex //Using NSNumber to handle 32bit/64bit easier.
}
#property (nonatomic, strong) UIPageViewController *pageViewController
#property (nonatomic, strong) NSArray *controllersArray //Used to help navigate between controllers
#end
MyUIPageViewController.m
#import MyUIPageViewController.h
#implementation MyUIPageViewController
- (instancetype)initWithNibName:(NSString *)nibName
bundle:(NSBundle *)nibBundle
{
if(self = [super initWithNibName:nibName bundle:nibBundle])
{
//Create ChartViewController1 (UIViewController *ChartViewController1 = [[ChartViewController1Class alloc] init];)
//Create ChartViewController2
//Create ChartViewController3
//Now we have created all 3 chartViewControllers, create our controllers Array with the controller objects.
self.controllersArray = [[NSArray alloc] initWithObjects:ChartViewController1, ChartViewController2, ChartViewController3];
//Currently setting to 0. A proper way of handling with Multi-tasking is to store the index value from before, but not dealing with that right now.
currentIndex = [NSNumber numberWithInt:0];
//Create our PageViewController. Currently set to PageCurl and all pages will go from left to right.
//These options can be changed, if so desired (Scroll Effect like iBooks Textbooks and a page change from bottom to top like a flip book.
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
//Set ourselves as the datasource and delegate to handle the pages etc.
self.pageViewController.datasource = self;
self.pageViewController.delegate = self;
//We need to set the viewControllers for the PageViewController, because this is the initial load, we will not animate the change.
[self.pageViewController setViewControllers:self.controllersArray direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:^ (BOOL finished) {
//No animation is being done so no need to worry.
}];
//Set our view to be the pagecontroller's view, so we can see it all.
self.view = self.pageViewController.view;
}
return self;
}
//DataSource Methods:
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerBeforeViewController:(UIViewController *)viewController
{
//As this method looks for the previous view controller. If our current index is 0, there is no previous VC. But using the objectAtIndex method on the array would throw a outOfRange exception
if([self.currentIndex intValue] <= 0)
{
return nil;
}
else
{
return [self.controllersArray objectAtIndex:([self.currentIndex intValue] - 1)];
}
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerAfterViewController:(UIViewController *)viewController
{
//As this method looks for the next view controller. If our current index is the maximum value the array count and be (2), there isn't a new VC to push. But using the objectAtIndex method on the array would throw a outOfRange exception
if([self.currentIndex intValue] >= self.controllersArray.count)
{
return nil;
}
else
{
return [self.controllersArray objectAtIndex:([self.currentIndex intValue] + 1)];
}
}
//Delegate Methods
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
if(transitionCompleted)
{
//We will update our currentIndex, only if the transition has happened.
switch (previousViewControllers)
{
case 0:
//Something went wrong :S
break;
case 1:
//We are either in Vertical Orientation of the first viewController is only being shown.
if([pageViewController.viewControllers contains:[self.controllersArray objectAtIndex:([currentIndex intValue]+ 1)]])
{
currentIndex = [NSNumber numberWithInt:([currentIndex intValue] + 1)];
}
else
{
if([currentIndex intValue] == 0)
{
//Saftey Net.
}
else
{
currentIndex = [NSNumber numberWithInt:([currentIndex intValue] - 1)];
}
}
break;
case 2:
//We are in horizontal Orientation.
//With 3 View Controllers the only ViewController that will be in both arrays is the ViewController at index 1. We just need to see if the pageViewControllers viewcontrollers array contains the ViewController at index 0 or index 1.
if([pageViewController.viewControllers contains:[self.controllersArray objectAtIndex:([currentIndex intValue]+ 1)]])
{
currentIndex = [NSNumber numberWithInt:([currentIndex intValue] + 1)];
}
else
{
if([currentIndex intValue] == 0)
{
//Saftey Net.
}
else
{
currentIndex = [NSNumber numberWithInt:([currentIndex intValue] - 1)];
}
}
break;
default:
//Should never reach here.
break;
}
}
}
#end
It is also handy to look at the reference documentation:
Class Reference - Apple Docs
How can I pass data from UINavigationController to The root UITableViewController?
I have implemented the ECSlidingViewController (https://github.com/edgecase/ECSlidingViewController). User selects one of the cells in the menu that correspond to different urls I want to display information from on my tableView that sitts on top of the UINavigationController. (u know the default combination that u get my dragging UINavigationController to ur storyboard). I am able to get the data from the sliding menu to my navigationController now I am trying to pass that same info on my tableview?
In my menu I have:
UINavigationController *newTopViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"NavigationTop"];
newTopViewController = [(NavigationTopViewController*)newTopViewController initWithCinema:self.myCinema];
In UINaviationController:
- (id)initWithCinema:(Cinema *)cinema {
self = [super init];
if(self) {
_myCinema = [[Cinema alloc] init];
_myCinema = cinema;
}
return self;
}
- (void) viewDidLoad {
[super viewDidLoad];
// this log works I get the info to here.
NSLog(#"url(navigation):%#", self.myCinema.cinemaURL);
//MoviesTableViewController *moviesTableViewController = [[MoviesTableViewController alloc] initWithCinema:self.myCinema];
//UITableViewController *newTopViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"MoviesTable"];
//NavigationTopViewController *newTopViewController = [[NavigationTopViewController alloc] initWithCinema:self.myCinema];
//newTopViewController = [(MoviesTableViewController *)newTopViewController initWithCinema:self.myCinema];
//[self performSegueWithIdentifier:nil sender:self.myCinema];
[self prepareForSegue:nil sender:self.myCinema.cinemaURL];
}
In my UITableView:
- (void)setCinema:(Cinema *)cinema {
// works here too
NSLog(#"Table(setCinema):%#", cinema.cinemaURL);
self.myCinema = [[Cinema alloc] init];
if(!cinema) {
cinema.cityIndex = kAstanaIndex;
cinema.name = kKeruen;
cinema.nameForText = kKeruenText;
cinema.cinemaURL = kKeruenURL;
cinema.cinemaURLTomorrow = kKeruenURLtomorrow;
}
self.myCinema = cinema;
// works here too!!!
NSLog(#"Table(myCinema):%#", self.myCinema.cinemaURL);
}
However its gone in viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
// set delegate to self
self.tableView.delegate = self;
// set loading theater's url
// does not work here: I GET NULL !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
NSLog(#"url(moviesTable):%#", self.myCinema.cinemaURL);
_model = [[MovieModel alloc] initWithURL:self.myCinema.cinemaURL];
}
None of the methods I have tried (commented in Navigation worked...) at least for me. Please give me any suggestions. Thank you in advance.
UINavigationController does not hold any data, but rather a stack of view controllers. I'd recommend you check out frameworks such as the free Sensible TableView. The framework will automatically handle detail view generation and passing data between them. Saves me tons of development time in my projects.