I have a app that will use multiple UICollectionViewControllers in a container view like this:
MasterViewController > (x2) Container Views > UICollectionViewController > UICollectionView > UICollectionViewCell
I've had to do this because I need the sections(each of the collection views in my case) to be scrollable vertically. Otherwise I would used a single Collection View and use the sections to my favor. This proves to be a little tricky because so far I've had to make Master Controller the data source of each of the Collection Views. Which means I have to implement if statements to check which collection view is asking for the data. Here is a sample:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"section1"]) {
self.topLeft = [segue destinationViewController];
[self setDelegate:self.topLeft]; // set topleft delegate
self.topLeft.collectionView.dataSource = self;
}
if ([[segue identifier] isEqualToString:#"section2"]) {
self.topRight = [segue destinationViewController];
self.topRight.collectionView.dataSource = self;
}
}
How can the 2 contained controllers coordinate with my master controller? Right now I don't even know why I have them. Currently I have a gesture recognizer attached to the master controller because I wanna drag and drop between Collection View Controllers. I need to constantly check which Collection View the touch is above because I want to animate items out of the way when I add one to a collection, but it seems like I have to search thru all the collection views each time the UIGestureRecognizerStateChanged is called. Is there any way I can use delegation to make everything more modular right the the master controller is doing all the work.
Thanks
Related
I'm new on Stackoverflow and I'm currently learning XCode from scratch and I'm in a process of making a Single Page Application with options.
Anyone knows how to efficiently make a simple menu with multiple selectable UIButtons that make the main ViewController display different datasets depending on the selection in XCode?
Tried different things (creating SecondViewController for example but can't figure out how to pass data from it to main ViewController).
Any help will be greatly appreciated.
Refer this:
https://www.appcoda.com/storyboards-ios-tutorial-pass-data-between-view-controller-with-segue/
How to pass prepareForSegue: an object
Simple Test from above Answer Reference:
Simply grab a reference to the target view controller in prepareForSegue: method and pass any objects you need to there. Here's an example...
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"YOUR_SEGUE_NAME_HERE"])
{
// Get reference to the destination view controller
YourViewController *vc = [segue destinationViewController];
// Pass any objects to the view controller here, like...
[vc setMyObjectHere:object];
}
}
REVISION: You can also use performSegueWithIdentifier:sender: method to activate the transition to a new view based on a selection or button press.
For instance, consider I had two view controllers. The first contains three buttons and the second needs to know which of those buttons has been pressed before the transition. You could wire the buttons up to an IBAction in your code which uses performSegueWithIdentifier: method, like this...
//When any of my buttons are pressed, push the next view
- (IBAction)buttonPressed:(id)sender
{
[self performSegueWithIdentifier:#"MySegue" sender:sender];
}
// This will get called too before the view appears
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"MySegue"]) {
// Get destination view
SecondView *vc = [segue destinationViewController];
// Get button tag number (or do whatever you need to do here, based on your object
NSInteger tagIndex = [(UIButton *)sender tag];
// Pass the information to your destination view
[vc setSelectedButton:tagIndex];
}
}
Hope this help but please go through refernces!
I have 2 view controllers - One with a collectionView displaying images, the other it's corresponding detail view - pretty basic. The problems is items in collectionView are not selectable for some reason (touch but nothing happens). Also, I am not using a nav controller to embed the collectionView VC in, prefer to use an unwind segue with custom button - will this work?
I made a connection from the collectionView Cell to the Detail VC.
In prepareForSegue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"detailSegue"]) {
LPDiaryDetailViewController *destViewController = segue.destinationViewController;
NSIndexPath *indexPath = [self.collectionView indexPathForCell:sender];
LocationImage *image = self.savedItems[indexPath.row];
destViewController.captionString = image.caption;
}
}
The cell is probably not responding to touches because you haven't set the image view's userInteractionEnabled property to YES (it's NO by default).
You can't use an unwind segue to go forward; they're for going back to a previous controller, so your preference to use an unwind segue doesn't make sense. Do you mean for the unwind segue to be used for going back from the detail VC? It's not clear where you want this custom button. You already have the segue connected from the cell, so you don't need a button to invoke the segue.
this is my problem. I can perfectly show a detailedViewController came from a table view, but i got 2 more tableview that i want to make it seem in detailed.When i gave it same variables - since every things that came same - it still doesn't go to the next view controller.I checked segue identifier aswell and i really don't want to make a new detailed controller.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showDetail"]) {
// Get destination view
detailViewController *destViewController = [segue destinationViewController];
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSInteger tagIndex = [(UIButton *)sender tag];
destViewController.recipeName =[[self.content objectAtIndex:indexPath.row] valueForKey:#"recipeName"];
destViewController.recipeDetail =[[self.content objectAtIndex:indexPath.row] valueForKey:#"recipeDetail"];
this is how i pass the data.They are exactly same with a small difference. The content of the content array.
You can go to the same view controller from multiple other controllers. You may be able to do this by simply creating the segue from the appropriate cells in each table. The way I've done it is to create a segue from each table view controller to the "detail" view controller, and then perform the segue in code when the appropriate cell is selected. Keep in mind that when creating segues in IB, there is a difference between creating them from table view cells and from the view controllers themselves.
In my app, I have 4 view controllers, (login,welcome,game view and results view). In the game view, I have two additional views (like this)[screen shot link to the views]. I am using a web api to get data, and my data is consist of items(each item has 1 image and 4 string). Item number is not constant so based on the amount of items(which I store it inside an array), I transition my views from one to another until I ran out of items.(The way I present is really similar to view transitions sample from apple. After displaying the last item, I use perform segue to go to next view.
The problem that I am trying to solve
I am trying to create an additional view/ or view controller that uses some part of the information from my items array.
my question
Why I am getting null for container views array ?(_results array is the array that has the items)
this is what I tried:
based on this question:
GameView
ContainerViewController *container = [[ContainerViewController alloc]init];
container.array = _results;
[self performSegueWithIdentifier:#"changetoResults" sender:self];
ContainerViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"items in the array - containerviewcontroller.m %#",array);
}
this is the console:
2013-11-26 19:11:29.157 GuessTheImage[3664:70b] there are 8 , of items in the current index -gameviewcontroller.m
2013-11-26 19:12:44.439 GuessTheImage[3664:70b] items in the array - containerviewcontroller.m (null)
Thank you.
Because the ViewController that you create isn't the ViewController that you go to via the segue.
If you'd like to use a segue, you can get the destination ViewController (it already exists) in a prepareForSegue method and tune it however you want (in your case - add an array).
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"changetoResults"])
{
ContainerViewController *vc = (ContainerViewController *)[segue destinationViewController];
vc.array = _results;
}
}
There are two things that you are not doing correctly:
You are setting the array on a temporary view controller different from the instance activated by your segue, and
You are logging the array too early: viewDidLoad: is called before the segue code manages to put the array into the new view controller.
To fix the first problem, remove the two lines above the "perform segue" call, and add this method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"changetoResults"]) {
ContainerViewController *container = segue.destinationViewController;
container.array = _results;
}
}
To fix the second problem, move the logging code into the viewDidAppear:. NSLog should start showing the correct number of items.
I want to create a single person lap timer xib/class and load it twice onto a single View Controller on my Story Board. Each of the two instances will be used to time and compare two persons lap times on a single ViewController.
I have laid out two Container Views side by side within the Story Board View Controller (LapCounterViewController)
I have also created an xib and class files as a single person lap timer ( LapCounterNibViewContainer)
How do I create two instances of LapCounterNibViewContainer and put it inside each of the Container Views
_vc1 = [[LapCounterNibViewController alloc] initWithNibName:#"LapCounterNibViewController" bundle:nil];
_vc1.view.frame = self.LapCounterFrame1.frame;
//_vc1.delegate = self;
[_LapCounterFrame1 addChildViewController:_vc1];
[_vc1 didMoveToParentViewController:self];
[self.view addSubview: _vc1.view];
In the storyboard, you can add two container views to the same view controller and connect them both with the same child view controller by right-click dragging and choosing embed. This created the segue like so:
Click on the segue and give it an identifier. Then, add the prepareForSegue method to your parent view controller, and set some properties for the lap timers separately if you want.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segueName isEqualToString: #"embedSegueToLapTimerOne"]) {
LapCounterNibViewController * childViewController = (LapCounterNibViewController *) [segue destinationViewController];
[childViewController setFoo:bar1];
}
if ([segueName isEqualToString: #"embedSegueToLapTimerTwo"]) {
LapCounterNibViewController * childViewController = (LapCounterNibViewController *) [segue destinationViewController];
[childViewController setFoo:bar2];
}
}