performSegueWithIdentifier not executed - swift

I'm trying to use a segue, here's my code:
if let status_code = response.response?.statusCode {
if status_code == 200 {
// register is ok
// cancel all warnings
self.usernameField.hidden = false;
self.usernameFieldError.hidden = true;
self.usernameShortError.hidden = true;
self.usernameTakenError.hidden = true;
self.performSegueWithIdentifier("registerToFeed", sender: self);
}
}
(I've cut the code for length)
So here's the problem: the segue is simply not executed. I've put a breakpoint on it to see what happens, and the execution flow just passes on it, and do nothing, quite frustrating.
I've read that performSegueWithIdentifier needs to be called on the main thread, so I called NSThread.isMainThread()just before my segue call, and it returned me true.
I also double checked if the identifier name was the same as the one i'm calling and that's the case.
I tried to do
dispatch_async(dispatch_get_main_queue()){
self.performSegueWithIdentifier("registerToFeed", sender: self)
}
as I've seen in another SO thread, but still not working, nothing gets executed.
So I don't know why this simple line doesn't get executed. Thank you for your help.
EDIT: so here's the full RegisterViewController.swift file:
http://pastebin.com/dpBBXhe8
The problem is that the program crashes at line 190 because the performSegue is not executed.

Is this code in the viewDidLoad method? If so, you must move it to viewDidAppear.

Where was the viewController (self) in this code originated from. The
performSegueWithIdentifier(_:sender:) requires the calling viewController to be loaded from a storyboard (storyboard must not be nil).
Also, have you tried implementing preapreForSegue to see if this is called when you call performSegue? The default implementation of 'prepareForSegue' does nothing.

Related

Modify IBOutlet property from outside of viewDidLoad - Xcode Storyboards

I have a separate class which when called upon updates the ToolTip (a text property) for an NSButton in a pistonViewController via its IBOutlet.
However, whenever I try to perform the action, I get the error
"Unexpectedly found nil while implicitly unwrapping an Optional value"
since pistonViewController.piston.tooltip didn't work, I created an instance above the class:
let pistonView = pistonViewController();
and then from within the separate class called pistonView.set_piston();
func set_piston(index: Int) {
piston1.toolTip = "yay it worked!";
}
I get the same error: found nil.
How to get the correct instance of the pistonViewController (the one that appears on viewDidLoad) so that piston1 will not be nil?
There is this solution, but it looks needlessly complex. This one appears to only work on iOS, using a storyboard.InstantiateViewController command that does not work on MacOS. This MacOS solution is poorly explained and does not appear to work.
"[How do I] Modify IBOutlet property from outside of viewDidLoad"
(But what you're really asking is how you modify a view controller's views from outside of the view controller.)
The short answer is "Don't do that." It violates the principle of encapsulation. You should treat a view controller's view properties as private, and only modify them inside the view controller's code.
(To misquote Groucho Marx: "Doc, it crashes when I do this". "Then don't do that!")
Instead, add a public property (pistonToolTip) in your PistonViewController (Class names should begin with upper-case letters).
class PistonViewController: UIViewController {
var pistonToolTip: String {
didSet {
piston?.tooltip = pistonToolTip
}
}
}
And in case you set pistonToolTip before your PistonViewController has loaded its views, add this line to viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
piston?.tooltip = pistonToolTip
// The rest of your viewDidLoad code
}
Ultimately I just set it up in viewDidLoad, with a timer waiting for the other program to get the variables that will then be assigned to the pistons.
The lack of effective pointers to instances of View Controllers makes anything else not possible or perhaps just arcane and difficult.

in swift, ViewController wont let me access its textfield from another class

here is what is happening https://imgur.com/a/fblot
yes i've read the article about optional
but that textfield isn't nil or without a value as it does it
when i press enter when theres a value in the text-bar
i also tried ! and ? with same results
i tried many many things and it wont work
always the same crash
can someone explain what is the reason that textfield is hard to access
i tried
var = ViewControler()
If you want to call the class function from the viewcontroller that contains the textfield change the class function to have one argument :
func changetextfieldincontroller(_ vc: NSViewController){
if let vc = vc as? ViewController{
vc.textField.stringValue = "New text"
}
}
when you call it from the controller make sure to pass self as an argument.
You need to instantiate the viewController since it looks like it's from a storyboard/xib. If that's the case, you can check this other question: How can I load storyboard programmatically from class?

