Is it possible to access a view controller from my previous project?
What I want to achieve is to use the view controller of my previous project to my new project programmatically. In Swift 3.
You can use a Framework target to contain virtually any common code you want, including UIViews.
In your Framework:
open func commonView() -> UIView {
// code to create view or call up xib file from framework
}
In your app:
import MyFramework
class MainViewController:UIViewController {
override viewDidLoad() {
self.view = commonView()
}
}
But if you want it to be a UIViewController? I'm not so sure that can easily work. Maybe if you make it a child VC of a VC in the app, of split out everything among the VC's view and it's logic. In that sort of scenario, you probably are better off with the more manual solution that @Lion gave you.
If you are interested, here's a more detailed description of setting up a Framework target from a question I answered a few weeks ago.
EDIT Based on a comment, here's a bit more that may help. First, remember my original answer included a link at the end to something that should help you set things up in Xcode. Also, the important thing - maybe the most important - is to design things properly!
Let's say you wish to have common code to add a set of buttons that look the same and that you can connect up to specific functions within a specific app.
First, recognize what you can and cannot do, due to the platform. You have Cocoa (Foundation) and Cocoa Touch (UIKit). In other words, you have an NSButton and a UIButton. I know of no way you can simply make a framework that returns a "button". (But a framework can return a Core Image filter output because that is platform agnostic.)
Restricting things to UIKit, let's talk storyboards and view controllers. I'm finding much confusion on the latter. There's a huge difference between "views" and "view controllers". Yesterday I made several edits to a question because of this. UIViews are the base of just about any control in UIKit. UIViewControllers contain the logic to work with the views. (BTW, this is MVC 101.)
Storyboards are something specific to Xcode, and as such, I'm not a good source of how "reusable" you can make them. They may be something you can do - after all in the end they are a specific XML format that Xcode uses.
But while you probably cannot use a UIViewController as a return in a framework call (at least not easily), you can use any UIView - and their subclasses. And guess what? UIButton is such a thing.
Swift introduces much to a framework. Extensions and convenience initializers are two features. Let's say you put this into a framework:
extension UIButton {
convenience public init(
title:String,
titleColor:UIColor,
titleFontSize:CGFloat,
image:UIImage,
titleEdgeInsets:UIEdgeInsets,
imageEdgeInsets:UIEdgeInsets,
tintColor:UIColor,
backgroundColor:UIColor,
borderColor:CGColor,
borderWidth:CGFloat,
cornerRadius:CGFloat
) {
self.init(type: .system)
self.setTitle(title, for: .normal)
self.setTitleColor(titleColor, for: .normal)
self.titleLabel?.font = UIFont.systemFont(ofSize: titleFontSize)
self.setImage(image, for: .normal)
self.titleEdgeInsets = titleEdgeInsets
self.imageEdgeInsets = imageEdgeInsets
self.tintColor = tintColor
self.backgroundColor = backgroundColor
self.layer.borderColor = borderColor
self.layer.borderWidth = borderWidth
self.layer.cornerRadius = cornerRadius
self.translatesAutoresizingMaskIntoConstraints = false
}
}
If you combine that with this:
public func returnImage(_ named:String) -> UIImage {
let myBundle = Bundle.init(identifier: "com.company.framework")
let imagePath = (myBundle?.path(forResource: "images", ofType: "bundle"))! + "/" + named
let theImage = UIImage(contentsOfFile: imagePath)
return theImage!
}
[Replace "com.company.name" with your Framework ID, and "images" with the name of your bundle]
And you can do this in your app, as long as you imported your framework:
let openCamera = UIButton(
title: "Camera",
titleColor: UIColor.yellow,
titleFontSize: 15,
image: returnImage("Camera"),
titleEdgeInsets: UIEdgeInsets(top: 0, left: -51, bottom: -49, right: 0),
imageEdgeInsets: UIEdgeInsets(top: 0, left: 0, bottom: 23, right: -51),
tintColor: UIColor.yellow,
backgroundColor: UIColorFromRGB(0x1F1F1F),
borderColor: UIColor.yellow.cgColor,
borderWidth: 2,
cornerRadius: 10)
I'm still learning subtleties with Swift and frameworks... optionals and such. But you can also do this in your framework:
public class ToolBoardCloseButton: UIButton {
convenience init(
tag :Int,
target :Any,
action :Selector
)
{
self.init(frame: CGRect.zero)
self.backgroundColor = sgRed
self.setTitle("Close", for: .normal)
self.tintColor = UIColor.white
self.layer.cornerRadius = 5
self.layer.borderColor = UIColor.white.cgColor
self.layer.borderWidth = 1
self.tag = tag
self.addTarget(target, action: action, for: .touchUpInside)
}
}
And so that means this in your app:
closeButton = ToolBoardCloseButton(tag: tag, target: target, action: hideAction)
Of course, if you have control on this, make your target and action optional (if you need, I didn't). That way - as long as you code for it - you can make them optional in your calls.
Last note. In my framework the UI logic behind "hideAction" is there as part of the ToolBoard class, which is a subclass of UIView. All my app has in the view controller is (1) instantiating the ToolBar, tool bar buttons, and boards (along with their sizes), (2) creates the close button and the call to the framework to close it, and that leave (3) code that is app-specific. While you may not find a way to move a UIViewController into a framework call, you should be able to move all your common code and views into one.