4

I am currently making a demo iOS app for practice in swift and I have run into an issue. I just created a new page and there is only one button on this page. I have linked the button to an IBAction function and it shows a proper connection.

I would show you a screen shot but I do not have enough reputation (every other issue I have ever had I could find a post from someone else).

It even shows the circle with a filled in dot and when clicked it shows the correct button. In the connection inspector it shows under sent events a connection between "Touch Up Inside" and "UserPage btnProgressClick" (Userpage is my class that extends UIViewController and is referenced by this particulate View Controller and btnProgressClick is the name of the IBAction function I want to run).

I found this post and I tried a clean build but that did not work. I also moved my button around and it updated properly in the simulator.

The code inside btnProgressClick is never executed. I have put a breakpoint at the first line and it does not break.

Here is the "Main.storyboard" XML code that links the button to the function.

    <!--User Page-->
    <scene sceneID="aNb-aX-hZF">
        <objects>
            <viewController storyboardIdentifier="UserPage" id="w2h-zR-Kdu" customClass="UserPage" customModule="GenomeTrackerDemo" customModuleProvider="target" sceneMemberID="viewController">
                <layoutGuides>
                    <viewControllerLayoutGuide type="top" id="9dS-Hw-ZYg"/>
                    <viewControllerLayoutGuide type="bottom" id="7PS-pA-lFe"/>
                </layoutGuides>
                <view key="view" contentMode="scaleToFill" id="w6A-eT-aKv">
                    <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                    <subviews>
                        <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="JGD-xx-tMQ">
                            <rect key="frame" x="20" y="48" width="46" height="30"/>
                            <state key="normal" title="Button"/>
                            <connections>
                                <action selector="btnProgressClick:" destination="w2h-zR-Kdu" eventType="touchUpInside" id="F1N-QY-fhb"/>
                            </connections>
                        </button>
                    </subviews>
                    <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                </view>
            </viewController>
            <placeholder placeholderIdentifier="IBFirstResponder" id="Fsq-L4-Are" userLabel="First Responder" sceneMemberID="firstResponder"/>
        </objects>
        <point key="canvasLocation" x="1043" y="426"/>
    </scene>

and here is the UserPage Class:

import Foundation
import UIKit

class UserPage: UIViewController {

    var thisUser: User = User()

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    @IBAction func btnProgressClick(sender: UIButton) {

        let storyboard = UIStoryboard(name: "Main", bundle:nil)

        let vc: progressPage = storyboard.instantiateViewControllerWithIdentifier("progressPage") as! progressPage


        UIView.transitionFromView(self.view, toView: vc.view, duration: 0.8, options: UIViewAnimationOptions.TransitionFlipFromRight, completion: nil)
    }

}

As I said before this is my first question so I am open to feedback on how it was worded and what information I gave.

I would like to add some information about how this page is called. It is called after an Async call to a web service. After the data is successfully brought back I transition to the page with this function:

func afterSuccessfulLogin(thisUser: User){

    dispatch_async(dispatch_get_main_queue()){
        let storyboard = UIStoryboard(name: "Main", bundle:nil)

        let vc: UserPage = storyboard.instantiateViewControllerWithIdentifier("UserPage") as! UserPage
        vc.thisUser = thisUser


        UIView.setAnimationCurve(.EaseIn)

        UIView.transitionFromView(self.view, toView: vc.view, duration: 1.2, options: UIViewAnimationOptions.TransitionFlipFromRight, completion: nil)
    }
} 

not sure if this makes a difference but I figured I would throw this in there.

Any help on this issue would be very useful.

Thanks!!

Community
  • 1
  • 1
James Hollyer
  • 277
  • 1
  • 3
  • 18
  • How have you validated that the function is not being called, have you tried putting a breakpoint in that function to verify it isn't occurring? – Charles A. Oct 02 '15 at 18:20
  • Agreed. It sounds like the outlet was made properly so I am curious if any of the function is being called. – Russell Oct 02 '15 at 18:24
  • Yes, that is exactly what I did. The breakpoint was never hit. Sorry, I should have put that in the post. – James Hollyer Oct 02 '15 at 18:25
  • `@IBAction` should do this, but try putting the keyword `dynamic` between `@IBAction` and `func`. – Charles A. Oct 02 '15 at 18:31
  • I am not familiar with that keyword in swift. I tried it. Still not hitting the breakpoint. – James Hollyer Oct 02 '15 at 18:33
  • Could you post your test project on github? I'll fix it up for you. – matt Oct 02 '15 at 18:39
  • As an experiment, try changing `sender: UIButton` to `sender: AnyObject`. Any difference? – stevekohls Oct 02 '15 at 18:40
  • I actually changed it from AnyObject to UIButton as an experiment. I should have changed it back before posting. I just changed it back and still no joy. – James Hollyer Oct 02 '15 at 18:57
  • I will try to get it up on github soon. There is another page on this app that has some test data that falls under an NDA so I need to change it around before posting. – James Hollyer Oct 02 '15 at 18:59
  • 2
    Just wanted to comment that you did a great job on your first question. Thanks for putting effort into and showing what you've tried so far. – Sandy Chapman Oct 02 '15 at 20:42

1 Answers1

1

[Removed prior answer, due to additional information in question]

iOS contains a view hierarchy and a view controller hierarchy. Both of these need to be consistent. In the code posted in the question, only the view hierarchy is being handled. Try the following changes:

  1. Call addChildViewController: on self prior to calling transitionFromView:toView:duration:options:completion: passing vc.
  2. In the completion block for the transitionFromView:toView:duration:options:completion: method, call didMoveToParentViewController: on vc, passing self.

    let storyboard = UIStoryboard(name: "Main", bundle:nil)
    
    let vc: UserPage = storyboard.instantiateViewControllerWithIdentifier("UserPage") as! UserPage
    vc.thisUser = thisUser
    
    
    UIView.setAnimationCurve(.EaseIn)
    
    self.addChildViewController(vc)
    UIView.transitionFromView(self.view, toView: vc.view, duration: 1.2, options: UIViewAnimationOptions.TransitionFlipFromRight, completion: { (finished) -> Void in vc.didMoveToParentViewController(self) })
    

It's also a little strange to be calling transitionFromView:toView:duration:options:completion: and passing self.view as the fromView parameter. The fromView parameter is typically removed and replaced with the toView parameter, which would leave the original view controller in the view controller hierarchy with no actual view in the view hierarchy. It might be wise to introduce a nested UIView that you are replacing instead of self.view.

Charles A.
  • 10,685
  • 1
  • 42
  • 39
  • No joy. I broke the connection. The target membership had the target App in there and was checked. UserPage did get auto filled while typing it into the Class field. I reconnected the button with a ctrl-drag to the function and ran it again. Still does not execute that function....This is killing me. – James Hollyer Oct 02 '15 at 18:56
  • The only other thing I can think of is that your button has user interaction disabled or that it is drawing outside the bounds of its parent view but the parent isn't set to clip subviews. :/ Does it visibly highlight when you touch it? – Charles A. Oct 02 '15 at 18:58
  • Just checked the Attributes Inspector for the button and User Interaction Enabled is checked. and yes the Button visibily highlights when I click it. The word "Button" flashes white. – James Hollyer Oct 02 '15 at 19:07
  • I am going to add something else to the description. The page is called in a opened in a strange way. I don't think it should make a difference but nothing about this makes sense right now anyway. – James Hollyer Oct 02 '15 at 19:10
  • Like the other commentor mentioned, I'd be happy to look at it if you can post the project somewhere. – Charles A. Oct 02 '15 at 19:13
  • That is a strange presentation method. I would test just doing a normal modal presentation and see if the button works in that case. Then you will know if that's the problem. I think you probably need to set the UserPage view controller as a child of the view controller doing the presentation. I will edit my answer to reflect this. – Charles A. Oct 02 '15 at 19:18
  • This is the answer! It worked. However that replacement of self.view with the nested UIView is not just wise it is necessary. Otherwise there is an exception thrown. Thank you so much! – James Hollyer Oct 06 '15 at 16:49