Badge value on "More" tab - iphone

I am making an iOS app which has a tabBarController, with more than 5 tabs. Thus, first four are directly clickable and the rest come under MORE tab.
I want to show a badge on the MORE tab if there is any badge for the tabs that are hidden inside this MORE tab.
I know about how to do that from this question.
But the order of my tabs is configurable. Is there a way I can configure the MORE tab such it just puts the badgeValue if I set a value for a tab inside it?
I am thinking of this:
- (void)updateBadgeValue:(NSInteger)count {
int index = [self.tabBarController indexOfObject:self.tabBarItem];
if (index > 4) { //Inside MORE tab
[[[self.tabBarController moreTabBarController] tabBarItem] setBadgeValue:[NSString stringWithFormat:#"%d", count]];
}
//Also setting badge of self.tabbarItem so that it remains when it is brought to "hot tab items".
}
I am looking for a solution such that I dont have to do that for every tab. Also, if the tab order is changed by the user, the badgeValue should also update accordingly.
Thanks.

Try using this:
- (void)updateBadgeValue:(NSInteger)count {
int index = [self.tabBarController indexOfObject:self.tabBarItem];
if (index > 4) {
int moreTabCount = count + [[[[self.tabBarController moreTabBarController] tabBarItem] badgeValue] intValue];
[[[self.tabBarController moreTabBarController] tabBarItem] setBadgeValue:[NSString stringWithFormat:#"%d", moreTabCount]];
}
}
UPDATE: You can respond to configuration changes by using
- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed
delegate method in your UITabBarController's delegate (it should be AppDelegate). Let's do it:
- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed {
if(changed) {
int count = 0;
int i; for(i = 4; i < [viewControllers count]; i++)
count += [[[[viewControllers objectAtIndex:i] tabBarItem] badgeValue] intValue];
if(count > 0)
[[self.tabBarController moreTabBarController] tabBarItem] setBadgeValue:[NSString stringWithFormat:#"%d", count]];
}
}
I think that it will work.

Try using this
[[[[[self tabBarController] tabBar] items]
objectAtIndex:4] setBadgeValue:[NSString stringWithFormat:#"%d",yourBadgeValue];
Here ObjectAtIndex is for your Tab where 0 represents your first tab etc...

You can use for Swift 4:
let messagesCount: Int = 5
self.tabBarController?.moreNavigationController.tabBarItem.badgeValue = " \(messagesCount)"

Related

selected image wouldn't load in ego image viewer in ios 7

I am using EGOPhotoViewer to load up a bunch of images from the s3. They are shown in thumbnails first in table view, so when a user clicks 5th row of image, it loaded the image into image viewer starting at 5 of 20 . and this is working smoothly in ios 6.
but when I installed ios 7 and run my app.I got an error. it fails to load the clicked image.
when user click 5th row of image,image viewer load the very 1st image starting at 1 of 20.
i am using this much of code.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{ ......
[self showSelectedPhoto:indexPath];
......
}
//load the selected image
-(void)showSelectedPhoto:(NSIndexPath *)indexPath
{
[UserInfo sharedInfo].Path=indexPath;
NSLog(#"%#",indexPath);
NSString *passingImageName=[[self.tableDataSource objectAtIndex:indexPath.row]objectForKey:#"fileName"];
NSMutableArray *photoArray=[self getFilteredArray];
NSMutableArray *urlsArray=[[NSMutableArray alloc] init];
// [self.tableView reloadData];
for (NSString *string in photoArray) {
NSLog(#"String Values:%#",string);
NSURL *imageUrl=[self getEnlargedImageImageUrl:[self._prefix stringByAppendingString:string]];
NSLog(#"Passing url is:%#",imageUrl);
photo = [[EGOQuickPhoto alloc] initWithImageURL:imageUrl name:string];
[urlsArray addObject:photo];
}
self.source=[[EGOQuickPhotoSource alloc]initWithPhotos:urlsArray];
photoController = [[EGOPhotoViewController alloc] initWithPhotoSource:source];
[self.navigationController pushViewController:photoController animated:YES];
NSUInteger index = [photoArray indexOfObject:passingImageName];
NSLog(#"index = %lu",(unsigned long)index);
[photoController moveToPhotoAtIndex:index animated:NO];
}
so it is ios 7 ui bug or whatever?
I got the solution of this,And it working fine For my app in IOS 7.
In EGOphotoviewer
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSInteger _index = [self centerPhotoIndex];
if (_index >= [self.photoSource numberOfPhotos] || _index < 0) {
return;
}
//Change here for IOS7...add "&&_index>0" after _rotating
if (_pageIndex != _index && !_rotating && _index > 0) {
[self setBarsHidden:NO animated:YES];
_pageIndex = _index;
[self setViewState];
if (![scrollView isTracking]) {
[self layoutScrollViewSubviews];
}
}
}
In EGOphotoviewcontroller in viewwillappear method
if ([self.navigationController isToolbarHidden] && (!_popover || ([self.photoSource numberOfPhotos] > 1))) {
[self.navigationController setToolbarHidden:NO animated:YES];
}
After calling this method in ios7 _pageindex value getting zero,i don't know the actual reason for this, but i will give one idea.
just assign _pageindex value after this statement,like indexpath.row or may be tag value what youwant to assign,
Then the things are going good...
njoy...

Reduce number in text box by one for each button tap

I'm relatively new to Objective-C so this might be really simple to do: I have a text box in my application that displays an ammo count, so each time the user taps a fire button the number in the text box will go down by one (12 > 11 > 10, etc) to 0. I have tried using for and if statements, but they are not working (I may have used incorrect syntax). This is what I'm using right now, but obviously I need the
- (IBAction)fire {
[ammoField setText:#"11"];
}
- (IBAction)reload {
[ammoField setText: #"12"];
}
The simplest way would be to convert the text to a number, decrement that and the reset the text, i.e. replace the code in the fire method with:
NSInteger ammoCount = [ammoField.text integerValue];
ammoCount--;
ammoField.text = [NSString stringWithFormat:#"%d", ammoCount];
But don't do this, it will make baby Steve Jobs cry.
A better way would be to add a new variable to the class of type UIInteger that tracks the the number of bullets, i.e.:
// in interface
NSInteger _ammoCount;
...
// in implementation
- (IBAction)fire {
_ammoCount--;
if (_ammoCount <= 0) {
_ammoCount = 0;
fireButton.enabled = NO;
}
[ammoField setText: [NSString stringWithFormat:#"%d", _ammoCount]];
}
- (IBAction)reload {
_ammoCount = 12;
[ammoField setText: [NSString stringWithFormat:#"%d", _ammoCount]];
fireButton.enabled = YES;
}
Oh, and don't forget to call reload at some point early on to ensure _ammoCount and ammoField get initialised.
Set Instance Integer
int x;
set value of it
x = 12;
do change in method
- (IBAction)fire {
[ammoField setText:[NSString stringWithFormat:#"%i",x]];
x--;
}
set the value of count in viewdidload with an int variable
fire method decrease the count by 1
and reload method to return value to 12
log or use values accordingly
Try this:-
int i;
-(void)ViewDidLoad
{
i=12;
}
- (IBAction)fire
{
[ammoField setText:[NSString stringWithFormat:#"%d",i]];
i--;
}
- (IBAction)reload {
i = 12;
[ammoField setText: [NSString stringWithFormat:#"%d", i]];
}
Hope it will work for you. Thanks :)

Paged UIScrollview with lazy delayed loading

I need help with the uiscrollview implementation with the following requirements:
1) pagingEnabled = true.
2) lazy pages loading.
3) pages are loading in the background. So i need at first run loading the page X, then get the notification that the page is fully loaded and only then allow the user to scroll to it.
4) ability to change the current page.
My first attempt was to override the scrollViewDidEndDeacelerating and scrollViewDidScroll, but I had troubles with stucking on half of pages (when you stop the scroll on the half of the page and then wait for new page to add to the scroll) and empty pages (when the user scrolled too fast).
My second attempt was to override the layoutSubviews method of the UIScrollView and do all calculations there. But it seems to be very sofisticated.
So, I'd love to find any examples of similar implementations.
Now I have the code like this:
I've implemented scrollViewWillBeginDragging and scrollViewDidEndDecelerating:
- (void)scrollViewWillBeginDragging:(UIScrollView *)aScrollView
{
isScrolling = YES;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)aScrollView
{
isScrolling = NO;
// Here we load the page that was prepared when the user was scrolling
if (needDisplay > -1) {
//NSLog(#"Loading queued page %d", needDisplay);
[self loadScrollViewWithPage:needDisplay forceAddToSuperview:NO animated:YES];
needDisplay = -1;
}
// minLoadedPageIndex - index of the first loaded page.
int selectedIndex = MIN(floor((aScrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1 + minLoadedPageIndex, [photoItems count] - 1);
[self loadScrollViewWithPage:selectedIndex - 1 forceAddToSuperview:NO animated:YES];
[self loadScrollViewWithPage:selectedIndex forceAddToSuperview:NO animated:YES];
[self loadScrollViewWithPage:selectedIndex + 1 forceAddToSuperview:NO animated:YES];
}
In loadScrollViewWithPage I create the page view controller which loads the data from the server in the background. I don't add the view to the scrollview until it loads the data from the server.
- (void)loadScrollViewWithPage:(int)page forceAddToSuperview:(BOOL)value animated:(BOOL)animated
{
DetailController *controller = page >= viewControllers.count ? [NSNull null] :[viewControllers objectAtIndex:page];
if ((NSNull *)controller == [NSNull null])
{
controller = [[DetailController alloc] initWithNibName:#"DetailController" bundle:nil];
controller.delegate = self;
controller.view.hidden = NO; //this will call viewDidLoad.
if (page >= viewControllers.count) {
[viewControllers addObject:controller];
}
else {
[viewControllers replaceObjectAtIndex:page withObject:controller];
}
[controller release];
}
// add the controller's view to the scroll view
if (controller.view && controller.view.superview == nil && (controller.isLoadedOrFailed || value)) {
[self setNumberOfVisiblePages:visiblePagesCount+1];
if (page < selectedIndex) {
// We are adding the page to the left of the current page,
// so we need to adjust the content offset.
CGFloat offset = (int)scrollView.contentOffset.x % (int)scrollView.frame.size.width;
offset = scrollView.frame.size.width * (selectedIndex - minLoadedPageIndex) + offset;
[scrollView setContentOffset:CGPointMake(offset, 0.0) animated:animated];
}
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * (page - minLoadedPageIndex);
frame.origin.y = 0;
controller.view.frame = frame;
[scrollView addSubview:controller.view];
[controller viewWillAppear:NO];
}
}
Also I have a detailControllerDidFinishDownload method which is called when data for the page view controller has been loaded.
- (void)detailControllerDidFinishDownload:(DetailController *)controller
{
... //here I calculate new minLoadedPageIndex value
// reset pages frames
if (minLoadedPageIndex < oldMinPage) {
for(int i=oldMinPage;i < [viewControllers count]; i++) {
DetailController *detailsController = [viewControllers objectAtIndex:i];
if ((NSNull *)detailsController != [NSNull null]) {
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * (i - minLoadedPageIndex);
frame.origin.y = 0;
[detailsController.view setFrame:frame];
}
}
}
// load the page now or delay load until the scrolling will be finished
if (!isScrolling) {
[self loadScrollViewWithPage:[photoItems indexOfObject:controller.photoItem] forceAddToSuperview:NO animated:NO];
}
else {
needDisplay = [photoItems indexOfObject:controller.photoItem];
//NSLog(#"pageControlUsed is used!!! %d", [photoItems indexOfObject:controller.photoItem]);
}
}
The problem I have now is that sometimes the scroll stucks on the middle (or somewhere near to middle) of the pages and it won't go to the nearest page bounce until I slightly more it. My tests showed that this situation happens if I scroll out of content view frame (the scroll view have bounces on) and wait for the new page to load. In 1 of the 10 times the scroll stucks.
Thanks, Mikhail!
There are a lot of things you are requiring at the same time. I suggest you have a look at this example.
http://ykyuen.wordpress.com/2010/05/22/iphone-uiscrollview-with-paging-example/
It's a very good starting point.

Switch statement using a selectedSegmentIndex

How do to all,
This is the first time posting on the site, so i presume i have not followed all the
formats and protocols correctly.
My app has a UIView containing a list of questions, and a UISegmentedControl called "question_btn" for each question. The UISegmentedControl has 2 segments, the first for a NO answer, the 2nd for a YES answer, corresponding to each question.
Each "question_btn" individually calls -(void) processQuestions{}, but when i click on each "question_btn" only the last one is processed properly. All previous "question_btns" call the processQuestions method, but do not implement its code.
Im my problem with the UISegmentControl, or the switch statement, or both.
Any suggestions would be greatly appreciated.
The button is defined as follows
question_btn = [[[UISegmentedControl alloc] initWithFrame:CGRectMake(QUESTION_BUTTON_XPOS, questionsButton_YPos, 80, 20)] autorelease];
[question_btn insertSegmentWithTitle:#"No" atIndex:0 animated:NO];
[question_btn insertSegmentWithTitle:#"Yes" atIndex:1 animated:NO];
[question_btn setEnabled:YES forSegmentAtIndex:0];
[question_btn setEnabled:YES forSegmentAtIndex:1];
question_btn.segmentedControlStyle = UISegmentedControlStyleBar;
question_btn.tintColor = [UIColor colorWithRed:200.0/255.0 green:200.0/255.0 blue:200.0/255.0 alpha:1.0];
[question_btn addTarget:self action:#selector(processQuestions) forControlEvents:UIControlEventValueChanged];
Below is the processQuestions
- (void) processQuestions
{
//NSLog(#"QuestionsView processQuestions: Called");
//Process the questions i.e. determine whether yes or no was the answer
answersArray = [[NSMutableArray alloc] init];
int selectedIndex;
selectedIndex = [question_btn selectedSegmentIndex];
switch (selectedIndex)
{
case 0:
NSLog(#"QuestionsView processQuestions: No answered");
break;
case 1:
NSLog(#"QuestionsView processQuestions: Yes answered");
break;
}
[answersArray addObject:[NSNumber numberWithInt:selectedIndex]];
NSLog(#"QuestionsView processQuestions: answersArray contains: %#", answersArray);
}
Here is how i got the code to iterate properly and get the question_btn selected index value. It was just a matter of creating a mutable array to hold the question_btn objects,
and then set the selected index value for each button using a for loop.
The buttonsArray is set in my createView method.
buttonsArray = [[NSMutableArray alloc] init];
- (void) processQuestions
{
//NSLog(#"QuestionsView processQuestions: Called");
answersArray = [[NSMutableArray alloc] init];
int selectedIndex;
for (int i = 0; i < numQuestions; i ++)
{
question_btn = (UISegmentedControl*)[buttonsArray objectAtIndex:i];
selectedIndex = [question_btn selectedSegmentIndex];
switch (selectedIndex)
{
case 0:
NSLog(#"QuestionsView processQuestions: No answered for question: %d", i + 1);
break;
case 1:
NSLog(#"QuestionsView processQuestions: Yes answered for question: %d", i + 1);
break;
}
[answersArray addObject:[NSNumber numberWithInt:selectedIndex]];
}
NSLog(#"QuestionsView processQuestions: answersArray contains: %#", answersArray);
}
If you have a list of questions, you can use an array of Segemnted control. You may have a button, 'Get Result' so when pressed, you iterate through all the segmented controls and check there selected index (yes/no - 0/1).
right now, in your above code, processQuestions is called for each segmented control's state changing. If the default value is kept by the user, it will not add result to the answer array.

Allowing user to select a UIPickerView row by tapping

I'm trying to use a UIPicker View with a behavior somehow different of what's usually seen in iPhone code examples.
What I want to do is to allow users to scroll through the picker contents, but not to select a picker's row automatically (using the "didSelectRow" method from picker's delegate). Instead, I want to allow the user to touch the center row of the picker, which gets highlighted, and becomes the selection.
Is there any way to achieve this?
Thanks in advance.
Add a gesture recogniser to the UIPickerView which triggers a target method in your object:
myGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(pickerTapped:)];
[myPicker addGestureRecognizer:myGR];
// target method
-(void)pickerTapped:(id)sender
{
// your code
}
make a new UIControl
same position as the UIPickerView
[yourcontrol setBackGroundColor: [UIColor clearColor]];
make a method
- (IBAction) pickerControlTapped
{
[yourpicker selectRow: rand()% yourpickersize
inComponent: 0
animated: YES];
}
.3. make a connection between 1 and 2
[yourcontrol addTarget: self
action: #selector(pickerControlTapped)
forControlEvents: UIControlEventTouchUpInsied];
Building on Martin Linklater's answer to support tapping on the pickers other rows:
Has some magic numbers but works for me.
- (void) pickerTapped:(UITapGestureRecognizer*)gestureRecognizer
{
CGPoint location = [gestureRecognizer locationInView:self.pickerView];
CGFloat halfViewHeight = self.pickerView.frame.size.height / 2;
NSInteger row = -1;
if (location.y < halfViewHeight - 22
&& location.y > halfViewHeight - 66)
{
row = [self.pickerView selectedRowInComponent:0] - 1;
}
else if (location.y < halfViewHeight + 22
&& location.y > halfViewHeight - 22)
{
row = [self.pickerView selectedRowInComponent:0];
}
else if (location.y < halfViewHeight + 66
&& location.y > halfViewHeight + 22)
{
row = [self.pickerView selectedRowInComponent:0] + 1;
}
if (row >= 0 && row < [self.content count])
{
id element = [self.content objectAtIndex:row];
if (element)
{
[self.pickerView selectRow:row inComponent:0 animated:YES];
// do more stuff
}
}
}
I have a relatively simple solution to this problem that has worked well for me. Using a hidden custom button you can achieve the tap functionality without a gesture recogniser. This solution works for a picker with one component, however I'm sure it could be adapted to work with more.
Firstly add a button, either in the Interface Builder or programatically. Make it hidden and as wide as the picker then place it so that it sits exactly in the centre of the picker and also in front of it in the view hierarchy.
I'm using an IBAction like this to show my picker. However it's really up to you how you show and hide the picker.
- (IBAction)showPicker:(id)sender
{
_picker.hidden = NO;
_buttonPicker.hidden = NO;
}
All the action for choosing the picker value happens in an IBAction for the UIControlEventTouchUpInside event, something like this.
- (IBAction)selectPicker:(id)sender
{
//Hide the button so that it doesn't get in the way
_buttonPicker.hidden = YES;
//Make sure we're within range
NSInteger max = _values.count;
NSInteger row = [_picker selectedRowInComponent:0];
if(row >= 0 && row < max) {
NSString *value = [_values objectAtIndex:row];
//Set the label value and hide the picker
_label.text = value;
_picker.hidden = YES;
}
}
I've slightly modified the code for this answer from working code so apologies if it's broken at all.
There are only 2 delegates for UIPickerView.
UIPickerViewDelegate
UIPickerViewDataSource
So, we can use only 7 methods to control UIPickerView by delegate.
– pickerView:rowHeightForComponent:
– pickerView:widthForComponent:
– pickerView:titleForRow:forComponent:
– pickerView:viewForRow:forComponent:reusingView:
– pickerView:didSelectRow:inComponent:
– numberOfComponentsInPickerView:
– pickerView:numberOfRowsInComponent:
that'all.
In UITableViewDelegate case, there are more methods for UITableView for managing selections.
such as,
– tableView:willSelectRowAtIndexPath:
– tableView:didSelectRowAtIndexPath:
– tableView:willDeselectRowAtIndexPath:
– tableView:didDeselectRowAtIndexPath:
However...
In UIPickerViewDelegate case, there is only 1 method for responding to row selection.
– pickerView:didSelectRow:inComponent: