Open viewcontroller with textfield inside view xib file - swift

I will explain the process before asking my question:
I have a tableviewcontroller, but i needed a textfield was always present at the hearing, to solve this problem i create a xib file with textfield inside and call the view with viewForHeaderInSection; at this point all is perfect.
i call the view whith this code:
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return NSBundle.mainBundle().loadNibNamed("createComment", owner: nil, options: nil)[0] as? createComment
}
My problem is next:
I want that when capturing text field starts a new window opens, something like what makes facebook to create a comment.
My code in createComment is:
class createComment: UIView, UITextFieldDelegate {
#IBOutlet weak var commentTextField: StyleComentTextField!
weak var controller:tableComentVC!
var currentController = tableComentVC()
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func awakeFromNib() {
self.commentTextField.delegate = self
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
commentTextField.resignFirstResponder()
if(textField == commentTextField){
print("ok i tab in commentTextField")
let storyBoard: UIStoryboard = UIStoryboard (name: "Main", bundle: nil)
self.controller?.navigationController!.pushViewController(storyBoard.instantiateViewControllerWithIdentifier("writeComment") as! writeComment, animated: true)
resign()
return false
}else{
return true
}
}
}
but this code dont work, the print in code works correctly, but i don't know why dont open the next viewcontroller.
Thanks!

Related

swift _ Pushing ViewController in gives a black screen

I have two screens the first one"ViewController" has tableview and the second "MapViewController" one contains MKMapView when i navigate from the first one to the second the second one looks like black screen the second screen is supposed to appear the apple map can any one help me ?
import UIKit
import MapKit
struct Category {
let place : String
let coordinates : [Double]
}
class ViewController: UIViewController {
private let tableview : UITableView={
let table = UITableView()
table.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
return table
}()
private let data : [Category]=[
Category(place: "Misr bank ", coordinates: [30.576352,31.503955])
]
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(tableview)
tableview.delegate=self
tableview.dataSource=self
}
override func viewDidLayoutSubviews() {
tableview.frame=view.bounds
}
}
extension ViewController:UITableViewDelegate{
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let category = data[indexPath.row]
let mapview = MapViewController(coor: category.coordinates)
self.navigationController?.pushViewController(mapview, animated: true)
}
}
MapViewController
import UIKit
import MapKit
class MapViewController: UIViewController {
#IBOutlet weak var map: MKMapView!
private let coor : [Double]
init(coor:[Double]){
self.coor=coor
super.init(nibName: nil, bundle: nil)
let lat = coor[0]
let long = coor[1]
print(lat)
print(long)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
}
It looks like MapViewController is designed in the storyboard. (If it were not, you would not be talking about #IBOutlet weak var map: MKMapView!)
But if so, then saying MapViewController(coor: category.coordinates) is not how to retrieve the instance that you designed in the storyboard. If you say that, you will indeed get basically an empty interface.
Instead, give that instance in the storyboard an identifier, and in your code, ask the storyboard to instantiate the view controller that has that identifier.
You will also have to rearrange your initialization completely. The storyboard is going to call init(coder:), not init(coor:). In fact, you can get rid of the latter entirely:
#IBOutlet weak var map: MKMapView!
var coor = [Double]()
required init?(coder: NSCoder) {
super.init(coder:coder)
}
override func viewDidLoad() {
super.viewDidLoad()
let lat = coor[0]
let long = coor[1]
print(lat)
print(long)
}
Now when you instantiate MapViewController from the storyboard, immediately also set mapView.coor before pushing.

Passing data from UIViewController to Custom UIView with XIB

I have the following swift file which controls a xib file
import UIKit
protocol SelectProfile: class {
func selectionUp(id: Int, selected: Bool)
}
class Component: UIView {
#IBOutlet weak var name: UILabel!
#IBOutlet weak var selection: UIView!
var selected: Bool = false
var profileId: Int = 6
weak var delegate: SelectProfile?
#IBAction func selProfile(_ sender: Any) {
selected = !selected
selection.isHidden = !selected
delegate?.selectionUp(id: profileId, selected: selected)
}
let nibName = "Component"
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
func commonInit() {
guard let view = loadViewFromNib() else { return }
view.frame = self.bounds
self.addSubview(view)
selection.isHidden = true
name.text = String(profileId)
}
func loadViewFromNib() -> UIView? {
let nib = UINib(nibName: nibName, bundle: nil)
return nib.instantiate(withOwner: self, options: nil).first as? UIView
}
}
In my UIViewController where I want to interact with the component I have the following code (shortened for brevity)
import UIKit
class Home: UIViewController, SelectProfile {
#IBOutlet weak var profileComponent: Component!
func selectionUp(id: Int, selected: Bool) {
print(id, selected)
}
override func viewDidLoad() {
profileComponent.delegate = self
profileComponent.profileId = 2
}
}
My delegate works nicely and I'm able to change the values for IBOutlets but I can't pass a value to variables. This line doesn't pass the data to my xib profileComponent.profileId = 2.
It seems like I have an issue with initialization of the xib but I don't know how to fix it.
The viewDidLoad of controller is called after view's init, so when you change profileId as you do, it is changed, but not reflected anywhere.
I assume the following, at least, missed:
var profileId: Int = 6 {
didSet {
name.text = String(profileId)
// call delegate here if needed as well
}
}

How to open View Controller in Table View with Button by using Objc in Swift?

Stackoverflow
I know how to make a button in the table view cells with website links, rate, mail, and many things. However, How could I open the view controller with the instantiateViewController in the #Objc func's statements?
For example.
Create a new Table View Cell folder called FeedBackButtonsTableViewCell
class FeedBackButtonsTableViewCell: UITableViewCell {
#IBOutlet weak var ButtonCells: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Let create a new view controller folder called
class FeedbackViewController: UIViewController {
#IBOutlet weak var TableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.navigationItem.title = "Feedback"
}
}
add the extension to calling the view controller to UITableViewDataSource and UITableViewDelegate and create a obj func statements inside of the second FeedbackViewController with UITableViewDataSource and UITableViewDelegate under the cells.
extension FeedbackViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
if indexPath.row == 1 {
buttonCell = TableView.dequeueReusableCell(withIdentifier: "ButtonCells") as? FeedBackButtonsTableViewCell
buttonCell?.ButtonCells.addTarget(self,action: #selector(LearnMore),for: .touchUpInside)
buttonCell?.ButtonCells.tag = indexPath.row
return buttonCell!
}
#objc func LearnMore() {
// How could I write to open the view controller with UIButton in the Table View Cells?
}
}
Thank you for bring a kind of help! :)
Simple solution could be to use procol.
protocol CellActionDelegate{
func didButtonTapped(index: Int)
}
Now confirm the protocol in FeedbackViewController. Take index and actionDelegate properties in your UITableViewCell subclass.
class FeedBackButtonsTableViewCell: UITableViewCell{
var actionDelegate: CellActionDelegate?
var index: Int?
.....
// Take Action of UIButton here
#IBAction func more(_ sender: Any) {
if let delegate = self.actionDelegate{
delegate.didButtonTapped(index!)
}
}
}
Now in your FeedbackViewController set actionDelegate & Corresponding index in
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {}
you can open anotherView controller from func didButtonTapped(index: Int) definition .
extension FeedbackViewController:CellActionDelegate{
func didButtonTapped(index: Int) {
let storybord = UIStoryboard(name: "Main", bundle: nil)
guard let controller = storybord.instantiateViewController(withIdentifier: "AnotherControllerIdentfier") as? AnotherViewController else{
fatalError("Could not finc another view controller")
}
self.present(controller, animated: true, completion: nil)
}
}
#objc func LearnMore() {
let viewController = FeedbackDetailsViewController()// creation of viewController object differs depends on how you fetch the UI, means either you are using storyboard or xib or directly making ui in code.
self.navigationController?.pushViewController(viewController, animated: true)
}

