StefanLage / SLPagingViewSwift

Navigation bar system allowing to do a Tinder like or Twitter like. SLPagingViewSwift is a Swift port of the Objective-C of SLPagingView
MIT License
215 stars 35 forks source link

Custom Controller and Button Actions #10

Open YaroslawBagriy opened 9 years ago

YaroslawBagriy commented 9 years ago

Hello,

So I've implemented the code below.

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
    var orange = UIColor(red: 255/255, green: 69.0/255, blue: 0.0/255, alpha: 1.0)
    var gray = UIColor(red: 0.84, green: 0.84, blue: 0.84, alpha: 1.0)

    var ctr1 = storyboard.instantiateViewControllerWithIdentifier("SettingsViewController") as! SettingsViewController
    ctr1.title = "Settings"
    var ctr2 = storyboard.instantiateViewControllerWithIdentifier("gameViewController") as! SeekerViewController
    ctr2.title = "Game"
    var ctr3 = UIViewController()
    ctr3.title = "Exit"
    ctr3.view.backgroundColor = gray

    var img1 = UIImage(named: "gear")
    img1 = img1?.imageWithRenderingMode(.AlwaysTemplate)
    var img2 = UIImage(named: "profile")
    img2 = img2?.imageWithRenderingMode(.AlwaysTemplate)
    var img3 = UIImage(named: "chat")
    img3 = img3?.imageWithRenderingMode(.AlwaysTemplate)

    var items = [UIImageView(image: img1), UIImageView(image: img2), UIImageView(image: img3)]
    var controllers = [ctr1, ctr2]
    controller = SLPagingViewSwift(items: items, controllers: controllers, showPageControl: false)

    controller?.pagingViewMoving = ({ subviews in
        for v in subviews {
            var lbl = v as! UIImageView
            var c = gray

            if(lbl.frame.origin.x > 45 && lbl.frame.origin.x < 145) {
                c = gradient(Double(lbl.frame.origin.x), Double(46), Double(144), orange, gray)
            }
            else if (lbl.frame.origin.x > 145 && lbl.frame.origin.x < 245) {
                c = gradient(Double(lbl.frame.origin.x), Double(146), Double(244), gray, orange)
            }
            else if(lbl.frame.origin.x == 145){
                c = orange
            }
            lbl.tintColor = c
        }
    })

    self.nav = UINavigationController(rootViewController: self.controller!)
    self.window?.rootViewController = self.nav
    self.window?.backgroundColor = UIColor.whiteColor()
    self.window?.makeKeyAndVisible()

I added two new custom controllers. The SettingsViewController has a button with an action. When I go to click the button my program crashes. Any reasons why? The button works perfectly if I don't have it go through the SLPagingViewSwift controller.

YaroslawBagriy commented 9 years ago

Hello,

So I see there was Swift 1.2 updates. I pulled the code from https://github.com/kobim/SLPagingViewSwift/tree/swift1.2

it still doesn't seem to work. It builds great. But I get a EXE_BAD_ACCESS (code=EXC_i386_GPFLT) when I click a button on one of my custom ViewControllers that I added. I would greatly appreciate help with this. I've been searching all over the internet for the answer but couldn't find it.

I added a new subclass of UIViewController

class TestViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

    let button   = UIButton()
    button.frame = CGRectMake(100, 100, 100, 50)
    button.backgroundColor = UIColor.greenColor()
    button.setTitle("Test Button", forState: UIControlState.Normal)
    button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)

    self.view.addSubview(button)

    // Do any additional setup after loading the view.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func buttonAction(sender:UIButton!)
{
    println("Button tapped")
}

/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.
}
*/

}

Which then I replaced one of the UIVIewControllers in AppDelegate with it. Code is shown below.

var window: UIWindow?
var nav: UINavigationController?
var controller: SLPagingViewSwift!

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
    let orange = UIColor(red: 255/255, green: 69.0/255, blue: 0.0/255, alpha: 1.0)
    let gray = UIColor(red: 0.84, green: 0.84, blue: 0.84, alpha: 1.0)

    var ctr1 = UIViewController()
    ctr1.title = "Ctr1"
    ctr1.view.backgroundColor = orange
    var ctr2 = UIViewController()
    ctr2.title = "Ctr2"
    ctr2.view.backgroundColor = UIColor.yellowColor()
    var ctr3 = TestViewController()
    ctr3.title = "Ctr3"
    ctr3.view.backgroundColor = gray

    var img1 = UIImage(named: "gear")
    img1 = img1?.imageWithRenderingMode(.AlwaysTemplate)
    var img2 = UIImage(named: "profile")
    img2 = img2?.imageWithRenderingMode(.AlwaysTemplate)
    var img3 = UIImage(named: "chat")
    img3 = img3?.imageWithRenderingMode(.AlwaysTemplate)

    var items = [UIImageView(image: img1), UIImageView(image: img2), UIImageView(image: img3)]
    var controllers = [ctr1, ctr2, ctr3]
    controller = SLPagingViewSwift(items: items, controllers: controllers, showPageControl: false)

    controller.pagingViewMoving = ({ subviews in
        if let imageViews = subviews as? [UIImageView] {
            for imgView in imageViews {
                var c = gray
                let originX = Double(imgView.frame.origin.x)

                if (originX > 45 && originX < 145) {
                    c = self.gradient(originX, topX: 46, bottomX: 144, initC: orange, goal: gray)
                }
                else if (originX > 145 && originX < 245) {
                    c = self.gradient(originX, topX: 146, bottomX: 244, initC: gray, goal: orange)
                }
                else if(originX == 145){
                    c = orange
                }
                imgView.tintColor = c
            }
        }
    })

    self.nav = UINavigationController(rootViewController: self.controller)
    self.window?.rootViewController = self.nav
    self.window?.backgroundColor = UIColor.whiteColor()
    self.window?.makeKeyAndVisible()
    return true
}

func applicationWillResignActive(application: UIApplication) {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

func applicationDidEnterBackground(application: UIApplication) {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

func applicationWillEnterForeground(application: UIApplication) {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

func applicationDidBecomeActive(application: UIApplication) {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

func applicationWillTerminate(application: UIApplication) {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

func viewWithBackground(color: UIColor) -> UIView{
    var v = UIView()
    v.backgroundColor = color
    return v
}

func gradient(percent: Double, topX: Double, bottomX: Double, initC: UIColor, goal: UIColor) -> UIColor{
    var t = (percent - bottomX) / (topX - bottomX)

    let cgInit = CGColorGetComponents(initC.CGColor)
    let cgGoal = CGColorGetComponents(goal.CGColor)

    var r = cgInit[0] + CGFloat(t) * (cgGoal[0] - cgInit[0])
    var g = cgInit[1] + CGFloat(t) * (cgGoal[1] - cgInit[1])
    var b = cgInit[2] + CGFloat(t) * (cgGoal[2] - cgInit[2])

    return UIColor(red: r, green: g, blue: b, alpha: 1.0)
}

screen shot 2015-08-28 at 2 46 32 pm

Here is the stack trace. I made a new project and make a one screen app with the screens class as my TestViewController, I clicked the button and it worked.

kobim commented 9 years ago

The problem is that your TestViewController isn't retained - this library only retains the views of the view controllers, and not the view controllers themselves.

If you add var ctr3 : UIViewController! to your AppDelegate, and assign that to SLPagingViewSwift's controllers parameter, your code will work.

YaroslawBagriy commented 9 years ago

Koblm,

Thank you for such a quick response. It works just like I want.

Thanks,

Yaroslaw Bagriy

MuhammadMazharIqbal commented 7 years ago

Thanks its working