iOS PopOver - only from bar button item or round rect? - objective-c

Im building an iPad app which has a tableview embeded within a UIview (odd, i know). In the UITableview there is data loaded in via a PLIST. I want to allow a user to "select" a row and it would show a "popover" (uiview) containing a textfield allowing them to edit that field.
However, looking through the code i see there are only two ways to fire the function:
presentPopoverFromBarButtonItem
presentPopoverFromRect
IS this true, can you only fire that function from either a round rect or a bar button item? I have a feeling i can be done, however searching has not turned up any answers.

Yes you can only present a popover from a bar button item or from a rect in a view.
From the official doc:
Presenting and Dismissing the Popover
– presentPopoverFromRect:inView:permittedArrowDirections:animated:
– presentPopoverFromBarButtonItem:permittedArrowDirections:animated:
– dismissPopoverAnimated:

Those are the only two ways to present a subclass of UIPopoverController. It is not clear in your question as to why "presentPopoverFromRect" wouldn't work.
I understand that "presentPopoverFromBarButtonItem" is a bit limiting but "presentPopoverFromRect" lets you do whatever you want. It allows you to position a popover relative to a view where the "rect" provides a way to offset the popover relative to the view's frame.
Try:
CGRect popoverRectFromCell = CGRectMake(tappedCell.frame.size.width / 2, tappedCell.frame.size.height / 2, 1, 1);
[cellPopover presentPopoverFromRect:popoverRectFromCell
inView:tappedCell
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
Of course you can tweak the "popoverRectFromCell" to achieve desired results.
However, I am not sure this is really a use-case for a UIPopoverController. Might be easier to just make a custom view and use that for text input when the user taps a cell.

Related

iOS7 - content overlapping during push segue from table view

Apologies if this has been asked before. I can't find any reference to this particular problem though.
I have an app which is basically a table view nested within a navigation controller. Each item from the table segues to a fresh view (via a generic push transition), containing some content within a scrollview. I have set this all up using storyboard for ease of layout.
When you click an item in the table, the intention is for the table to slide off the screen to the left and be replaced by the content view. This works fine in iOS 6, but since testing the app on iOS 7 I've noticed the functionality is different.
In iOS 7 the content view slides into frame as normal, but the table view only slides a little way to the left - still visible behind my new content. It disappears very suddenly after half a second or so, but the effect is very jarring as it creates a momentary overlap of two views.
This is only a problem because my content views have transparent backgrounds, but this is important to maintain for the effect I want. So just to be clear, my content view slides in over the top of the menu, which subsequently disappears. Looks very odd.
Any help on this would be much appreciated. I'd be curious to know the reason for this change and if there's a way I can fix it. Preferably by making the menu slide all the way offscreen again.
Thanks!
I had the same problem.
Try to add into target ViewController (that shows up after push)
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.backgroundColor = [UIColor redColor];
}
If all is ok you can change background to something like that
self.tableView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"GreenBkg.png"]];
ps. tableView needs to be defined as #property in your .h filw

How Can I Change UIImages in a ScrollView based on a User's Input

