swift: delegate is nil after segue - delegates

I have a center ViewCentroller with a button to another ViewController. In the first file I also declare a protocol. This delegate works just fine in the first ViewCentroller, but after the segue has been performed, the delegate is nil. How can I solve this?

First way is to use prepareForSegue and declare in it all your delegate methods.
Second way is to use NSNotificationCenter and with this transfer your delegate so this works with pushToViewController

Related

Unable to change delegate on NSSplitView

I have a storyboard that contains a main window (with a corresponding MainWindowController class), and a main view (an NSSplitViewController, with corresponding MainViewController class). For certain functionality I am attempting to set the delegate of the NSSplitView contained in the view to the MainWindowController class.
Without any IB linkage, the NSSplitView delegate is already set to the MainViewController at application launch. I am able to get a reference to the MainWindowController, but when I attempt to set the delegate to the window controller (which does implement NSSplitViewDelegate), I am getting the following:
*** Assertion failure in -[NSSplitView setDelegate:], /Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-1404.34/AppKit.subproj/NSSplitView.m:600
This also happens if I attempt to set the delegate to nil.
Does anyone know why this might be so, whether there are restrictions on setting delegates, and if there is a way to use IB to set the delegate of an item in a view to another Controller?
Thanks.
I don't have a reference for this but I'm pretty sure the split view and the split view controller aren't meant to be separated. Fortunately, NSSplitViewController mirrors the delegate methods, giving you a chance to intervene. There should therefore be no reason to change the split view's delegate.

viewDidLoad called before an IBAction?

in my Xcode project I have a button, that does two things.
First: call an IBAction
Second: go to another view (segue)
In the action linked to the button I set a variable to YES (global var), but in the viewDidLoad method in the linked view, its still NO. Its YES in viewDidAppear though. I wonder why the action is not called first. Can I change that? I'd prefer to use the viewDidLoad method, since it seems to load quicker.
You can use the prepareForSegue method to pass whatever data to the destination view before the segue assigned to the button is performed. This data will be available in the destination view viewDidLoad

UIButton tapped getting [SecondPage performSelector:withObject:withObject:]: message sent to deallocated instance

