Send object to UIViewController from UITabBarController - ios

I have an object that is sent from my main VC to my MasterTabViewController(UITabBarController) in the viewDidLoad I NSLog the object and it shows the object, good. Now I need that object to go to the first tab UIViewController. I tried multiple times and cannot get it to go. I am new so forgive my ignorance,
I send the object from my main vc to my MasterTabViewController via segue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showLogin"])
{
MasterTabViewController *preview = segue.destinationViewController;
preview.communityTapped = self.tempCommunity;
}
}
^This works fine!^ self.tempCommunity is an instance community object.
MasterTabViewController.h
- (void)viewDidLoad
{
[super viewDidLoad];
FirstTabViewController *firstvc;
firstvc.communityTapped = self.communityTapped;
NSLog(#"%# !!!!!!!!! ",self.communityTapped.commDescription);
// Do any additional setup after loading the view.
}
FirstTabViewController.h
#property (nonatomic, strong) IBOutlet UILabel *descriptionLabel;
#property (nonatomic, strong) Community *communityTapped;
FirstTabViewController.m
- (void)viewDidLoad
{
self.descriptionLabel.text = self.communityTapped.commDescription;
[super viewDidLoad];
// Do any additional setup after loading the view.
}
If anyone could help that would be greatly appreciated as I have tried and failed many times.

You can't set up IBOutlets to a tab bar controllers view controllers (and I see from your project that you never hooked them up). In your viewDidLoad for the tab bar controller, you can get a reference to any of its view controllers with the viewControllers property. So do something like this:
- (void)viewDidLoad
{
[super viewDidLoad];
self.firstvc = self.viewControllers[0];
self.firstvc.communityTapped = self.communityTapped;
NSLog(#"%# !!!!!!!!! ",self.communityTapped.commDescription);
}

I think the problem is in the viewDidLoad of your MasterTabViewController.h. You're creating the variable firstvc, but you're not setting the value to anything. So when you set the value of communityTapped in the next line, you're trying to set the value of communityTapped on nothing.
Option 1
If you've set up the tab in interface builder, you need to create an IBOutlet in your MasterTabViewController.h and connect it to your view controller. Something like the following:
#property (strong, nonatomic) IBOutlet FirstTabViewController *firstvc;
Then to set the value of the communityTapped, property, you would use something like this:
self.firstvc.communityTapped = self.communityTapped
Option 2
The other option would be to create the tab pragmatically, and add it to the view. I'm not sure quite what your setup is, but I imagine it would be something like this:
FirstTabViewController *firstvc = [[FirstTabViewController alloc] init];
firstvc.communityTapped = self.communityTapped;
NSArray *viewControllers = [[NSArray alloc] initWithObjects:firstvc, nil];
[self.navigationController.tabBarController setViewControllers:viewControllers animated:NO];

Related

Self shows "0 objects" in debugger

I am an iOS noob.
I am having a problem similar to this:
"self" object for UIViewcontroller has #"0 objects" in debug window in xcode
Re-starting xcode does not solve the problem.
I can see the self object in the view controller after a segue from my main view controller. I have a UITableViewController inside that view controller, with a separate class for delagete/data source for the table. Once i get into this tableviewcontroller code, the self object shows "0 objects" in the debugger. I believe that I am initializing the table view incorrectly to cause this problem somehow, but not quite sure how.
Thanks for the help. My code is below.
#implementation ConnectTableController
#synthesize perpArray;
#synthesize nameArray;
+ (ConnectTableController *)connectTableController
{
return [[ConnectTableController alloc] init];
}
- (void)viewDidLoad {
[super viewDidLoad];
perpArray = [[NSMutableArray alloc] init];
nameArray = [[NSMutableArray alloc] init];
}
....
#interface ConnectTableController : UITableViewController <UITableViewDelegate, UITableViewDataSource> {
UITableView *tableView;
NSMutableArray* perpArray;
NSMutableArray* nameArray;
}
+ (ConnectTableController*) connectTableController;
#property (nonatomic, strong) NSMutableArray *perpArray;
#property (nonatomic, strong) NSMutableArray *nameArray;
...
// Parent view controller code
#implementation ConnectVC
- (void)viewDidLoad {
[super viewDidLoad];
// Set the controller delegate/dataSource for the Table
connectTableController = [[ConnectTableController alloc] init];
connectTable.dataSource = connectTableController;
connectTable.delegate = connectTableController;
[self addChildViewController:connectTableController];
}
...
#interface ConnectVC : UIViewController{
IBOutlet UIButton *CONNECT;
ConnectTableController *connectTableController;
IBOutlet UITableView *connectTable;
}
The following applies to UITableViewControllers as well, make sure you are accessing the views properly
"Self" for a viewController doesn't contain the views, you have to check "self.view.subViews", "Self.view.subViews" contains the views for the viewController, not just "self" alone.
for example, if Self is a UIViewController then the following will crash your app with the corresponding error:
for(UIView * a in self)
{
NSLog(#"%#", a.description);
}
error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIViewController countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x7f854176fbf0'
It crashes because "self" of uiviewController doesn't contain the views
BUT if you try this, then you will have something to work with:
for (UIView *s in self.view.subviews) {
NSLog(#"%#", s);
}
this will log to console all the views in the UIViewController, thereby allowing you to access the views
Also, it looks like you may be trying to access the views of "connectTableController". To access this controller's views then here's how it works:
connectTableController.view.subViews.
UITableViewController * aaa = [UITableViewController new];
aaa.tableView;
aaa.view;
aaa.view.subviews;
So, this means you are going to access the following:
connectTableController.tableView
connectTableController.view.subViews
and then from there, you can do this:
connectTableController.tableView.subViews
.. that is of course if the subviews you are looking for are subviews of the UITableViewController's tableView
In addition, I think the way you are doing the placement of a UITableViewController is OKAY, but probably not the best choice, only because it gets a little complicated and it's not as easy as adding it as a child like that in order to make this work. You should be using something like this:
tester2 = [UITableViewController new];
[self addChildViewController:tester2];
[self.view addSubview:tester2.view];
[tester2 didMoveToParentViewController:self];
then of course you should combine this method when/if you want to remove the child view controller
- (void)hideContentController:(UIViewController*) content
{
[content willMoveToParentViewController:nil];
[content.view removeFromSuperview];
[content removeFromParentViewController];
}
This will hopefully give you a start, so also try this:
- (void)viewDidLoad {
[super viewDidLoad];
// Set the controller delegate/dataSource for the Table
connectTableController = [[ConnectTableController alloc] init];
connectTable.dataSource = connectTableController;
connectTable.delegate = connectTableController;
[self addChildViewController:connectTableController];
[self.view addSubview:connectTableController.view];
[connectTableController didMoveToParentViewController:self];
}
Also, I don't know that you need to do anything with delegation declaration since the child view controller is basically it's own little world within a world. Try it with and without these lines:
connectTable.dataSource = connectTableController;
connectTable.delegate = connectTableController;
What I mean, is possibly declare these in the UITableViewController instance or make sure you are adding the "connectTable to the the UITableViewController, something like this:
cconnectTableController.tableView = connectTable;
or
[cconnectTableController setTableView:connectTable];
then you can try this
connectTable.dataSource = cconnectTableController;
etc, etc.
Try this for loop and list the results
for (id s in self.view.subviews) {
NSLog(#"%#", s);
}

Moving to and fro modal view inside TabBarController

hi i am working on an app and all was going good till now.... i am stuck at this point..
here is my storyboard snapshot..
in the DemoTableViewController when i clock on "filters" button .. Brands TableViewController is opened modally .
after user select multiple rows in Brands TableViewController ,, he then clicks on done button and view controller is dismissed by this code:
-(IBAction)DonePressed:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
I am storing the user selections in NSMutableSet and it is to be Used in DemoTableViewController so that i can reload the table rows according to the selection but i dont know how to send NSMutableSet to DemoTableViewController and then reload the table according to selection..
what is the right way to dismiss modal view and reload the parent DemoTableViewController
i know i am not doing it correctly but can anyone help me in doing it...
here is some code ---
DemoTVC.h
#import <UIKit/UIKit.h>
#import "MyModelClass.h"
#import "brandsTableViewController.h"
#interface demoTableViewController : UITableViewController<UITableViewDataSource,UITableViewDelegate,MyModelProtocol,FilterProtocol>
#property (strong, nonatomic) IBOutlet UITableView *demoTable;
- (IBAction)FilterPressed:(id)sender;
#end
DemoTVC.m--
the method which performs segue--
- (IBAction)FilterPressed:(id)sender {
[self performSegueWithIdentifier:#"FilterPressed" sender:self];
}
the delegate method which is called to get the values from BrandsTVC--
-(void)GetTheSet:(NSMutableSet *)MySet{
[self dismissViewControllerAnimated:YES completion:nil];
}
viewdidLoad--
- (void)viewDidLoad
{
[super viewDidLoad];
productArray = [[NSMutableArray alloc] init];
homeModel = [[MyModelClass alloc] init];
// Set this view controller object as the delegate for the home model object
homeModel.delegate = self;
// Call the download items method of the home model object
[homeModel downloadItemswithurl:#"url is written here"];
}
BrandsTVC.h---
#import <UIKit/UIKit.h>
#import "MyModelClass.h"
#protocol FilterProtocol <NSObject>
-(void)GetTheSet:(NSMutableSet *) MySet;
#end
#interface brandsTableViewController : UITableViewController<UITableViewDataSource,UITableViewDelegate,MyModelProtocol>
#property (strong, nonatomic) IBOutlet UITableView *RetailerList;
#property (strong,nonatomic) NSMutableSet *selectStates;
#property (nonatomic, weak) id<FilterProtocol> delegate;
- (IBAction) DonePressed:(id)sender;
#end
BrandsTVC.m---
#interface brandsTableViewController ()
{
MyModelClass *myModelClass;
NSMutableArray *BrandsArray;
brandsTableViewController *Delegate;
}
#end
viewDidLoad----
- (void)viewDidLoad
{
[super viewDidLoad];
BrandsArray = [[NSMutableArray alloc] init];
self.selectStates=[NSMutableSet new];
myModelClass = [[MyModelClass alloc] init];
// Set this view controller object as the delegate for the home model object
myModelClass.delegate = self;
// Call the download items method of the home model object
[myModelClass downloadItemswithurl:#"url to get json"];
self.tableView.allowsMultipleSelection = YES;
}
Done Button is called ---
- (IBAction)DonePressed:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
id<FilterProtocol> strongDelegate = self.delegate;
if ([strongDelegate respondsToSelector:#selector(GetTheSet:)]) {
[strongDelegate GetTheSet:self.selectStates];
}
}
#end
You can keep those elements in NSUserDefaults, and whenever DemoTableViewController appears, you send [tableView reloadData]. Do this in the viewDidAppear: method.
You can also use Core Data, but there are a lot of details to explain how to do that.
After a lot of trial and error i come to know that in BrandsTVC--
- (IBAction)DonePressed:(id)sender {
NSLog(#"done pressed %#",self.delegate);
[delegate GetTheSet:self.selectStates];
}
self.delegate is giving me NULL.
delegate is not setup and i cant figure out how to do that.. someone help me..
this answer solved my problem :D
custom viewcontroller delegate not working

Calling Story Board data - Objective C

I have an NSMutableArray that I am trying to access from one of my ViewControllers to the other.
Here is what I am doing:
a.h:
#import "b.h"
.....
#property(nonatomic,strong) b *viewControllers;
a.m:
- (void)viewDidLoad
{
[super viewDidLoad];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil];
_viewControllers = [storyboard instantiateViewControllerWithIdentifier:#"createChallengeInfo"];
.....code....
}
....code....
-(IBAction)sendVideo:(id) sender
{
NSLog(#"%#",self.viewControllers.selectedCells);
}
Now when logging this I encounter an error, EXC_BAD_ACCESS (code=1,address =0x13765350).
Here is my other ViewController.
b.h:
...code....
#property (strong, nonatomic) NSMutableArray *selectedCells; <-- this is the array I want to access
...code...
b.m:
#import "a.h"
...import...
#interface b ()
#end
#implementation b
- (void)viewDidLoad
{
[super viewDidLoad];
/* INITIATE VARIABLE */
_selectedCells = [[NSMutableArray alloc] init];
....code....
}
...code...
So my issue is accessing, selectedCells. But firstly why am I getting a EXC_BAD_ACCESS? And secondly before I get the error It lays out the ViewController and shows the variable selectedCells as nil.
Suggestions, thoughts?
If "b" is embedded in a container view of "a", then it is already instantiated when "a" gets instantiated. Therefore, when you use instantiateViewControllerWithIdentifier:, you are creating a new instance, NOT the one you have on screen. Your viewDidLoad should look like this instead,
- (void)viewDidLoad
{
[super viewDidLoad];
_viewControllers = self.childViewControllers[0];
.....code....
}
Another way to get a reference to the embedded view controller is in prepareForSegue, which will be called right after your "a" controller is instantiated. Your "b" controller will be segue.destinationViewController.

Modifying UIButton's alpha property from another class

I'm trying to change the alpha of an UIButton from another class. The function that is called in set the alpha property of my UIButton is actually called because I've put a NSLog there and I can see how it works. I'd be thankful if you could give me any suggestion.
Here's my current code.
ViewController.h
- (void) setAlphaToButton;
#property (strong, nonatomic) IBOutlet UIButton *myButton;
ViewController.m
#synthesize myButton;
- (void) setAlphaToButton {
myButton.alpha = 0.5;
NSLog(#"Alpha set");
}
ImageViewSubclass.m
- (void) tapDetected:(UITapGestureRecognizer *)tapRecognizer {
ViewController *VC = [[ViewController alloc] init];
[VC setAlphaToButton];
}
And when the image view is pressed, in my console I get: Alpha set. And the button doesn't change.
In your code, an instance of ViewController is alloced and inited, and the method setAlphaToButton is called on it. Then the view controller is released because you have no object retaining it. That's why you don't see any effect; the ViewController instance you call the method on never appears on screen.
It's not clear how your code is supposed to work; do you have an instance of ViewController in existence when tapDetected is called? If this is the case, and this is the ViewController whose button you want to alter the alpha of, then you need to have a reference to that instance of ViewController and call setAlphaToButton on it.
Your view is not loaded at the moment you trying to set alpha! You need to call this method after your viewDidLoad fired. You can force it by calling view, but it's kind of hackand not recommended!
MyViewController *vc = [MyViewController new];
vc.view; // this string will force view loading
[vc setAlphaToButton];
Add a property of uiviewcontroller class in imageviewsubclass as
ImageViewSubclass.h
#propery (nonatomic, retain) uiviewController *parent;
ImageViewSubclass.m
#synthesize parent;
And initialize it with "self" in view controller class when initalize object of imageviewsubclass and add on the view like
ImageViewsubclass *oneObj = [ImageViewsubClass alloc] init];
oneOBj.parent = self;
do the same for all objects of ImageviewsubClass objects.
and in
- (void) tapDetected:(UITapGestureRecognizer *)tapRecognizer {
[parent setAlphaToButton];
}

ios custom delegate setup

I am trying to make a custom protocol that i hope somebody might help with.
I have a mainViewController (mainVC) that has a label. That label needs to be updated with a string when i press a button in edwwVC.
I am using ARC and storyboard.
The problem is when i press the Done Button on the edwwVC, the "done" method is called BUT the delegate method is not called in mainVC.
Whereas, if i call the done method VIA the mainVC, then the done method is called AND the delegate method. So I can see the connection is there, I just do not understand why the delegate method is not called when i press the done button in the edwwVC.
I imagine it has something to do with the init of the edwwVC. Because it is already initiated by storyboard, so it looks to me as if I am initializing it again the in the viewDidLoad method of the mainVC. But that is how far i got :)
Thanks in advance!
edwwVC.h
#import <UIKit/UIKit.h>
#import "IIViewDeckController.h"
#class EDWWViewController;
#protocol EDWWViewControllerDelegate <NSObject>;
#optional
- (void)edwwVCDidFinish:(EDWWViewController *)edwwVC;
#end
#interface EDWWViewController : UIViewController <IIViewDeckControllerDelegate> {
__weak id<EDWWViewControllerDelegate> delegate;
NSMutableArray *edwwPoints;
}
#property (weak) id<EDWWViewControllerDelegate> delegate;
#property (weak, nonatomic) IBOutlet UITableView *theTableView;
#property (strong, nonatomic) NSString *testString;
- (IBAction)done:(id)sender;
- (IBAction)add:(id)sender;
#end
edwwVC.m:
#pragma mark - delegate method
- (IBAction)done:(id)sender {
testString = #"This is the test string!";
[delegate edwwVCDidFinish:self];
[self.viewDeckController closeRightViewAnimated:YES];
NSLog(#"Done pressed");
}
MainVC.m:
- (void)viewDidLoad
{
[super viewDidLoad];
edwwViewController = [[EDWWViewController alloc] init];
edwwViewController.delegate = self;
}
- (void)edwwVCDidFinish:(EDWWViewController *)edwwVC {
edwwLabel.text= edwwVC.testString;
NSLog(#"delegate method called");
}
Remove the line ...
__weak id<EDWWViewControllerDelegate> delegate;
From the .h and change the line...
[delegate edwwVCDidFinish:self];
to...
[self.delegate edwwVCDidFinish:self];
In the .m.
That should sort it.
The way you have it set up the ivar delegate is not the same as the property delegate (which is actually an ivar called _delegate) (thanks #Joris Kluivers, just adding for clarity). They are pointing to different things.
If you add a breakpoint where you are calling the delegate method I think you'll find that delegate is nil. Whereas _delegate (or self.delegate) is not nil.
::EDIT::
Ahh... just spotted the second bit too.
If you are setting up the edwwvc in storyboard then you should be alloc initing it too.
If you are segue-ing to the edwwvc then you should intercept the segue in mainVC.m like this...
- (void)prepareForSegue: //blah the rest of the name...
{
if ([segue.identifier isEqualToString:#"the name of your segue"])
{
EDWWViewController *controller = segue.destinationViewController;
controller.delegate = self;
}
}
This will take the controller that you are pushing to from the storyboard and set the delegate to it.
:: ANOTHER EDIT ::
If EDWWVC is inside a containerViewController then you can do this inside viewDidLoad in MainVC.m...
- (void)viewDidLoad
{
// other stuff...
for (UIViewController *controller in self.childViewControllers) {
if ([controller isKindOfClass:[EDWWViewController class]]) {
EDWWViewController *edwwvc = (EDWWViewController*)controller;
eddwvc.delegate = self;
}
}
}
You may find this code has to go in viewDidAppear or something but I think viewDidLoad shouldd work just fine.
You may actually be able to set the delegate property directly by using the storyboard to (but I'm not 100% certain on this).
The answer was in the containerVC of both controllers.
Where i initialized the view controllers: the viewDidLoad of the containerVC m file:
- (void)viewDidLoad
{
[super viewDidLoad];
mainVC = (MainViewController *)[self.storyboard instantiateViewControllerWithIdentifier:#"MainVC"];
edwwVC = (EDWWViewController *)[self.storyboard instantiateViewControllerWithIdentifier:#"EDWWVC"];
//THIS LINE WAS MISSING
edwwVC.delegate = mainVC;
self.centerController = mainVC;
self.rightController = edwwVC;
}
BUT guys thanks for the help! :) Appreciate it got me in the right direction! :) THANKS! :)

Resources