I'm having troubles using the storyboard.
I properly connected a button (inside a custom uiviewcell) to a scene (ProfileVC) through push segue (whose identifier is pic2profile).
Besides in the table view controller (HomeVC) that manages the cells I implemented the method prepareForSegue:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"pic2profile"]){
ProfileVC *profile = (ProfileVC *)segue.destinationViewController;
NSLog(#"%#", [segue identifier]);
Tweet *tweet = [tweets objectAtIndex:0];
profile.user = tweet.user;
}
}
As explained in the documentation, once called segue.destinationViewController at the end of prepareForSegue should be displayed the view controller at the end of the segue (ProfileVC in this case).
What happen is that I get (no errors!) a black screen and the method viewDidLoad in ProfileVC is not called though the object "profile" is not null.
Inside the storyboard the ProfileVC scene is linked to its view controller (ProfileVC) and is also set up a Storyboard ID.
I already tried this but it didn't work.
Are you performing a segue to a view controller using the code you have, but have a navigation controller in between? If so you have to use a different way, specifying the navigation controller in between.
If you don't need the navigation controller you can delete it and connect the cell to the view controller and keep the code you have. Otherwise you have to change it.
Related
I have created a plunker that communicates between two different controller in nested views using factory. Below is the url of plunker.
https://plnkr.co/edit/fWA2Xugjbkf3QvHKfTa0?p=preview .
Here is the factory.
routerApp.factory("widgetService",function($state){
var callbackFunctions=[];
var counter=0;
var addWidget=function(name){
callbackFunctions[0](name);
}
var addCallback=function(callback){
if (callbackFunctions.length===0) {
callbackFunctions.push(callback);
}
}
return{
addCallback: addCallback,
addWidget: addWidget
}
})
Scenario 1:
1. Click on "List" menu under the home page.
2. Click on "verify" button. notice the change in highlighted area with yellow. Text changes from "Chandan" to "singh1".
3. Click again on verify button. Text changes from "singh1" to "singh2". So i am able to communicate between two controller in this.
Scenario 2:
1. Repeat the scenario 1 till step 2.
2. Click on "PARAGRAPH" menu under home page.
3. Click on "List" menu under home page. Click verify button. The text wont change. It will remain "chandan".
Communication is not working as we change the state.
Also i have observed that the model is changing but same is not getting reflected in view. Moreover if we bind the view to rootscope, view is getting updated.
Please clarify.
When you switch between list and paragraph states, your list controller is destroyed (and recreated next time you go to list). So when it is recreated it gets a new scope.
The callbackFunction that is registered in your service, refers to the changeMyName() function on the old controller scope, so whenever you call addWidget() in your service, you're actually calling the callback in your old scope.
To make this work as expected (at least in your sample code here), you would have to change your service to allow changing the old callback in the addCallback()-function. Something like this:
var addCallback=function(callback){
callbackFunctions[0] = callback;
}
I need to load a specific JavaScript function after one of the tabs in the tabbar finishes loading (after it is clicked for the first time). I don't really understand how to set up an event listener with the onsen-ui tabbar (ons-tabbar), and the docs were not very clear.
Basically, what I am trying to do, is create a few graphs on one of the pages. This page is loaded up when a ons-tab is selected and the partial loads. However, I need the JavaScript that creates the graphs to only load after the page is loaded (the JavaScript looks for the elements to position the graph in the partial, hence my problem right now is that the JS is loading first and not finding the html elements in the partial because they have't been loaded yet). How do I create an event listener to detect when one of the tabs are selected to run a specific code of JavaScript?
To be a little bit more clear, I am using the persistent attribute on this specific tab, so essentially I only need this event listener to run the JS code once, when the tab is first opened. However, I don't understand how to get the once event listener to work...
For the reference: http://onsen.io/reference/ons-tabbar.html#methods-summary
There are three tabbar methods related to events: on, once and off.
That means the way to use them is myTabbar.on(...), for example. You can see in that link their parameters as well. Also, right below there are the three tabbar events. In this case I think you want to use postchange, right?
In your HTML you create a tabbar and assign it to a variable with var attribute, as I am sure you already know:
<ons-tabbar var="myTabbar">
<ons-tab page="tab0.html" label="Tab0" active="true"></ons-tab>
<ons-tab page="tab1.html" label="Tab1"></ons-tab>
<ons-tab page="tab2.html" label="Tab2"></ons-tab>
</ons-tabbar>
Now, you have to wait until the app is initialised and Onsen UI is loaded in order to set the event listeners, and you can use ons.ready() for that.
Going back to the tabbar events method, since you only need to trigger the functionality with a specific tab you need to filter the tabs inside the listener. Therefore, if you use myTabbar.once('postchange', ...) the listener itself will be triggered only once regardless the filter you set inside, so perhaps it will be triggered with a different tab and then deleted for the tab you want. You cannot use it in this case.
Instead of that, you can set a listener with myTabbar.on('postchange', ...) that triggers always, then filter the tabs inside and remove the listener only when you want with myTabbar.off('postchange'). Something like this:
ons.ready(function() {
myTabbar.on('postchange', function(event) {
// Only with the tab we want, we can use the index or the name
if (event.index === 2) {
console.log('postchange and do stuff with the tab');
console.log(event.tabItem);
// Delete this listener so it's only triggered the first time
myTabbar.off('postchange');
}
});
Working here: http://codepen.io/frankdiox/pen/QbYEaq
In case you have other listener over postchange, you can use the second parameter of myTabbar.off(...) to remove the exact listener you want and not the others.
Hope it helps!
I am using the XPages Mobile Controls with an Object data source (Java Class which is NOT a managed bean) tied to View scope on a second app page. I have resetContent on the second page set to true. So I would have assumed the Object Data Source would be destroyed and recreated every time I transitioned to the second page.
When I transition to the second page the first time, the createObject() method is invoked as expected. If I transition to the second page using a button AND set forceFullRefresh to true the createObject() method is invoked. If, however I have a Rounded List Item with a moveTo specified for the second page the createObject() method does not get invoked. Instead the object remains set to the last value it was using when that application page was last accessed.
Is there a way to force the createObject() method to be invoked every time I transition to the page?
Another way is to call the refresh method of the datasource in SSJS.
Assumning you have only one datasource on the page, you can access the ObjectDataSource from the view:
var ods:com.ibm.xsp.extlib.model.ObjectDataSource = view.getData().get(0);
ods.refresh()
This executes the createObject method binding and reinstantiate the datasource.
The solution turned out to be to move the object data source from view scope to request scope. This is possible because I do not have the need for any partial refreshes on that page until the details are ready to be submitted.
I need a good explanation how can I handle the UINavigationControllers and the UITabBarControllers on iOS6.1 with StoryBoards.
When I load my app (1st ViewController) I need if (FB login = success) it jumps with segues to the 2nd ViewController automatically. Here I think I can't use a UINavigationController like root, apple's HIG don't like it.
I need a UITabBarController that connects to 3 UICollectionViewControllers (one tab for each one). I have to put the UITabBarController like root? If yes, how can I handle the others Viewontrollers between them? Like this:
I need a custom BarButtonItem (like the "Delete All" that you can see on the image 2) on each CollectionViewController, I need to use a UINavigationController for each one?
Let's assume you are happy to use unwind segues (if not there are many ways to do without).
1 When I load my app (1st ViewController) I need if (FB login = success) it jumps with segues to the 2nd ViewController automatically. Here I think I can't use a UINavigationController like root, apple's HIG don't like it.
You 1st VC (lets call it the loginVC)..
- should NOT be contained in the Navigation Controller.
- should be set as the application's initialViewController
Your 2nd VC (lets call it your startVC)
- SHOULD be contained in the Navigation Controller
- in that Navigation Controller's Identity Inspector, assign a storyboardID: #"InitialNavController"
In your App Delegate, let's have a loggedIn BOOL property:
#property (nonatomic, assign) BOOL loggedIn;
Now, in your LogInViewController...
In viewDidAppear check to see if we are already logged in, if so, navigate immediately to your startVC:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if ([(AppDelegate*)[[UIApplication sharedApplication] delegate] loggedIn]) {
UINavigationController* navController =
[[self storyboard] instantiateViewControllerWithIdentifier:#"InitialNavController"];
[self presentViewController:navController
animated:NO
completion:nil];
}
}
It's important that this is placed in viewDidAppear, not (for example) in viewDidLoad - the segue won't work unless the initial view is properly initialised and onscreen.
Make an unwind Segue (and declare it in loginVC's #interface) … loginVC will be the destination VC if users log out.
- (IBAction)unwindOnLogout:(UIStoryboardSegue *)segue
{
[(AppDelegate*)[[UIApplication sharedApplication] delegate] setLoggedIn:NO];
}
(corrected - removed this line:
[[self presentedViewController] dismissViewControllerAnimated:YES
completion:nil];
we don't need to dismiss as the segue has already done that behind the scenes. This is redundant and logs an error message)
In other viewControllers, whereever appropriate you can make a 'logout' button. CTRL-drag from that button to the 'exit' symbol at the bottom of the ViewController in the storyboard, and you will be able to select this segue as the unwind segue.
2 I need a UITabBarController that connects to 3 UICollectionViewControllers (one tab for each one). I have to put the UITabBarController like root? If yes, how can I handle the others Viewontrollers between them? Like this:
I think you are trying to work out how the tabBarController relates to the NavigationController in the previous viewController (startVC). The answer is, it shouldn't - you really don't want to embed the Tab Bar VC in the previous Nav Controller as it will create weird situations for the Tab Bar's child viewControllers.
The navigation from startVC to the tabBarVC should be via a modal segue, NOT a push segue.
You can make another unwind Segue in startVC to facilitate return from your tabBarController's viewControllers:
- (IBAction)unwindToInitialNavFromModal:(UIStoryboardSegue *)segue {
}
(corrected - removed this line:
[[self presentedViewController] dismissViewControllerAnimated:YES completion:nil];
this method doesn't need any content to perform the dismissing)
3 I need a custom BarButtonItem (like the "Delete All" that you can see on the image 2) on each CollectionViewController, I need to use a UINavigationController for each one?
You won't get a Navigation bar in your tabBarVC by default.
You can provide one in two ways
- embed each child viewController in it's own Navigation Controller;
- manually drag a navigation bar to EACH child viewController's scene.
Either is fine, it really just depends whether you will want navigation to other ViewControllers.
You can then add a barButtonItem on the left or right to connect up to the initialVC's unwind segue (CTRL-drag to the 'exit' symbol).
I'm using storyboarding and have a UITableView containing events, which when clicked load another view with more details. I also have an 'add' button on that list which goes to the same page but doesn't prepopulate the information and changes the banner button.
I do it by setting the detail item with the following method, and then in the configureView method I just check if the detail item exists.
- (void)setDetailItem:(id)newDetailItem {
if (self.detailItem != newDetailItem) {
_detailItem = newDetailItem;
[self configureView];
} }
This works ok, but I thought there might be a better way to distinguish between methods, eg by getting the segue identifier in this new view controller and using that. Is there an easy way to do this or do I need to pass this information through as part of the prepareForSegue method?
Using prepareForSegue: seems right. In general, it's a bad idea for methods to care about the conditions under which they're being called if it's not explicit in their parameters.