Currently messing with Swift Reachability, should I do all my code in viewDidLoad or in viewDidAppear?

I'm currently trying to implement Reachability into my current project. I followed a tutorial on YouTube that worked but I'm unsure whether or not its the correct way of doing it. In the Reachability documentation (https://github.com/ashleymills/Reachability.swift) it shows two examples first one being 'Example - closures' where I assume it's done in the viewDidLoad?
//declare this property where it won't go out of scope relative to your listener
let reachability = Reachability()!
reachability.whenReachable = { reachability in
// this is called on a background thread, but UI updates must
// be on the main thread, like this:
DispatchQueue.main.async {
if reachability.isReachableViaWiFi() {
print("Reachable via WiFi")
} else {
print("Reachable via Cellular")
}
}
}
reachability.whenUnreachable = { reachability in
// this is called on a background thread, but UI updates must
// be on the main thread, like this:
DispatchQueue.main.async {
print("Not reachable")
}
}
do {
try reachability.startNotifier()
} catch {
print("Unable to start notifier")
}
and the last example was 'Example - notifications', this is where I get confused the creator says to do that all in viewDidAppear. Is there really a big difference if I just do everything inside viewDidLoad? Does it change the outcome of anything? It currently works fine but I'm not sure whether it's right, I don't want it affecting me in the future. Any help would be great! Thanks.
It depends on your needs.
If you want to use Reachability...
... dynamically only if this particular view is frontmost, startNotifier() in viewWillAppear and stopNotifier() in viewDidDisappear.
... in this particular view as long as the view is alive/loaded startNotifier() in viewDidLoad.
... globally in all views put the entire code in AppDelegate and post notifications.

why pass viewController as variable?

First of all I have to say I am really new to swift and Objective C.I am learning them by myself.
I have a question for this code
I have a delegate in my SettingViewController called "settingsViewControllerFinished" and it pass the whole controller as a variable.
the code like this:
in my SettingViewController.swift
protocol SettingViewControllerDelegate: class {
func settingsViewControllerFinished(settingsViewController: SettingsViewController)
}
#IBAction func close(sender: AnyObject) {
dismissViewControllerAnimated(true, completion: nil)
self.delegate?.settingsViewControllerFinished(self)
}
I am confused.What did you mean if you pass the whole controller as a variable?(maybe the question is silly for you)
in my viewController:
func settingsViewControllerFinished(settingsViewController: SettingsViewController)
{
self.brushWidth = settingsViewController.brush
self.opacity = settingsViewController.opacity
self.red = settingsViewController.red
self.green = settingsViewController.green
self.blue = settingsViewController.blue
}
I guess the reason is:I pass everything in SettingViewController to ViewController so that I could use the variables in SettingViewController.
Am I rihgt?
Generally you are correct, yes: passing the SettingViewController back to its delegate enables the original caller to not have to keep a reference to the created and shown SettingViewController since the delegate method sends the relevant information along already.
But there is more: In some cases of delegates this style is useful for something different. Imagine a click handler consisting of a function func somethingGotClicked(sender:YourSenderType). If your class creates multiple instances of YourSenderType and shows them at the same time registering itself as their delegate there would be no way to know which one got clicked if there was no sender parameter. In some func somethingGotClicked() you would not know which one got clicked. That capability is often needed when showing multiple UITableView or UICollectionView is one single view with one single instances set as their delegate.

Why does my UIButton delegate have to execute entirely before changes are shown in view?

I'm doing some MonoTouch development, and I really can't figure out an problem I've run into
I'm having an ViewController containing a UIButton. I have added a delegate to the TouchDown event of this button. In this delegate I'm calling a WebService and trying to change the colour and title of the button. However nothing happens to the button before the entire delegate have been executed. The thing is that the webservice is rather slow, so I want to give the users a waiting message by changing the colour and title of the button.
The code:
public override void ViewDidLoad ()
{
View.BackgroundColor = UIColor.Black;
bookButton = new UIButton( new RectangleF(10,100,this.View.Frame.Width-10 ,40) );
bookButton.BackgroundColor = UIColor.Clear;
setButton();
bookButton.TouchDown += delegate {
gymClass.book();
setButton();
tableView.ReloadData();
NavigationController.PopViewControllerAnimated( true );
};
this.View.AddSubview( bookButton );
}
Anyone, please?
The delegate is executed on the main thread which is responsible for rendering, so you are blocking the renderer until you return.