So I have two search bars, a couple of buttons and a tableView below those (yes, all these) in one view. And I also have a navigation bar on top of it all with a back button.
For a particular operation, I remove all search bars, buttons and I display only one uitableviewcell in my view.
If I press edit, I want the whole view to be reloaded, not just the tableView but I want the view to have the search bars and buttons and the navigation screen.
I did [self.view reloadInputViews] in the IBAction of the edit button. Control goes here, but the view is just not reloaded. Why?
reloadInputViews is specifically used for views that are firstResponders. Probably self.view is not the first responder at that time. But why you want to do all this using "reloadInputViews", it wouldn't be easier to use: [self.view setNeedsLayout] ?
A better way to handle refreshing the state of a view is to abstract the configuration of your UIViewController's view's subviews into a custom method that you can call initially from viewDidLoad and again as an action of your UIbarButtonItem.
- (void)viewDidLoad {
//Specific, non repeated view setup
[self resetViewState];
}
- (void)resetViewState {
//Repeatable view setup
}
The reason it's worth making the distinction is because viewDidLoad is called automatically by the system after the view is lazy loaded. By design it's not a method that should be called multiple times per view. It will be called again if the view is discarded and recreated.
You can also move the layout of your UIViewController's subviews into viewWillLayoutSubviews if you need to do layout work, again this gets called by the system at various times.
I do not know how I get the answer myself right after posting it here on StackOverflow. Sorry for the trouble guys (sigh!)
I did [self viewDidLoad];
Related
I have a UITableView with some Cells.
I don't use NavigationController, so I'd like to use UIModalTransition to Switch from RootController, my TableViewcell, to my DetailView, but want to add a Navigation bar to attribute some actions, like Backbutton.
I don't want to use seguesTransition, I only used XIB File and any Storyboard.
I really don't know how to use the Modal Transition in TableView, anyone know how i can do it ?
Thanks.
have you tried
[self presentModalViewController:yourViewController animated:YES];
then you can set certain styles for transitions in it.
On the other view add a navigationbar and place a backbarbuttonitem and add an action to it to go back to your previous view.
Although why do you want to do it is unclear to me.
if you dont want a navigation controller on the first view, you can just set it to hidden.
self.navigationController.navigationBar.hidden = YES;
and then in the viewDidLoad of other view you can do the reverse i.e
self.navigationController.navigationBar.hidden = NO;
this is quite an easy way of achieving what you want with relatively less amount of code!!
I need to hide the navigation bar when the user scrolls down. Currently, I'm calling setNavigationBarHidden: YES animated:YES on scroll, but this solution isn't ideal as it makes the main view jump up as soon as the animation is called.
The Instagram app has a much better solution - the navigation bar is locked to the top of the main view, and it scrolls up as the user scrolls. Scroll down a few pixels, and only part of the nav bar gets hidden.
Any ideas on how this could be accomplished?
Check out https://github.com/andreamazz/AMScrollingNavbar.
Its very easy to use, just subclass AMScrollingNavbar in your viewController
I don't think they are using a navigation bar. I think it's custom header view for the UITableView, or at least that's what I would do since you can put any UIView there.
You can use the UITableView delegate to set those headers.
navigation bar doesn't provide this function. the best way is to use a custom view (your custom navigation bar) as a subview of the main view, then do the animations yourself, using functions like [UIView animateWithDuration ....] with translation function using something like CATransform3DTranslate
I have found exactly the way Instagram did it - check out my answer here
No pan gesture recognizers, setting bars hidden, nothing like that, just some cool engineering inside scrollViewDidScroll delegate method of the table view
I have a uitabbar with 4 buttons. The start up screen loads as it should on the applications start. 2 of the buttons views don't load on start (good). 1 is a web view the other is a navigation controller with a table view. The last view does load on application start. It is another navigation controller with a table view.
I know which ones are loading and which are not because i added nslogs to the didload function on all top level controllers.
So the overall issue is that when i start my app, then rotate it, then go into the tabbar item that has already been loaded the header in the tableview which is a webview, never got the memo that it should have rotated, and therefore resized. Once your in the view if you rotate back and forth then it works as it should. Its just the initial time.
Update 1:
The question is how do I stop the 2nd controller that is on another button of the tab bar from loading on app start.
Update 2:
I do all my init stuff in didload but I tried adding the following code, but it never shows up in the log. I am not using IB, this is all done programmatically:
- (void)loadView
{
NSLog(#"Loading feedback");
}
Update 3:
I figured out whats causing this. I do have a xib that houses my tabbarcontroller. In that tabbarcontroller i have a navigation controller, then i have a view controller (I set the class to my feedback class), then i had the navigation item and a table view. When i add the tableview it triggers the controller to load. Simply removing that will stop it form loading early. Then to fix it, i created a xib for the feedback. So I dont like having nibs that server a single purpose, in this case its to get a table view in there and have it be a grouped style. I may try to just manually add the tableview instead of having a tableview controller.
Its much easier to do in code. The tab bar controller accepts the view controllers in the array and the default tab bar controller is the one which is at the first index of the tab bar controller.
UITabBarController *tabBarController = [UITabBarController alloc] init];
tabBarController.viewControllers=[NSArray arrayWithObjects:firstViewConoller,secondViewController,nil];
[self.view addSubview : tabBarController.view];
Place all the view related task in viewDidLoad method sometimes loadView gies problem this may be because of your viewController trying to load a new view which calls itself again and again so better to add them to viewDidLoad.
The view controller for the tab that loads prematurely probably accesses the self.view property before it is needed needed.
If finding he access point is hard add a breakpoint to loadView, make a dummy overload only calling [super loadView] if needed (The view is loaded from a NIB). The breakpoints stack trace will show you where you force the load to occur.
How can I make a custom view in iOS which appears above the existing view,but smaller? It should be like UIAlertView, but taken from a .xib file. After user taps a certain button, the small view vanishes and the normal view appears.
If this is posiible, how can I do it? And.. if it's not hard for you, please, include code.
Thanks in advance!
I think what you're looking for is a modal view. Modal views make it easy to have a view take over the screen for a little while, then when they get dismissed have the background view resume where it left off without having to worry about who's on top or handling events in partially-obscured views.
Here is Apple's article describing it.
They key is to have the controller class for your view call [self presentModalViewController:popupController animated:YES]; where "popupController" is the view controller for the view you want to show up. When you're ready to make it go away, call [self dismissModalViewControllerAnimated: YES];
You can just use the addSubview: method on your UIWindow or your visible UIViewController's view to show the UIView, and you can hide/remove it later by calling removeFromSuperview on the presented UIView.
I'm looking for a way to slide the keyboard into view from the right, like what happens in the Contacts application when you edit a note.
My problem is that when I call [someTextView becomeFirstResponder] in viewWillAppear, the keyboard immediatly pops up with no animation. And when I call it in viewDidAppear, the view first slides in from the right (UINavigationController does the sliding), and then the keyboard slides in from the bottom.
Is it possible to have the keyboard slide in from the right, together with the view?
Solution
In iOS 7, calling becomeFirstResponder on _textView in viewDidLayoutSubviews works.
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
[_textView becomeFirstResponder];
}
Note: Doing it in viewWillLayoutSubviews also works.
Explanation
Read the discussion in the docs for becomeFirstResponder.
You may call this method to make a responder object such as a view the first responder. However, you should only call it on that view if it is part of a view hierarchy. If the view’s window property holds a UIWindow object, it has been installed in a view hierarchy; if it returns nil, the view is detached from any hierarchy.
When using a navigation controller to push your custom view controller onscreen, self.view.window is still nil by the time either viewDidLoad or viewWillAppear: is called. So, _textView.window is also nil in the same methods, since _textView is a subview of self.view, i.e., they're both in the same window. No matter how you present your custom view controller, self.view.window (and thus _textView.window) is also nil in initWithNibName:bundle:. self.view.window is set by the time viewDidAppear: is called, but that's too late because by that time, the navigation controller has already completed the animation of pushing the view onscreen.
self.view.window is also set by the time either viewWillLayoutSubviews or viewDidLayoutSubviews is called and these methods are called before the push animation of the navigation controller begins. So, that's why it works when you do it in either of those methods.
Unfortunately, viewWillLayoutSubviews and viewDidLayoutSubviews get called a lot more than just on the initial navigation controller push. But, navigationController:willShowViewController: and willMoveToParentViewController: get called too soon (after viewDidLoad but before self.view.window is set) and navigationController:didShowViewController: and didMoveToParentViewController: get called too late (after the push animation).
The only other way I can think of doing it is to somehow observe the window property of _textView so that you get notified when it changes, but I'm not sure how to do that since window is readonly.
All you need to do is tell the text view in question to become the first responder in the viewDidLoad method of the view controller you're pushing onto the navigation stack:
override func viewDidLoad() {
super.viewDidLoad()
someTextView.becomeFirstResponder()
}
This works in iOS 8. The keyboard slides in from the right along with the view.
In iOS 7 (or any version before) you can make a simple thing in loadView, viewDidLoad or viewWillAppear
[yourTextView performSelector:#selector(becomeFirstResponder) withObject:nil afterDelay:0.0];
In this case you will get left-to-right appearance of the keyboard aligned with the motion of pushing view controller.
For iOS 7 I've found the following solution to work the best for me:
-Import UIResponder-KeyboardCache to your project.
-Add [UIResponder cacheKeyboard:YES]; to the viewDidLoad of the view before the keyboard view. It might be better to do this immediately when the application loads or during a time convenient when you can afford it (during an HTTP request, for example). In most cases, simply in the view before is sufficient.
-Add the following to the viewDidLoad of the keyboard view.
dispatch_async(dispatch_get_main_queue(), ^{
[_textField becomeFirstResponder];
});
To explain, this will preload the keyboard view, which will remove the delay from the first call of the keyboard view. Calling becomeFirstResponder on the text field in the main queue causes it to slide in with the view instead of animating upward before the view slides in.
You could try sending the becomeFirstResponder message to the new view controller before you push it onto the stack. For example:
-(void)functionWhereYouPushTheNewViewController {
yourNewViewController *newVC = [[yourNewViewController alloc] init];
[newVC.yourTextView becomeFirstResponder];
[self.navigationController pushViewController:newVC animated:YES];
}
I have found that changing animations on things like they keyboard is pretty tough though, and if you read the Human Interface Guidelines Apple makes it pretty clear that they want certain things to act in certain ways, all the time. There are ways to change the behaviors of certain animations but they often involve undocumented API calls and are grounds for rejection from the app store. It would be a violation of HIG to have pushed views slide up from the bottom, for example.
Hope this helps.