TableView: Based on rowName setting variables - objective-c

Im gonna do a TableView-layout but depending on the chose I would like to set variables to specific numbers.
Examples:
Choosing "row1" -> Alpha = 1.00
Choosing "row2" -> Alpha = 2.00 & Beta = 3.00
and so on...
As far as I concerns tapping on a row just forward to next view, I want all my rows to be linked to the same View but with different/custom Alpha and Beta.
Tried to search but finding it hard to formulate this in xcode word.

So you are going to a new viewController, when tapping on a row? Than look for your code in
tableView: didSelectRowAtIndexPath:
Inside that code you will find smth. like that:
ViewControllerClass* viewController = [[ViewControllerClass alloc] init];
[self.navigationController pushViewController: viewController animated: YES];
[viewController release];
Just add your custom settings, before pushing:
ViewControllerClass* viewController = [[ViewControllerClass alloc] init];
if(indexPath.row == 0)
{
viewController.alpha = ...;
viewController.beta = ...;
}
else if(indexPath.row == 1)
{
viewController.alpha = ...;
viewController.beta = ...;
}
else
{
viewController.alpha = ...;
viewController.beta = ...;
}
[self.navigationController pushViewController: viewController animated: YES];
[viewController release];

Related

Initializing and passing values between ViewControllers

I have two UIViewControllers: TimerViewController and EfficiencyViewController (For simplicity's sake, we will call them TVC and EVC)
I am trying to pass certain values (2 NSString objects, 1 NSTimeInterval)from TVC to EVC when a button is pressed. EVC needs to be intialized and pop up upon pressing the button.
Overall, I have tried two methods.
1. Directly passing the values (In TVC)
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
EfficiencyViewController *efficiencyViewController = [storyboard instantiateViewControllerWithIdentifier:#"EfficiencyView"];
efficiencyViewController.category = _categoryLabel.text;
efficiencyViewController.desc = _descriptionTextField.text;
efficiencyViewController.duration = [_timer getInterval];
efficiencyViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:efficiencyViewController animated:YES completion:NULL];
Problem: When I instantiate EVC, the values I held in TVC are reset, so basically no data is passed. (I think this is because EVC actually pops up on the screen)
2. Building a custom init method
TVC
EfficiencyViewController *efficiencyViewController = [[EfficiencyViewController alloc] initWithName:_categoryLabel.text desc:_descriptionTextField.text duration:[_timer getInterval]];
[self presentViewController:efficiencyViewController animated:YES completion:NULL];
EVC initWithName method implementation
- (id)initWithName:(NSString *)category desc:(NSString *)theDesc duration:(NSTimeInterval)theDuration {
// self = [super initWithNibName:#"EfficiencyViewController" bundle:nil];
if (self != nil) {
_category = category;
_desc = theDesc;
_duration = theDuration;
}
return self;
}
Problem: The values are simply not being passed. And also in this way, EVC is missing some major components, such as a button and a text label.
If you have these in a storyboard, you should be using a storyboard segue, and in TVC's prepareForSegue(), you get the destination view controller (i.e. EVC) from the segue object, and that's where you set EVC's properties.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main"
bundle:nil]; EfficiencyViewController *efficiencyViewController =
[storyboard
instantiateViewControllerWithIdentifier:#"EfficiencyView"];
efficiencyViewController.category = _categoryLabel.text;
efficiencyViewController.desc = _descriptionTextField.text;
efficiencyViewController.duration = [_timer getInterval];
efficiencyViewController.modalTransitionStyle =
UIModalTransitionStyleCoverVertical;
Use self instead of _, see this link https://stackoverflow.com/a/30901681/4912468

Trying to pass Data from current VC to the next but first checking if the user inputs the correct info

I am trying to pass data from the current View Controller to the next View Controller using an IBAction because I also need to check if the user is using the correct User Email and ID before going to the second View Controller. I am still new to Objective-C and Xcode. I thought this would work but it doesn't. It will not pass the number 15 to the second VC. I would like to for it to be something like this. Please help me figure out a way to do this. This is actually for my Final Project that is due today. Lol
- (IBAction)signInButtonPressed:(id)sender {
DatabaseManager *data = [DatabaseManager new]; // A DB Using SQLite3
if (![self.studentEmailField.text isEqualToString:#""] && ![self.studentMDCID.text isEqualToString:#""]) {
if ([data checkStudentEmail:self.studentEmailField.text checkStudentID:self.studentMDCID.text]) {
StudentMainPageViewController *secoundVC = [StudentMainPageViewController new];
secoundVC.rowInDB = 15;
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *StudentMainPageVC = [mainStoryboard instantiateViewControllerWithIdentifier:#"StudentMainPageID"];
[self presentViewController:StudentMainPageVC animated:TRUE completion:nil];
}
}
}
Try use following solution:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"YourSegueIdentifier"])
{
DestinationViewController *dest = [segue destinationViewController];
dest.myData = self.myData;
}
}

Presenting view controllers on detached ... - sometimes