Okay gang, I'm scratching my head on how to accomplish this one so I wanted to put it out to the world at large.
Essentially what a client wants is a way to toggle PART of a view based on whether the user selects a "Yes" or "No" option. My question is how would I go about accomplishing that?
Allow me to provide some more details. Within this specific app resides a form (a form with custom text fields, picker views, switches, sliders and other UI elements) that have all been laid out in a Storyboard, then programmed to function. About 3/4 of the way down this form, the user will be greeted with a "Yes" or "No" option and a button for each. The trick is that each view needs to have its own UI elements (text fields, sliders and buttons) appear ONLY when one of the options is selected and only BELOW the "Yes" or "No" option (all the elements above it need to remain, stay in the same place and hold the information the user enters).
An example : If the user hits the "Yes" button, below it 3 lines of text followed by a UIButton and Text Field would appear. Underneath this, other navigation buttons which navigate to other ViewControllers would appear. However, if the user hits the "No" button , all of those items I mentioned a moment ago would need to disappear, and instead a different set of text fields, labels, buttons and background image would need to appear. The navigation buttons will also need to link to other ViewControllers, different from the buttons in the "Yes" option. At this point I suggested to the client that a Navigation controller rooted at the bottom of the screen would be a good idea, but they are vehemently opposed to this and instead want the navigation options to be "dynamic" (or change according to which option is pressed, "Yes" or "No").
I have thought to attempt this programatically by simply using each button to load in a different image, this works just fine. The hitch then becomes twofold;
1) When I attempt to load the other UI elements that I get no way to lay them out in a storyboard and thus they appear in sporadic locations and
2) All this needs to be contained within a scroll view, which ALSO needs to change its size depending on how much space is needed below the yes and no option. Naturally the "Yes" section is 3 times smaller than the "No" section.
So, any ideas on how to make all this happen? I should mention at this point that the client also does not wish to simply navigate to a different ViewController, they very much want all this to occur on the same screen. I wish I had some code to share but we are still in the "design" aspect of this project and as such, very little code has been written. Any advice will be much appreciated as I've never been greeted with this type of build request before.
Create a UINavigationController object and set your view(say yourViewController) where your Yes and No buttons exist as a root view controller as below
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:yourViewController];
Now when user press YES/NO button on yourViewController view than you can programmatically create all controls text field and buttons and set frame according to your view. like
UITextField *txtField = [[UITextField alloc] initWithFrame:CGRectMake(enter frame accordinglly)];
[self.view addSubview:txtField];
same you can add more controls like buttons or any other controls.
after that when user press any the button(on which you want another view to display) you can push other view in the navController as below
[navController pushViewController:otherViewController animated:YES];
you need to keep track of navController in your yourViewController
when you want to go back just pop view from navController
[navController popViewControllerAnimated:YES];
PS: please be watchful for memory deallocation as well.

Pull to reveal hidden navBar-like menu in iOS? as seen in GetPocket App

I've been driving myself mad over this one. It might be one of those things where I need to take a step back and figure out the simplest way to implement this. Can't find anything on this either. I google-fu'd the heck out of this one.
In the Pocket App when you pull down a menu reveals itself just like the searchBar does. In this instance the faux bar when you pull it past its halfway point if you release it shows springs into place. If it is release before the halfway point the bar will snap back and hide. As shown here
In my case I've been trying to replicate this with no luck. In my case I have a UITextView inside of a UIViewController view. I think I have it all wrong.
I can get it to work with a UIScrollView hidden by initiating with it offscreen and then when I press a button the UIScrollView reveals itself. The problem is that this method covers everything so I'll have to resize and relayout a bunch of views. Is this in a UITableView possibly? I want it to be a pull action though and just want to put some TextStrings/Labels in this bar.
Thank you in advance.
Feels like you need a UIScrollView (or UITableView) and to put the menu you want to reveal at the top (in the table view header, for example) and then get the delegate callbacks for scrolling.
UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
You might also need to watch for some of the dragging delegate callbacks
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
You can initially hide the menu by setting the content offset to the height of the menu, then catch the delegate callbacks for scrolling and, if the scrolling has reached beyond half the size of the menu set the content offset with animation.
- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated
If I understand your goal correctly you don't need the scroll view.
What I would do is have an simple UIView containing all the stuff you need and place it outside of the visible area. This will be your pull-down view. Then add an UIPanGestureRecognizer to the view in your UIViewController and use it to track the movement of your finger and update the frame of the pull-down view accordingly. Then in this update method you simply check if the position has passed some threshold and if so you let the pull-down view snap to its final position (using animations of course).
If you are unfamiliar with the UIPanGestureRecognizer there is a really good tutorial here:
http://www.raywenderlich.com/6567/uigesturerecognizer-tutorial-in-ios-5-pinches-pans-and-more

Getting around Subclassing UIView and Using Pictures in Storyboard

