Pressing back button (backBarButtonItem) in KIF? - ios

Does KIF provide any special support for tapping back buttons or will I have to do something like this?
// in parent ViewController
self.navigationItem.backBarButtonItem.isAccessibilityElement = YES;
self.navigationItem.backBarButtonItem.accessibilityLabel = #"Back";
// in test class
[tester tapViewWithAccessibilityLabel: #"Back"]];
The latter would be a bit unfortunate, because my code currently does not have back buttons at all and self.navigationItem.backBarButtonItem is and can normally remain nil (see here): the description in the storyboard suffices so far.

By default, the back button will be labeled "Back" and accessible to VoiceOver as such as well so:
[tester tapViewWithAccessibilityLabel: #"Back"];
will work if you haven't done anything else.
So assuming I understand the structure of your view controllers (which is navigation, but with no explicit backBarButtonItem set), then what you have should work without the parent view controller changes you're worried about.

Related

iOS UIButton in programmatically instantiated subview not firing

I have a Nib in my storyboard which is not connected to anything but I'm instantiating it as a subview thusly:
-(void)LoadCameraOverlayView
{
CameraOverlayViewController *cameraVC = [self.storyboard instantiateViewControllerWithIdentifier:#"CameraOverlayNib"];
cameraVC.view.userInteractionEnabled = YES;
[self.view addSubview:cameraVC.view];
}
The UIViewController has a camera with feedback which is working fine and a button which (when I segue to the view controller also works fine.)
The button is linked to a Touch Down event and Touch Up Inside event.
When I click the button I can see it is changing visually from its default state to its focused or highlighted state however none of the code seems to be executing. If I put an NSLog in the ViewDidLoad I can see that in the console but not for the linked method. However if I segue to the view it does work.
What's going on?
I looked at other solutions but I don't think it could be that there is a view in the way or that the CGRect isn't calibrated correctly or anything since I can see the visual change when clicking the button.
This code violates Rule One of how to use view controllers:
CameraOverlayViewController *cameraVC = [self.storyboard instantiateViewControllerWithIdentifier:#"CameraOverlayNib"];
[self.view addSubview:cameraVC.view];
You cannot simply instantiate a view controller and then add its view manually to the view hierarchy like that. There are very strict rules about this; there is an elaborate "dance" that you must do in order to add a view controller's view to your interface manually, and you are not doing the dance.
The result is that your cameraVC comes into existence, is given no place in the view controller hierarchy, and vanishes in a puff of smoke. There is thus no object for your button to talk to, and so when the button is tapped, nothing happens.
My suggestion would be: use a .xib file, not a storyboard scene, for this view; and after you have loaded it and put it into the interface, use code to configure the button so that it talks to self, your current view controller.

Loading controller on top of view from storyboard (or nib if necessary)

I've seen lots of topics about this but i could not get this to work as i wanted, i'm sorry that this will look like a duplicate.
What i'm tyring to do :
Show a view from a storyboard VC (or a .xib, it's really up to what's "best") as if it was an alert. The user has to interact with it and then dismiss it.
Here is what i have :
A viewcontroller in my storyboard ; its linked to the corresponding .h and .m files and everything works fine on that side.
Note : That viewcontroller is "alone", there is no segue leading to it.
Now i'm in my active VC from my app flow, and i'm doing this :
ADFViewController *adf = [[ADFViewController alloc]initWithNibName:#"ADFView" bundle:[NSBundle mainBundle]];
adf.xxx = yyy // just setting some data that the user interacts with.
[self.view addSubview:adf.view];
(The VC has a button that does [self.view removeFromSuperview]; to dismiss itself when the user decides to do so.)
I've also tried using this :
adf = [self.storyboard instantiateViewControllerWithIdentifier:#"ADFViewController"];
Both don't work or "almost" work.
They're linked like they should, the storyboard and Nib name corresponds (i've tried both).
As a result I just get a blank screen. The view size is 300x300 so It should at least appear somewhat on my screen. But all i get is a blank screen (the view background).
When that is working, I intend to make the background transparent so it really looks like an alert but i'm not even up to that point. And maybe i'm struggling even though i'm going in the wrong direction.
Questions :
Am i doing something wrong?
Is this the right way of achieving this?
What should I do?
Thanks a lot for your time.
Getting a view to look and behave like an alert (with the transparent background, etc.) takes some work because you can't subclass UIAlertView. I would recommend using an already-built customizable UIAlertView-looking dialogue. There are a couple listed on this question:
UIAlertView addSubview in iOS7
These basically just take a view as input, so you can just pass in your view controller's view and everything else will be taken care of for you.

Custom TabBarController functionality

I'm attempting to create a custom tab bar controller with the following options:
Feed
Map
New
Camera
Search
The feed, map, camera, and search will each pull up their individual VC's, while new is supposed to be more of a functionality button. When the new tab item is pressed, the map view should be displayed, and the map should begin recording the user's location. I'm trying to use a UITabBarController to manage these views, but I cannot seem to figure out how to implement the functionality that I would like with the "New" tab. It seems as if I would need to implement a separate view controller for the "New" record and stop functionality but that doesn't seem right.
The functionality of record/stop should be similar to snapchat's big red button that takes a picture when you press it.
While I agree with Scott's comment that this is a bad UX, if you technically wanted to do it, you could subclass UITabBarController and in viewDidLoad you could add a UIButton subview to the the tab bar controller's tabBar:
[self.tabBar addSubview:yourCustomButton];
Thus, this button could have it's own action and selector to do whatever you want with.
Take a look at idevrecipes for an example.
I think you have to implement the container view controller yourself. I think you can't do that with UITabBarController.
I was going to dig up the idevrecipes example that shawnwall pointed out, but there's another possibly answer, assuming you want the New button to match the standard UITabBarButton appearance. I agree it may not be the best UI, but it's workable.
For starters, you would create a dummy view controller for the New item. I'm not saying you should duplicate the Maps controller or anything, I'm just saying create an empty view controller and stash to it (or it's location) in a property. Assuming you're creating your tab bar in application:didFinishLaunchingWithOptions:, it'd look something like this.
self.newViewController = [[UIViewController alloc] init];
self.newViewController.title = NSLocalizedString(#"New", nil);
self.newViewController.image = [UIImage imageNamed:"new.png"];
Drop that view controller at the appropriate location in the tab bar controller's viewControllers property.
Save a reference to the Maps controller the same way you saved one for the dummy New controller.
If you haven't already done do, set the delegate of your tabBarController to your app delegate. You may need to declare that your app delegate conforms to UITabBarControllerDelegate.
UITabBarDelegate gives you a few hooks for tracking changes to the tab bar. tabBarController:shouldSelectViewController: looks to be the appropriate place for us to hook in for your desired behavior.
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
if ([viewController isEqual:self.newViewController]) {
self.tabBarController.selectedViewController = self.mapViewController;
// Whatever logic you need to start the recording
return NO;
}
return YES;
}
The look of the user interaction's a little odd - the user tabs the middle item (New), but the item to the left (Map) gets selected. If you want the "tab bar triggers behavior" action, I'd go the idevrecipes route and make the button visually distinct. If you're married to the tab bar item look, though, I believe this is how you'd accomplish it.

Push View Controller not showing elements added from storyboard

Okay, so far I've two view controllers in my storyboard. One with "login" elements and other as "User's home" sort of thing. I am intending to do the following : When user clicks on login, there's a bit of processing and then it should show to user's home screen..
When I do it via storyboard, i mean = control drag "login" button to user's home view it works fine. But I cant use that as I've to process the login data. It also shows some animation meanwhile. So, I've to do this shift programmatically. I wrote following code in the login button's IBAction ::
HomeViewController *homeView = [[HomeViewController alloc] init];
[self presentViewController:homeView animated:YES completion:NULL] ;
Now, this takes user to the intended view. However, the elements in the homeview (say a label, navigation bar are not being shown. And thats what my worry is.
(In theory, I can build entire view programatically but i think thats not the proper way of doing this, is it ? I want to make use of storyboard functionality in full i.e. design maximum UI in storyboard and use them from the backend how you want them to work.)
How do I do it ?
Cheers.
PS : I intend to add few more view controllers so at the moment i didn't think of navigation controller. not sure, if i should use it.
Using storyboards you should be using:
UIViewController *homeView = [self.storyboard instantiateViewControllerWithIdentifier:#"someID"];
[self presentViewController:homeView animated:YES completion:NULL] ;
Then set the ID to the view controller in storyboard like so:
Additionally, if you wish to there is absolutely nothing wrong with designing your UI entirely in code. Personally I prefer it. It gives you much more flexibility than interface builder.
In addition to NSPostWhenIdle's suggestion of instantiateViewControllerWithIdentifier, you can also define a segue between the two view controllers (not between the button and the second controller, but between the two view controllers):
Then give the segue a unique identifier, and then have your IBAction method do a performSegueWithIdentifier. This way your storyboard will continue to visually represent the various relationships between your view controllers.

Affecting a UINavigationBar's Back Button Method (iOS)

I have a table view that pushes to a detail view controller. From the detail view controller, when I press the 'back' button, I'd like an integer value to change. How do I edit the navigation bar back button's action programatically. The back button is automatically placed in my app because I'm using a table view so I didn't actually create the button, so I don't know how to affect it's method.
To be clear, I still want the back button to go back to the original view, but simultaneously change an integer's value. Thanks!
Thanks PengOne to point me to this direction.
Add the UINavigationBarDelegate in the header file and use this in the .m file:
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item
{
//insert your back button handling logic here
// let the pop happen
return YES;
}
I've figured out an easy fix to this. I simply unchecked 'Shows Navigation Bar' in the Interface Builder for the UINavigationController that the Table View was contained in. Then I used a UINavigationBar to replicate the look (but be able to add and delete buttons as I pleased).
After that I just created IBAction's that I connected to the buttons and could control an integer value from there.
(P.S. The only problem with this is that there is no 'Back' button left pointing arrow shape in the XCode interface builder as many of you know. There are solutions around this that are pretty easily found if you search).
If you're using a UINavigationController, then UINavigationBarDelegate is the delegate class and it implements -navigationBar:shouldPopItem. You can put the action you want to trigger in that method, e.g. incrementing or decrementing a counter.
You could try implementing viewDidDisappear, which should be called as the detail view controller's view goes out of view.

Resources