3

I have an Obj C project that I have added a Swift viewController to.

I'm trying to attach a storyboard to the viewController.

I can programmatically add things to the view but I can not get the storyboard to show up.

I have also tried to use a xib as a vie for the Swift viewController with no luck.

Calling the Swift vie form Obj C from a didSelectRowAtInexPath:

SwiftController *sc = [[SwiftController alloc] init];
[self.navigationController pushViewController:sc animated:YES];

SwiftController.swift:

import Foundation
import UIKit

@objc class SwiftController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

        // This prints
        println("in the scrolling view")
        // This works
        self.view.backgroundColor = .redColor();
    }

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

Storyboard is hooked up correctly:

1

2

And this is what I get every time:

3

Same results happen with a xib.

There are a lot of things in the Apple Docs and on the web and here on SO that deal with many issues "around" this one but I have not found anything that helps me see what I'm doing wrong here. Doing things the way that works or Obj C does not seem to work. Clearly I'm a noob with Swift. Any help would be great. Thanks.

addzo
  • 845
  • 3
  • 13
  • 37

3 Answers3

5

There are two basic approaches when using storyboards:

  1. When you have Objective-C code that needs to transition to another scene in the storyboard, you can:

    • give that destination scene a storyboard id (e.g. SwiftControllerScene) in Interface Builder;

    • use the storyboard instantiateViewControllerWithIdentifier to instantiate that destination view controller; and

    • transition to that new scene (i.e. push or present that view controller).

    Thus:

    SwiftController *sc = [self.storyboard instantiateViewControllerWithIdentifier:@"SwiftControllerScene"];
    [self.navigationController pushViewController:sc animated:YES];
    
  2. Alternatively, when using storyboards, rather than manually instantiating the destination's view controller and then calling pushViewController, I'd prefer to set up a segue in the storyboard between the view controllers (see https://stackoverflow.com/a/27650207/1271826). I'd then programmatically perform the segue (referencing, of course, whatever storyboard identifier you gave the segue):

    [self performSegueWithIdentifier:@"SegueToSwiftScene" sender:self];
    

    This way, the storyboard continues to represent the visual flow of the app.

Note, the fact that the destination scene's view controller is written in Swift vs Objective-C is largely immaterial. The question is merely what language the source view controller uses (hence the above examples are in Objective-C) and the process is otherwise largely the same regardless of the language of the destination view controller.

Community
  • 1
  • 1
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Both answers were correct. But since this one taught me something extra I chose this one. Thanks to both Rob and Sergey and Schemetrical! – addzo May 04 '15 at 14:48
  • Interestingly, when using this solution I now get "Unknown class SwiftController in Interface Builder file" When I run. Any objects I place in the storyboard show up but when I try to connect to them in the .swift file I get the dreaded "not key value compliant" error. Additionally, the module for the storyboard is "None" but changing it does not help. So I have not been able to find an answer for this. Any ideas why this would be happening? – addzo May 04 '15 at 16:44
  • I'd make sure that the `SwiftController` class is included in the compile sources for that target. But I just did a test Objective-C project and added a scene with a Swift view controller and it worked fine. So I don't know what the issue might be. – Rob May 04 '15 at 17:22
1

Because in this case, you're initializing a new SwiftController instead of using the one from the storyboard. You will want to either perform a segue to the new storyboard vc or get the vc from

self.storyboard.instantiateViewControllerWithIdentifier(_controller id_)
Sergey Kuryanov
  • 6,114
  • 30
  • 52
Schemetrical
  • 5,506
  • 2
  • 26
  • 43
1

in case you use a xib for your swift viewController you must init it like this:

SwiftController* controller = [[SwiftController alloc]  initWithNibName:@"SwiftController" bundle:nil]

Where SwiftController is also the name of your xib.

I notice this issue in iOS 8, but it works normally in iOS 9 and iOS 10 when you init the controller simply like this:

SwiftController* controller = [[SwiftController alloc]  init];
eli-k
  • 10,898
  • 11
  • 40
  • 44
Sam
  • 97
  • 10