Xcode segue with data to set label - label

Hello guy's and girl's,
I got a question, i'm new to objective c and iphone apps. But i'm trying to make a few simple applications but i have trouble with creating a segue that also sets the label in the next view controller.
The situation is as following. i have a Tableviewcontroller with an loaded nsarray of data.
Next i have created a segue (ctrl + drag). Al works so far.
Now the viewcontroller has an label, i have namend the segue and a'm trying the following code.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ShowTitleInOtherViewController"]) {
PracticeViewController *pvc = [segue destinationViewController];
pvc.labelForDisplayData.text = #"Segue complete";
pvc.labelForDisplayData.textColor = [UIColor blueColor];
pvc.labelForDisplayData.font = [UIFont boldSystemFontOfSize:50];
}
}
i have imported the header and the viewcontroller header looks like the following:
#interface PracticeViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *labelForDisplayData;
#end
Please tell me what i am doing wrong. (there are no error's)

Recommendation
From your description (as long as you've connected the outlet in your storyboard) then this workflow should be okay. You are not showing how the segue is initialized (i.e., performSegueWithIdentifier). Please see this stack overflow question for more details (link). I've posted a few tips on manual segueing. If you've resolved this issue please update your original question. Here is another sample of calling a manual segue (link). Please advise if this issue is still open or share the problem/solution.
New Apple Tutorial on Storyboards
Hope this helps.

Make the Label property to strong instead of weak
#interface PracticeViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *labelForDisplayData;
#end

Related

allocating view controller the right way

i am trying to archiv something really simple.
I add a property for a NSScrollView in my ViewController header file called PanelController:
#property (strong) IBOutlet NSScrollView *listurls_fld;
I add the ViewController.h file to my NSObject Interface called "qhandler.h"
#import "handler.h"
#import "PanelController.h"
i have a +(void) function inside the qhandler.m ->
+ (void)do_handle:(NSDictionary *)response
{
PanelController *MyView=[[PanelController alloc] init];
NSLog(#"add moo");
[MyView.listurls_fld setStringValue:#"moo"];
}
which doesn't work...
It does neither work with setAlphaValue or whatever, i guess it's because i am allocating a new instance of PanelController, but as a matter of fact, I tried to change the main instance.
I know it's basic but i have enormous problems using IBOutlets from a viewcontroller, inside an external obj-c file.
Thanks,
john
ViewController.h
id mainDelegate;
ViewController.m
in viewDidLoad oder what function ever triggers after load:
mainDelegate=self;
so i can use [mainDelegate ...:..]; in every file..

ipad uisplitview: passing data from masterviewcontroller to a uiviewcontroller (redirected via segue)

I'm new to iOS programming so I want to make this thing from scratch to be able understand how the whole thing works. So instead of using the master detail template I did this from the ground up.
I'm having a huge roadblock in terms of passing data between the master view and the detail view. At the moment, whenever I tap on the item of the master view it would look for the first view on the detail view controller, let's call it mainswitchviewcontroller. It's the first ViewController connected via segue to the UINavigationController for the detail controller part (Please refer to image below).
This happens after login where it shows that viewcontroller, I want the user to pick an option before accessing the whole app. which will lead them to the last ViewController of the flow (refer to the image below - red circle).
Now what I'm trying to do is this:
#interface MasterListViewController : UITableViewController{
}
#property (nonatomic) int matNum;
#property (strong, nonatomic) DetailStaffMainContentViewController *detailViewController;
#end
:
:
#implementation MasterListViewController
#synthesize matNum;
:
:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
for(UIViewController *vc in self.splitViewController.viewControllers){
NSLog(#"%#)", vc.title);
}
self.detailViewController.teststring = #"gronk";
}
This is my detailViewController (the one I want to access)
#implementation DetailStaffMainContentViewController
#synthesize tableView;
#synthesize teststring;
#synthesize lblOutput;
Now on select of the row, I assign the teststring which I want to use to populate that label on the controller. That's what I did.
My questions are:
I'm getting an error. Wondering what I was doing wrong?
[MainSwitchBoardViewController setTeststring:]: unrecognized selector
sent to instance 0x7572190
Is this a recommended way of passing data? Or should I just stick with notificationcenters?
Thoughts?
EDIT
Just to give you on the flow of the app:
User logs in (if username does not exist, the floating viewcontroller will pop up and force the user to log in.
Once the user logs in, the pop up goes away and then asks the user what type of role is to be used in the current session (eg. staff or fighter).
If the user picks fighter, it pushes the user to the top VC If the user picks staff, it pushes the user to the bottom VC (collections controller)
FOR Staff: At the moment I'm pushing to the last VC with this [self perfermSegueWithIdentifier:sender:self]
Once the user gets shown the last VC (DetailsStaffView), I want this to be the main Details View where the user does it's transaction. A few more pop ups? (Or maybe another push to another VC for specific transaction needs to be added). But ultimately I don't want the user to access the first Viewcontroller (MasterSwitchBoard)
EDIT 2
This is the main switch board class that controls the first VC after login.
#interface MainSwitchBoardViewController : UIViewController{
}
#property (strong, nonatomic) IBOutlet UILabel *txtLabel;
- (IBAction)btnStaff:(id)sender;
- (IBAction)btnAdmin:(id)sender;
#end
This is the collections VC which atm automatcially pushes to the last VC. In the beginning I was using a notification on this but it seems like it's not necessary so I took it out.
#interface MatListCollectionViewController ()
#end
#implementation MatListCollectionViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self performSegueWithIdentifier:#"SeguePushToStaffDetailFromMats" sender:self];
}
And then the details staff
#interface DetailStaffMainContentViewController : UIViewController{
}
#property (strong, nonatomic) IBOutlet UITableView *tableView;
#property (nonatomic, retain) IBOutlet UILabel *lblOutput;
#property (nonatomic, retain) NSString *teststring;
#end
#implementation DetailStaffMainContentViewController
#synthesize tableView;
#synthesize teststring;
#synthesize lblOutput;
I'll tackle those in reverse order:
Is this a recommended way of passing data? Or should I just stick with notificationcenters?
You theoretically could use notification center, but I wouldn't in this case. Personally, I only use NSNotificationCenter if:
I'm doing asynchronous process which has no reasonable way of knowing the state of the view controllers (e.g. I have some background task that's doing some time consuming update of data from a server, and the user could have navigated to just about anywhere in the app by the time I'm ready to notify the view controllers that the update is done); and/or
I potentially have multiple objects that I want to notify of some event.
Neither of those conditions apply here. Certainly you could use NSNotificationCenter, but that should be unnecessary. Explicitly setting properties is generally preferable.
I'm getting an error. Wondering what I was doing wrong?
Unfortunately, it's hard to say on the basis of the evidence you've presented thus far. But there are a few things that I'm having trouble reconciling on the basis of your code and comments:
You've declared detailViewController to be a DetailStaffMainContentViewController (and that's the class for which you've synthesized the teststring accessors);
But your error message suggests that detailViewController is clearly a MainSwitchBoardViewController object (which doesn't understand the setTeststring accessor method); and
You haven't shown us how you're setting detailViewController, so it's hard to say where you've gone wrong here.
Personally, in cases like this, I'm always reticent to define properties to maintain pointers to view controllers. I'd generally be inclined to ask the UISplitViewController what's in the detail split. So, rather than having a class property/ivar for that, in my master view controller, I have a method like:
- (UIViewController *)detailViewController
{
return [[self.splitViewController.viewControllers lastObject] topViewController];
}
That's basically saying "get the last object from my split view controller's array of viewControllers (the detail split) and because I (personally) always use a navigation controller in that detail split, let's use the topViewController to get a pointer to my subclassed UIViewController that's in that detail split (embedded within the navigation controller).
Then I have my didSelectRowAtIndexPath check to see if that view controller is the one I expected. If not, I segue to it (and have prepareSegue pass the data I want to that controller).
So, for example, consider this storyboard:
Here, "A" is my default detail controller. "B" might be some random scene that I may have replaced "A" with. And "C" is my real detail view controller where I can see the details for the item I selected from the master view controller's table view. Thus, my didSelectRowAtIndexPath for the master view controller might look like:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIViewController *controller = [self detailViewController];
if (![controller isKindOfClass:[DetailCViewController class]])
{
// if I'm not already showing "C" in my detail split, then let's segue to it
[self performSegueWithIdentifier:#"GoToC" sender:self];
}
else
{
// if I'm already showing "C" in my detail split, let's just set the item of data I want to pass to it
DetailCViewController *cController = (DetailCViewController *)controller;
cController.detailItem = self.objects[indexPath.row];
}
// I have a method I call to make sure that the popover menu for the master view
// controller disappears (in case it popped up since I was in portrait mode) and
// adds the master view controller button to the navigation bar if I need it.
[self removePopoverAndAddNavigationButton];
}
In case I needed to segue to "C", I also have my `prepareSegue pass the detailItem as needed:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"GoToC"])
{
DetailCViewController *cController = (DetailCViewController *)[segue.destinationViewController topViewController];
cController.detailItem = self.objects[[[self.tableView indexPathForSelectedRow] row]];
}
}
As I said, trying to figure out why your detailViewController has the wrong type of object is hard to say, but this is how I might tackle something like this.
Maybe you should first take a look at some nice movies from the last WWDC where they describe Storyboard Segues.
In the code you provided there is nothing written about segues. Be sure to use segues either via IB or programmatically via [self performSegueWithIdentifier:]. See Apple Docs
Then you can provide additional operations in yout view controller:
[view shouldPerformSegueWithIdentifier:sender:]
[view prepareForSegue:sender:]
The first one decides whether to perform the segue or not. The second one is executed just before segue is performed. Within the secon operation you can provide information to the destinationViewController.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"showIssuesByProject"]){
if (_searchActive) {
((IssueListViewController *)segue.destinationViewController).project = [_filteredProjects projectAtIndex:[self.tableView indexPathForSelectedRow].row];
} else {
((IssueListViewController *)segue.destinationViewController).project = [_projects projectAtIndex:[self.tableView indexPathForSelectedRow].row];
}
}
if ([segue.identifier isEqualToString:#"showIssuesByFilter"]) {
((IssueListViewController *)segue.destinationViewController).filter = [_filters filterAtIndex:[self.tableView indexPathForSelectedRow].row];
}
}
Be careful: UISplitViewControll.viewControllers are only two controllers: the master and detail ones.

Error with presentViewController - no visible #interface for AppDelegate

I am making a splitview application for ipad and I need to display a different view controller for login purposes.
I call this in the didFinishLaunchingWithOptions function in Appdelegate:
LoginViewController *login = [[LoginViewController alloc] init];
[info setModalTransitionStyle: UIModalTransitionStyleCrossDissolve];
[self presentViewController:login animated:YES completion: nil];
but I get the error "No visible #interface for AppDelegate declares the selector presentViewController" on the third line.
The view controller I want to display is set to the LoginViewController class.
I have Imported all classes.
I am pretty new to programming and would really appreciate any help!
Thanks!!
What the error message says is that the class AppDelegate does not contain a method called presentViewController. Indeed, that method belongs to UIViewController class.
What you should do depends on how you created your project, whether it uses a navigation controller, a tab bar controller, or a simple view controller.
From your comment, I understand you used the Window-based template (or Empty application) to create your project. In this case, in your application:didFinishLaunching: you should have something like this:
self.login = [[LoginViewController alloc] init];
[self.window addSubview:self.login.view];
and also add to your AppDelegate.h the following declaration:
#property (nonatomic, strong) LoginViewController* login;
If this seems not to apply to your case, please, post your definition of application:didFinishLaunching:

NSArrayController, NSPopupButton proper bindings

I just started Mac programming coming over from iOS and was playing around with bindings.
I'm trying to make a simple directory popup that shows a history of recently selected directories and last element would read other... which will open the opendialog box.
I can't seem to figure out how to Bind an NSPopupButton to my Model though.
Its setup like this:
MainUIViewController, NSController, NSObject Controller all wired up in the nib
I do connect an outlet in MainUIViewController to the Directory Array Controller in the NIB
I have a class for eachDirectory, and a class for DirectoryArrayController(NSObject) I bind the NSPopupButton on view this way:
and I have the Directory Array Controller bound to the Directory Popup Array Controller thus
Here is the .h file that is connected to the Directory Popup Array Controller
#interface DirectoryPopupArrayController : NSObject
#property (weak) IBOutlet NSPopUpButton *directoryPopupButton;
#property (nonatomic) IBOutlet NSMutableArray *allDirectoryHistory;
#property (nonatomic) eachDirectory *currentlySelectedDirectory;
#end
I fill some sample directory info with the following code in the corresponding .m file
- (void)awakeFromNib {
[super awakeFromNib];
//testing sample directories
self.allDirectoryHistory = [[NSMutableArray alloc] initWithCapacity:10];
NSString *name;
eachDirectory *newDirectoryName;
for (int i = 0; i < 5; i++) {
name = [NSString stringWithFormat:#"directory %d", i];
newDirectoryName = [[eachDirectory alloc] initWithDirectoryName:name];
[self.allDirectoryHistory addObject:newDirectoryName];
}
}
and here is the code for the eachDirectory.h
#interface eachDirectory : NSObject
#property (nonatomic) NSString *directoryPath;
#property (nonatomic) NSString *directoryVisibleName;
-(id) initWithDirectoryName:(NSString *)newName;
#end
Now When I go to my code if I place the code for creation of the Array and bind the Array controller directly to the UIViewController.m file things seem to work fine.
What I want to do is handle all the array stuff in a separate class file and only get back the final directory choice to the main controller. When I bind the NSArrayController to the Object controller in the NIB as described above I get nothing showing in the popup and I don't understand why!
Any Help is greatly appreciated, Sorry for the long-winded post - just wanted to make myself clear.

Set view as delegate to viewcontroller

I'm having problem passing data and executing functions in the viewcontroller from the view. I want to access label outlets in the viewcontroller from the view (yeah I know it might be bad structure of my app).
Got delegations working on UIPopovers but how can I set the delegate of the view to viewcontroller?
For example, you have a subclass of UIView. Let's name it SubClassUIView;
In another view, you want to use the data, from SubClassUIView.
So, your SubClassUIView should be done like this:
SubClassUIView.h
#interface SubClassUIView:UIView
#property (nonatomic, retain) UILabel* someLabelYouWantToUse;
#end.
SubClassUIView.m
#implementation SubClassUIView
#synthesize someLabelYouWantToUse;
#end.
And to access someLabelYouWantToUse
SubClassUIView* scView = [SubClassUIView alloc]init];
NSLog(#"%#", scView.someLabelYouWantToUse.text);

Resources