By using of Xcode 5 and auto-reference counting is enabled.
In a Non NavigationController based application i have take a UIButton and the IBAction and IBOutlet are properly defined and connected. But before the IBAction for TouchUpInside event called by Button taped the App gives "[SecondPage performSelector:withObject:withObject:]: message sent to deallocated instance 0x6cb7970".
SecondPage is view-controller on which this UIButton exists.
Basically I want to open a new view-controller's view on this UIButton tapped and i will do this by Custom Segue
Hmm strange it sounds like ARC is autoreleasing your secondView controller before your selector is being called.
Try defining your secondView as a property of the first (if you're adding it as a subview) with a property type of strong.
That's all I can recommend without seeing your code.
I was getting same problem and solved with what Matt Rees suggested.
Just declair your secondViewController in firstViewController.h and made its instance there. Like,
secondViewController *secondView;
I was getting same problem and solved with what error thrown.
With more details, I was reallocating caller object (SecondPage in this case) on logout/login, but re-using some other viewcontrollers, so re-used viewcontroller have previous instance of caller object that I reallocated.
Well, solved it now!

Call IBAction in different class

My document based application has a window with a tableview. The tableview has a datasource which points to a class of type NSObject (called HopBill) which includes a NSMutableArray (aHopBill) and the needed tableview methods. So far so good.
For adding rows to the tableview I've added a sheet which is controlled from a NSWindowController (called HopBillSheetController). When pressing the OK button in the sheet. I actually need to do two IBActions (which is not possible): Add the row to the array of the tableview and close the sheet. I can connect the OK button in the sheet to the NSWindowController (to close the sheet) or connect it to the NSObject (to add the row to the array). But I want both :-)
Is it possible to call the IBAction in the NSWindowController from the NSObject? Or is there another way to do this?
I'm quite a beginner to Cocao and Objective-C, so please be gentle :-)
If your sheet is a nib/xib with an NSPanel, the call to close it is simply [panel close]; Assuming your window controller has a property for the panel, you can put the close code at the end of its row-adding IBAction. Or you could have the IBAction itself call another method if you prefer.
If your panel is running modal, you might need to stopModal too. (That's what's needed if everything stays frozen after the panel closes; otherwise never mind.)
Assuming hopBill, your data source, is a property of the window controller, any IBAction you write in the window controller also has access to hopBill; it can do everything you need.
So add a single IBAction to the window controller and connect the panel's OK button to it. That ought to work.
As for calling an IBAction from somewhere other than a control in a nib, yes, you can do that. Use a reference to the control as the sender arg, or nil if the IBAction doesn't use the sender arg.
You could also create your panel programmatically, or use NSAlert. But it sounds like your current setup is simpler -- and therefore better.
Take a look at this h file for an app controller: Apple's ClockControl example
The NSMutableArray *appointments property is the actual data source that will be used by the NSTableViewDataSource protocol methods. The IBAction "addAppointment" can access "appointments" directly: [self.appointments addObject:whatever atIndex:whatever];
The ClockControl example could be modified to use HopBill. You would import its declarations up top: #import "HopBill.h" And then instead of the "appointments" property, it would declare HopBill *hopBill; And "addApointment" would access HopBill's mutable array (aHopBill) like this: [self.hopBill.aHopBill addObject:whatever atIndex:whatever];
Why you can’t send messages to hopBill:
First, because although you declare it, you never initialize it. You have:
HopBill *hopBill;
[self.hopBill.aHopBill addObject: bHopAdditionAtInit];
It should be:
HopBill *hopBill = [[HopBill alloc] init];
[hopBill.aHopBill addObject: bHopAdditionAtInit]; // “self” won’t work here
Second, you’re declaring it inside an IBAction method, (doneHopBillSheet:), so it’s a local variable, accessible only within that method. If HopBill is holding your table’s data source cache, it should be a property of the controller which implements the NSTableViewDataSourceProtocol methods.
In your HopBill interface, you declare the aHopBill array to be a property, and you initialize it in HopBill’s init method (you should also release it in HopBill’s dealloc method). You need to do the same thing for the controller — it should have an instance of HopBill as a property, and that instance should be initialized in the controller’s init method.
If you want HopBillController to manage the tableview, its interface declaration should look like this:
#interface HopBillSheetController : NSWindowController <NSTableViewDelegate, NSTableViewDataSource> {
…
}
And, then, of course, you have to implement the relevant NSTableViewDelegate and NSTableViewDataSource methods.
Also, the controller must have an IBOutlet property for the tableview itself, and in the controller’s awakeFromNib method, it has to assign itself as delegate and datasource:
[self.tableview setDelegate:self];
[self.tableview setDataSource:self];
(The self-dot syntax assumes you’ve set up #property and #synthesize code for tableview.)
The IBAction method that adds items to your table must be in that controller class, or in a class that has a property which is an instance of the controller class. Then the IBAction method will have access to the aHopBill array and can add the new object to the array, after which it will call [tableView reloadData], which will in turn trigger the tableview protocol methods and update the table.
Now, that means that the xib containing the tableview has to have the controller as its file’s owner. Since you’re using NSDocument, I suspect that, instead, you would put the tableview outlet in the NSDocument subclass. And you would give that doc subclass a property which is an instance of the controller. The IBAction methods would also be in the doc subclass, and so they would have access to the controller and its HopBill property. Or maybe you would simply make the doc subclass the controller, rather than using the separate HopBillSheetController class. I’m not sure about the NSDocument stuff. But, remember, the IBAction method can itself call other methods, as long as it has access to instances of the classes in which those methods are declared.
Apple has an example using both the tableview delegate and datasource protocol methods. Go to this link and download the sample code: tableview example
It looks like a nice app. Good luck.

Execute IBAction on a custom event

How would I be able to run an IBAction based on another event? For example I could use a piece of code to run an IBAction.
What I'm trying to do is have two different buttons run one or more IBActions.
You can hook multiple buttons up to the same IBAction, so you could do it that way.
But IBActions are just methods. For example, if you have some action doSomething:, you can just call it on an object:
[obj doSomething:nil];
An IBAction is just a hint for the Interface Builder. It's actually another way of saying void.
#define IBAction void
So there is nothing special about it.
In Interface Builder, you can connect touch event for different buttons to the same IBAction.
You can also call IBAction methods from another IBAction method. Use the sender argument to identify the source of the event.
For example,
-(IBAction)buttonTapped:(id)sender {
UIButton *btn = (UIButton *)sender;
NSLog(#"tapped: %#", btn.titleLabel.text);
[self anotherIBAction:sender];
}

Resources