Unable to access UIView subclass IBOutlets From TabBarController

I have a UIView Class with xib. I try to add it in another ViewControllers as a popover view. I have outlet connections. But when I run the application it crashed and stated
This class is not key value coding-compliant for the key btnAbtUs
I think the problem is should select delegate. I may using wrong way to add this xib. How can I correct it?
Here is my code.
my UIView subclass
class MoreView: UIView {
#IBOutlet var containerView: UIView!
#IBOutlet weak var btnAboutUs: UIButton!
override public func awakeFromNib() {
super.awakeFromNib()
}
override init(frame: CGRect) {
super.init(frame: frame)
loadViewFromNib()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
loadViewFromNib()
}
func loadViewFromNib() {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "MoreView", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
view.frame = bounds
view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.insertSubview(view, at: 0)
commitInit()
}
private func commitInit(){
containerView.translatesAutoresizingMaskIntoConstraints = true
self.btnAboutUs.addTarget(self, action: #selector(self.clickAboutUs(_:)), for: .touchUpInside)
}
class func instanceFromNib() -> UIView {
return UINib(nibName: "MoreView", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! UIView
}
#objc func clickAboutUs(_ sender: Any) {
print("tap")
}
}
in UITabBarController
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
let moreView = MoreView.instanceFromNib
if let navigationController = viewController as? UINavigationController,
navigationController.viewControllers.contains(where: { $0 is MoreViewController }) {
moreView().frame.origin.y = 100
self.view.addSubview(moreView())
return false
} else {
moreView().removeFromSuperview()
return true
}
}
Finally I found the issue. This is the right way to add a UIView as a SubView controller of a UIViewController.
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if let navigationController = viewController as? UINavigationController,
navigationController.viewControllers.contains(where: { $0 is MoreViewController }) {
let mySubView : MoreView
mySubView = MoreView(frame: CGRect(x: 0, y: 0, width: 375, height: 667) )
self.view.addSubview(mySubView)
return false
} else {
return true
}
}
You might have copied the XIB and forgot to remove/add a connection with the IBOutlet. Please check.
It indicates that an already connected Interface Builder object is removed/renamed in its owner's source (File's Owner).
You may forgot to remove a connection with the IBOutlet. Please check on on show connection inspector.First click on file inspector of xib then click on show connection inspector. Shown in image.
Remove the broken outlets.