Like others coming to iOS8, I'm getting the warning:
Presenting view controllers on detached view controllers is discouraged <EditItineraryViewController: 0x7ca56e00>.
This is caused by the following code:
- (void)editActivityDetailsForIndexPath:(NSIndexPath *)indexPath {
NSPredicate *predicateForDisplay = [[NSPredicate alloc] init];
switch (indexPath.section) {
case kIncompleteActivitiesSection:
predicateForDisplay = _predIncomplete;
break;
case kCompleteActivitiesSection:
predicateForDisplay = _predComplete;
break;
default:
break;
}
NSString *theActivityName = [[NSString alloc] init];
theActivityName = [[[_activitiesArray filteredArrayUsingPredicate:predicateForDisplay] objectAtIndex:indexPath.row] activityName];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ActivityDetailViewController *activityDetailVC = [storyboard instantiateViewControllerWithIdentifier:#"ActivityDetailView"];
activityDetailVC.modalPresentationStyle = UIModalPresentationFormSheet;
activityDetailVC.delegate = self;
// send the activity to the view
activityDetailVC.theActivity = [[_activitiesArray filteredArrayUsingPredicate:predicateForDisplay] objectAtIndex:indexPath.row];
// configure the look of the view
_activityDetailsPopover = [[UIPopoverController alloc] initWithContentViewController:activityDetailVC];
_activityDetailsPopover.delegate = self;
ItineraryCell *cell = (ItineraryCell *)[self.itineraryTableView cellForRowAtIndexPath:indexPath];
activityDetailVC.contentView.backgroundColor = [UIColor whiteColor];
activityDetailVC.navigationBar.barTintColor = _colorSchemeLightColor;
activityDetailVC.navigationBar.titleTextAttributes = #{NSForegroundColorAttributeName:_colorSchemeColor};
activityDetailVC.saveButton.tintColor = _colorSchemeColor;
activityDetailVC.cancelButton.tintColor = _colorSchemeColor;
activityDetailVC.labelB.textColor = _colorSchemeColor;
activityDetailVC.labelM.textColor = _colorSchemeColor;
activityDetailVC.activityTitle.textColor = _colorSchemeColor;
activityDetailVC.activityTitle.font = [UIFont boldSystemFontOfSize:17.0];
// present the view
[_activityDetailsPopover presentPopoverFromRect:cell.cellDetailsButton.frame inView:cell.cellDetailsButton.superview permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
This is an iPad app and in this case, the popover is being presented in such a way as to have its little pointer pointing at an "i" icon that sits on a tableview cell in a tableview.
This works in three other places in my app without causing the warning at all. But for some reason, with this implementation, it's causing the warning. The weird thing is, this was the first place in my app I used this means of presenting the popover from a tableview cell and the other instances are just copies of this code!
Any ideas what I can look at to figure out where the hierarchy is buggered up? Is it related to how the tableview cell is being generated and then this popover presented on top of it, or does it have to do strictly with the popover itself? Or could it have to do with the tableview. I don't even know where to start to look.
Thanks so much!
I worked around this problem by presenting the popover from the view controller that presents the tableView (in my case a collection view). The problem arises when you present from a cell.
I'm assuming any cell is considered a "detached view controller" so presenting from them will give you this error and will not receive rotation events, which in turn will not use the popoverPresentationController:willRepositionPopoverToRect:inView: callback.

ipad objective c using removeFromSuperview to remove UICollectionViewController throws an error

So I'm customizing this control I found since I think it works very well except with this issue of mine:
http://www.cocoacontrols.com/controls/fsverticaltabbarcontroller
I wanted to load a UICOllectionViewCOntroller instead of a regular ViewController whenever an item is tapped on the sidebar. So I did this modification when selecting an item:
- (void)setSelectedIndex:(NSUInteger)selectedIndex
{
NSLog(#"selected Index is %#", [NSNumber numberWithInt:selectedIndex]);
NSLog(#"_selected Index is %#", [NSNumber numberWithInt:_selectedIndex]);
NSLog(#"vc counts is %i", [self.viewControllers count]);
if (selectedIndex != _selectedIndex && selectedIndex < [self.viewControllers count])
{
// add new view controller to hierarchy
UIViewController *selectedViewController = [self getSelectedVCWithSelectedIndex:selectedIndex];
[self addChildViewController:selectedViewController];
selectedViewController.view.frame = CGRectMake(self.tabBarWidth,
0,
self.view.bounds.size.width-self.tabBarWidth,
self.view.bounds.size.height);
selectedViewController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
[self.view addSubview:selectedViewController.view];
// remove previously selected view controller (if any)
if (_selectedIndex != NSNotFound)
{
UIViewController *previousViewController = [self.viewControllers objectAtIndex:_selectedIndex];
NSLog(#"ERROR HERE: remove previous: previousVC = %#", previousViewController);
[previousViewController.view removeFromSuperview];
[previousViewController removeFromParentViewController];
}
// set new selected index
_selectedIndex = selectedIndex;
// update tab bar
if (selectedIndex < [self.tabBar.items count])
{
self.tabBar.selectedItem = [self.tabBar.items objectAtIndex:selectedIndex];
}
// inform delegate
if ([self.delegate respondsToSelector:#selector(tabBarController:didSelectViewController:)])
{
[self.delegate tabBarController:self didSelectViewController:selectedViewController];
}
}
}
So what I did is since it already handles the index number of the items on teh sidebar, I just made sure it instantiates the type of controller it needs to load using this line, I have 3 regular VC and 1 collection VC:
UIViewController *previousViewController = [self.viewControllers objectAtIndex:_selectedIndex];
This is how it looks like:
-(UIViewController *)getSelectedVCWithSelectedIndex:(NSUInteger)selectedIndex{
UIViewController *selectedVC = [[UIViewController alloc]init];
// do a switch case on this.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
// need to instantiate each and every custom uinav
switch(selectedIndex){
case 1:
selectedVC = [storyboard instantiateViewControllerWithIdentifier:#"UINavAdminCategoryIndexViewControllerID"];
break;
case 2:
selectedVC = [storyboard instantiateViewControllerWithIdentifier:#"UINavAdminParticipantIndexViewControllerID"];
break;
case 3:
selectedVC = [storyboard instantiateViewControllerWithIdentifier:#"UINavAdminTablesIndexCollectionViewControllerID"];
break;
case 4:
selectedVC = [self.viewControllers objectAtIndex:selectedIndex];
break;
default:
break;
}
return selectedVC;
}
Now everything would load smoothly, but whenever I would go to the Collection VC tab and then move away from it by going to another tab it would throw this error:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'UICollectionView must be
initialized with a non-nil layout parameter'
The application bombs on this part when I remove it from the superview:
[previousViewController.view removeFromSuperview];
Was wondering why it would instantiate the UIView again when all I'm doing is removing it from the stack (is that the right term?)
EDIT: Added some more codes
So I finally figured it out and hopefully someone else can find this useful. When generating a UiCollectionView you need to initiate the Layout for some reason. Idk why, I will try to find out. But this is what led me to the solution:
http://www.rqna.net/qna/ikvmhu-uicollectionview-must-be-initialized-with-a-non-nil-layout-parameter.html
Before when I instantiated the CollectionViewController on the main ViewController before the FSVerticalTabbar is called I just used the class connected to the ViewController on the storyboard eg. AdminMainController, AdminEventsCollectionController, etc.
I basically just added the Layout and used that for the UICollectionViewController when being initiated. It now removes the VC without any errors.
UICollectionViewFlowLayout *aFlowLayout = [[UICollectionViewFlowLayout alloc] init];
[aFlowLayout setItemSize:CGSizeMake(200, 140)];
[aFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
myCollectionViewController = [[MyCollectionViewController alloc]initWithCollectionViewLayout:flowLayout];

Releasing "referential" variables in method scope

In objective-c (cocoa touch) I have a series of UIViewControllers that I am switching between.
- (void)switchViews:(id)sender
{
UIButton *button = (UIButton *)sender;
UIViewController *nextViewController;
int tag = button.tag;
switch (tag)
{
// -- has already been created
case kFinancialButton:
nextViewController = financials;
break;
case kSocialButton:
if (social == nil)
{
SocialViewController *socialViewController = [[SocialViewController alloc] initWithNibName:#"SocialViewController" bundle:nil];
social = socialViewController;
[socialViewController release];
}
nextViewController = social;
break;
case kTicketingButton:
if (ticketing == nil)
{
TicketingViewController *ticketingViewController = [[TicketingViewController alloc] initWithNibName:#"TicketingViewController" bundle:nil];
ticketing = ticketingViewController;
[ticketingViewController release];
}
nextViewController = ticketing;
break;
}
///////
------> // -- [button/nextViewController release]????
///////
[self setActiveButton:button];
}
As you can see, I'm assigning one of the view controllers to "nextViewController". What I'm wondering is if I need to release this "local" variable or if it's ok to leave alone since it's just pointing to one of my view controllers (which I release in dealloc). I don't think "tag" needs to be released since it's a "primitive", correct? How about button? I don't quite understand what should and shouldn't be released explicitly so perhaps I'm being overcautious. Thanks in advance.
In general you only have to release a variable that you've retain'd init'd or copy'd.
Edit:
After reading your code a little bit more, it seems like you'd have other issues with bad values. The below code makes a little more sense to me. This assumes that financials, social, and ticketing are all #synthesized ivars.
- (void)switchViews:(id)sender
{
UIButton *button = (UIButton *)sender;
UIViewController *nextViewController;
int tag = button.tag;
switch (tag)
{
// -- has already been created
case kFinancialButton:
nextViewController = self.financials;
break;
case kSocialButton:
if (!social) {
self.social = [[[SocialViewController alloc] initWithNibName:#"SocialViewController" bundle:nil] autorelease];
}
nextViewController = self.social;
break;
case kTicketingButton:
if (!ticketing) {
self.ticketing = [[[TicketingViewController alloc] initWithNibName:#"TicketingViewController" bundle:nil] autorelease];
}
nextViewController = self.ticketing;
break;
}
// Do something with nextViewController I'd assume
[self setActiveButton:button];
}