I have this problem:
Im having a custom class named CoredataAction
In this class I do all my CoreData actions and it is not an UIViewController.
How can I open a view from my CoreDataAction class?
I have tryied opening a storyboard but did didn't work! It got me an bad_access error
One solution would be to add a variable in your CoredataAction class that holds the initial ViewController, just make sure you set that variable when you initialise your CoredataAction class.
CoredataAction
class CoredataAction {
var parentViewController:UIViewController!
func presentNewViewController() {
let newViewController = parentViewController.storyboard?.instantiateViewControllerWithIdentifier("YOUR STORYBOARD ID") as UIViewController
parentViewController.presentViewController(newViewController, animated: true, completion: nil)
}
}
ViewController
func initCustomClass() {
var coreData = CoredataAction()
coreData.parentViewController = self
}
Another option is to use a protocol to delegate the view presentation back to the ViewController class itself. It would be a very similar setup to the above, it just means the view presentation logic can be kept out of your CoredataAction customClass - Let me know if you would like an example of this.
Related
I have worked with delegate pattern for passing data in the past but that was one-to-one sort of interaction like say I need to pass data back from ViewController B to ViewController A and I set the delegate property defined in B from inside A. Usually we need this kind of delegation.
But I have certain condition where I need to set the delegate property from inside the third, not a ViewController, but a class
Here's how it is laid out -
protocol DataPassingDelegate {
func reloadData()
}
class ButtonView: UIButton {
// Some function that decide which ViewController is to be displayed
func destinationVCDecider() {
// parentController fetched the ViewController in which the button is laid out
let destinationVCObject = self.parentController.storyboard?.instantiateViewController(withIdentifier: Constants.STORYBOARD_IDENTIFIER.JOB_DETAILS_VIEW_CONTROLLER) as! JobDetailsViewController
// Setup for passing data via delegate
let jobsVCObject = JobsViewController()
destinationVCObject.delegate = jobsVCObject
// Displaying the Details of the job
parentController.navigationController?.pushViewController(destinationVCObject, animated: true)
}
}
class JobsViewController: UIViewController,DataPassingDelegate {
func reloadData() {
// Reload the jobs from the server
}
}
class JobDetailsViewController: UIViewController {
weak var delegate: DataPassingDelegate?
func navigateBack() {
delegate?.reloadData()
}
}
navigateBack() inside JobDetailsViewController will be called when certain event has been triggered
Now, when the navigateBack() is called, the delegate property turns out to be nil
Earlier I used to assign self in cases where there was one-to-one interaction but here there are a few classes between them that I don't want to pass them all around
Your approach here is correct. You need to debug it. Create your JobsViewController's instance like this-
let vc = UIStoryboard(name: "Name", bundle: nil).instantiateViewController(identifier: "ViewID") as JobsViewController.
You can debug whether delegate instance is being passed or not by putting a breakpoint in ViewDidLoad method of JobDetailsViewController.
Another approach you can follow is to use NotificationCenter
Im new to programming and trying to build my own app, I wonder how Im I supposed to link the info I get from the addTask viewcontroller to the tableview cell? At the moment Im just trying to get the text from the textfield and Im going to add the other features later.
What Im trying to do
Refer This :-
Create a global array add remove element from that array on click of your button
You can pass data from one view controller to another using Delegates. Check my ans here. You can set your table view class as delegate of your task view controller. Implement the protocol methods of task view controller get the data and reload table.
Hope it helps.
Happyy Coding!!
You can pass data using Delegation .
In Second ViewController
import UIKit
protocol secondViewDelegate: class {
func passData(arrData : [Any])
}
class SecondViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
weak var delegate: secondViewDelegate? = nil
#IBAction func clickOnButton(_ sender: Any) {
self.delegate.passData([]) // replace your array here
}
}
In FirstViewController
class FirstViewController: UIViewController, UITableViewDataSource, secondViewDelegate
let objectSecondVC: SecondViewController? = storyboard?.instantiateViewController(withIdentifier: "secondVCID") as! SecondViewController?
objectSecondVC?.delegate = self
navigationController?.pushViewController(objectSecondVC?, animated: true)
Second ViewController Delegate Method in FirstViewController
func passData(arrData : [Any]){
// append to your main array
}
It seems like your add task view controller is connected with your table view controller though a segue. So when you moving back from add task view controller, you can use unwind to pass data back. Here is a detailed tutorial with simple instructions and pictures.
Ok, Ive tried the usual methods here but can't figure out this relatively simple issue -
I have a view controller that I present here:
self.presentViewController((self.storyboard?.instantiateViewControllerWithIdentifier("createEvent"))!, animated: true, completion: nil)
And I need to call a function in my original main VC from this createEvent VC. I have tried putting:
weak var superv: MainViewController!
in the create event class then doing something like this:
let create = self.storyboard?.instantiateViewControllerWithIdentifier("createEvent")
create.superv = self //error here
Then in create doing:
superv.updateThings()
But I get an error trying to tie the presented VC to my MainViewController. What am I doing wrong here?
I have seen use of protocols but I would like to avoid that. What is the simplest way to do this?
This is what I did:
In main:
var create = UIViewController()
create = (self.storyboard?.instantiateViewControllerWithIdentifier("createEvent"))!
create.delegate = self //error here
In create:
weak var delegate: CreateEventDelegate!
protocol CreateEventDelegate: class {
func doSomeFunction ()
}
And the error is value of type uiviewcontroller has no member delegate
The function in main I need to call is:
self.tableView.reloadData()
Error:
Use protocols. I know you said you don't want to but its so simple and convenient.
In your createEvent vc:
weak var delegate: CreateEventDelegate!
Then at the bottom of the file (outside the create event VC class)
protocol CreateEventDelegate: class {
func doSomeFunction ()
}
Then in the main VC class conform to the CreateEventDelegate protocol and add this:
create.delegate = self
Then you can call delegate.doSomeFunction() in your create event VC
A portion of my app has an embedded master-detail section. Each detail view is using a custom UIViewController. When I change the value of something inside one of these UIViewControllers I need to be able to grey out one of the table rows in the master UITableViewController.
The closest I have seen to a solution is to use NSNotificationCenter to bubble up any changes, though this feels a little untidy..
Another solution is to use delegates? But I haven't come across any example solutions or tutorials in how to use this in Swift?
I've also experimented just trying to access the table view by navigating back up the hierarchy:
let navController = self.splitViewController!.viewControllers[0];
navController.tableView.reloadData()
I know the example above is wrong, but I don't know how to access the master view that way, or even if it is the right approach.
Oh, I am trying to call reloadData() because in the master view there is some logic which checks the condition as to wether to grey out a table row is applicable (i'm using Core Data)
I've seen that you figured this one out already. However a cleaner and more future proof way would be to use a delegate protocol:
protocol DetailViewControllerDelegate: class {
func reloadTableView()
}
Then add a delegate property to your DetailViewController class and implement the call to the delegate:
class DetailViewController: UIViewController {
weak var delegate: DetailViewControllerDelegate?
....
func reloadMasterTableView() {
delegate?.reloadTableView()
}
}
And then in your MainViewController implement the delegate method:
extension MainViewController: DetailViewControllerDelegate {
func reloadTableView() {
tableView.reloadData()
}
}
Don't forget to set the delegate on your DetailViewController instances when you create them:
let detailViewController = DetailViewController()
detailViewController.delegate = self
I would suggest you use NSNotificationCenter .
If you want to to do it via Navigation controller here is to code should work for you in swift.
let navController: UINavigationController = self.splitViewController!.viewControllers[0] as! UINavigationController
let controller: MasterViewController = navController.topViewController as! MasterViewController
controller.tableView.reloadData()
Since I was able to access my viewController, I was able to access the parent viewcontroller like so:
func reloadMasterTableView(){
let navVC: UINavigationController = self.splitViewController!.viewControllers[0] as! UINavigationController
let sectionsVC : UIMasterViewController = navVC.topViewController as! UIMasterViewController
sectionsVC.tableView.reloadData()
}
I have a UIViewController-class instantiated via Storyboard that contains a constant property. For testing, I want to replace/mock whatever the value of the view controller.
I can actually do this by subclassing and defining a new constant and by overriding the methods that use it. However, I do not know how to instantiate the ViewController, since it's not in the storyboard.
It's important that all views and all other functionality of the original ViewController is still present, of course. How to go about it?
If i understand you need to access a property from another ViewController outside your Storyboard without presenting it. Since you're using swift, all you need to do is instantiate the class itself i believe. For example if the ViewController that is not in the storyboard has a class named "SecondController", and the variable inside second controller is called "stringVar" then all you need to do is this:
var secondVC = SecondController()
secondVC.stringVar = "new string value"
Example:
//SecondVC
import UIKit
class SecondViewController: UIViewController {
var something:String! = "String Value";
}
//Main VC
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var secondVC = SecondViewController()
secondVC.something = "Another String Value"
println(secondVC.something)
}
}