Xib file renders when called by my page view controller but not as a tab

I'm rendering a Xib file which is a subview in a view controller, the view controller is called by setViewController in a pageviewcontroller . It works great. I then placed the same Xib sub view in a view controller called by my tab view controller and it doesn't render.
To try and get to the bottom of this weird occurrence I have removed all code such that there is no class attached to the UIviewcontroller parent of the subview Xib in both cases. It is now a pure IB implementation of the Xib and the Xib classes are identical.
So in my comparison between the two implementations the only difference is one is opened from a page view controller and the other from a tab. I even copied the working view controller just so I knew they were identical.
Has anyone had this experience (where the same Xib doesn't render in one workflow compared to another) or have an idea as to why the two implementations cause different results??
Update: I took it one step further. Now there is absolutely no code. The only thing that is in the Xib is an unattached label. It only renders when the parent view is called from a page view controller! Wtf
Signin View Xib. (Works when instantiated from UIPageViewController:
SigninView.swift
class SigninView: UIView, GIDSignInUIDelegate, GIDSignInDelegate {
var view: UIView!
var nibName: String = "SigninView"
var delegate: SigninViewDelegate?
#IBOutlet weak var googleButton: GIDSignInButton!
#IBOutlet weak var signoutButton: UIButton!
override init(frame: CGRect) {
// properties
super.init(frame: frame)
// Set anything that uses the view or visible bounds
setup()
}
override func awakeFromNib() {
print("AWAKING!")
}
#IBAction func tapSignOut(sender: AnyObject) {
GIDSignIn.sharedInstance().signOut()
UserManager().logout()
self.updateDisplay()
}
required init?(coder aDecoder: NSCoder) {
// properties
super.init(coder: aDecoder)
// Setup
setup()
}
func setup() {
view = loadViewFromNib()
GIDSignIn.sharedInstance().uiDelegate = self
GIDSignIn.sharedInstance().delegate = self
view.frame = bounds
view.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
addSubview(view)
self.updateDisplay()
}
func updateDisplay() {
self.googleButton.layer.hidden = false
}
func loadViewFromNib() -> UIView {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: nibName, bundle: bundle)
let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
return view
}
func signIn(signIn: GIDSignIn!, presentViewController viewController: UIViewController!) {
//present vc on delegate
let delegateVC = self.delegate as! UIViewController
delegateVC.presentViewController(viewController, animated: true, completion: nil)
}
func signIn(signIn: GIDSignIn!, dismissViewController viewController: UIViewController!) {
print("Dismiss view controller")
let delegateVC = self.delegate as! UIViewController
delegateVC.dismissViewControllerAnimated(true, completion: nil)
self.updateDisplay()
}
func signIn(signIn: GIDSignIn!, didSignInForUser user: GIDGoogleUser!, withError error: NSError!) {
var success = false
if (user != nil) {
print("signed in? UID: \(user.userID), email: \(user.profile.email), name: \(user.profile.name), pic: \(user.profile.imageURLWithDimension(150))")
UserManager().createUser(user)
LocalDataStorage().saveContext()
success = true
} else {
print("User not signed in.")
}
self.updateDisplay()
if self.delegate != nil && self.delegate!.signInComplete != nil {
self.delegate!.signInComplete!(success)
}
}
func signIn(signIn: GIDSignIn!, didDisconnectWithUser user: GIDGoogleUser!, withError error: NSError!) {
print("disconnected")
}
}
Working UIViewController that contains working Signin Subview
Working call from UIPageViewController
let vc = UIStoryboard(name: "Intro", bundle: nil).instantiateViewControllerWithIdentifier("IntroPage2")
setViewControllers([getSlide(index)],direction: .Forward,animated: true,completion: nil)
UIViewController called from tab view that does not render signin subview
I am posting AN answer but really it's more of a work around. After hours of trying to finagle the views I get the code working consistently. To get it working created a new Xib and new VC file for the Signin module. I copied all the code from my original Signin class to the new one and it worked. No code was altered.
So if anyone comes across the gnarly painful situation give that a shot! This could very well be an XCode bug.