I'm trying to write my first iPhone app, and I'm running into a sort of design struggle. What I want to do is have a grid of icons and when you touch one, all the icons above and to the left will "activate" and all the ones below and to the right will "deactivate." If an icon is activated it shows one picture, and if it's not activated it shows another.
The problem I have is that I want to assign a gesture recognizer to each one of these individual icons, and when that icon is tapped, it needs to call a function that updates my grid of icons. But in order to properly update, the function needs to pass as arguments the location of the image in the grid and there's no way to call a function with arguments as part of a gesture recognizer.
So really all I need to do is extend UIImageView to hold two extra integers and the grid it's contained in, and then I could have the following code:
imageView.userInteractionEnabled = YES;
UITapGestureRecognizer *tapgr = [[UITapGestureRecognizer alloc] initWithTarget:
self action:#selector(handleTap)];
[imageView addGestureRecognizer:tapgr];
:
:
- (void)handleTap
{
[self.grid updateTableFromRow:self.row andCol:self.col
}
So I suppose this is one way of doing it, but I'm told that I'm not supposed to extend classes in Objective-C, that I should build them from the ground up. In this case, I would just make a custom view with all the properties and/or instance variables I need and I would just fill this custom view with the UIImageView.
This is mostly fine, except when it comes to building my Storyboard. I put all the code that manages and creates this table of icons (programmatically) in another custom view, GridOfIconsView. So on the Storyboard I drag out a custom view and set to be a GridOfIconsView, but then I just see a big white rectangle, and I really want to be able to visualize my app in Storyboard. I know that I can drag out actual image files that I use for the icons onto Storyboard and set them to be a custom view, but then how does that work? Is that image just a background to the custom view? Would I be able to change it programmatically? So if the activated image was a green square, but the deactivated was a red one and I initially dragged out red squares to the Storyboard, would I have access to that red square image?
And a more concerning issue is that I want to manage all these icons in a data structure, either as a 2d array (id icons[][]) or a NS(Mutable?)Array of NS(Mutable?)Arrays. Either way, how could I initialize the data structure to contain links to all these? The grid will be probably 8x8 or 10x10, and there's no way I'm going to have 64-100 #propertys connecting these icons. I'm thinking the only way to sensible organize this is programmatically, but then still, how can I visualize it in Storyboard?
First, it's completely fine to extend classes in Objective-C, and it's done all the time. UIView, UIViewController, UIComponent, etc., were all designed specifically to be subclassed and extended.
However, there are two ways you can do this that are much simpler than extending the class. First, you can have your grid as you already do, where each view has a gesture recognizer attached that calls back to a method on the view controller. Then, you can set a tag on each view (or even just use the view's frame for identification), and read that from the callback method (the gesture recognizer is passed back to the callback method). For example, let's say you had a grid of 4x4 views and you simply numbered them starting in the top-left, advancing each column to the right and then each row, from 0 to 11, you could easily identify the view as such:
// The system automatically passes the gesture recognizer as the only parameter
- (void)handleTap:(UIGestureRecognizer)gestureRecognizer
{
NSInteger viewNumber = [[gestureRecognizer view] tag];
// do something with this view
}
The other way you can do it is to have a single gesture recognizer on the parent view, and then in your -handleTap: callback, you'd query the position of the tap in the view. If the position is within the frame of any of your views, you'd know which one and what to do with it. If not, you could ignore it. This solution requires slightly more math, but also requires far less maintenance and far fewer gesture recognizer that need to be wired up. I would recommend this solution over tagging your views.

Width of Modal Sheet on iPad

I am presenting an instance of UINavigationController modally with the modalPresentationStyle set to UIModalPresentationFormSheet. Inside the UINavigationController is an UITableViewController. For a delete button in the table view, I have to know the width of the sheet. Is there any way to access this?
I tried [self.view bounds], however this returns the with of the screen. I think that's because the view is not visible at the time a call this, however I don't know where else I should call it.
You can directly measure and store a magic value for the form sheet width (not pretty, I know, but it works) the value that I have been using is 540.
If you really want to get it programatically. You'll have to make sure that the view has been resized and prepped for presentation before taking the bounds value from the view. I believe this happens somewhere between viewWillAppear and viewDidAppear, although I can't remember exactly.
If all you want to do is ensure a button is aligned to the right, try using the autoresizingMask property of the button. I believe you'll only need to use UIViewAutoresizingFlexibleLeftMargin.
You can do "last minute" view setup and adjustments in viewDidLoad -- all the nib outlets have been initialized by that time.