Updating uitableview datasource and updating tabbar - ios

I need your advice.
I have a screen with a table view and I'm using a separate file for UITableViewDataSource.
What I need is to be able to access the UITabBarItem inside my UITableViewDataSource (because based on the action on my tableview, I will update my tableview data, so I need to change something on my tabbar)
Any idea ?
Thanks.
To separate my datasource, in my controller I have:
var toPayDatasource: MyDataSource!
....
tableView.dataSource = mDatasource
tableView.delegate = myDatasource
And my datasource:
class MyDataSource: NSObject, UITableViewDataSource, UITableViewDelegate {
...
}
C.C.

One common mechanism for sending a message between two objects that are otherwise far apart is to use NSNotificationCenter. You can define a custom event and pass along whatever you need to update the tab bar item in the userInfo dictionary.

Since your datasource is separate you can create a Delegate for the view controller and pass it to the data source. Something like the following (right after setting data source for the tableView):
mDataSource.tabDelegate = self;
And declare / define the delegate the following way:
// protocol
protocol TabChangerProtocol {
// function signatures here
}
// data source
class MyDataSource : /* ... */ {
var tabDelegate : TabChangerProtocol!;
// rest here
}
// view controller
class ViewController : TabChangerProtocol, /* ... */ {
// ...
}
That way you can call the protocol functions from inside MyDataSource.
P.S Sorry for all the 3 dots. Typing code on mobile is annoying.

Related

How can I create an instance of a custom model with multiple viewcontrollers in Xcode with Swift 4?

I'm new to Swift and I'm sure this question is pretty basic and has been asked and answered before.
I am not using storyBoard. My main viewController is created from AppDelegate via code.
I have:
a custom class defined in a model.swift file
a main viewController (from AppDelegate) that I am using as a container
3 additional viewcontrollers as subviews of the main (not each other)
all 3 subviews are displayed simultaneously each covering 1/3 of the screen (no segues)
each viewcontroller is in a separate .swift file
I want to create an instance of my custom class in the main viewController and have all 3 of the subviews be able to reference that instance.
Each of the subview view controllers need to be able to get/set instance variables and the other subviews need to be made aware of those changes.
I think I will need to use notifications to communicate the changes to the multiple subviews - but I haven't even begun to try and figure that out yet.
If this has been asked and answered before - could someone please either provide a link - or provide me with the right search terms so that I'm able to find the answer? The only found answers I've found that come close are to use segues to pass the data back and forth.
You can use delegate pattern. Below code is assuming that you are using MVVM pattern. (It is very similar for VIPER/ReSwift patterns also)
protocol DataChangedDelegate {
func refreshData()
}
// ViewModel for FirstViewController
class FirstViewModel {
var delegate: DataChangedDelegate?
var data: Any {
didSet {
delegate?.refreshData()
}
}
//rest of the things
}
//similarly other two view models will have a delegate and on data change will call the refresh method
And your view controllers should adopt this protocol
class FirstViewController: UIViewController, DataChangedDelegate {
//view controller code
//delegate code
func refreshDate() {
//tableView.reloadDate()
//collectionView.reloadDate()
//lableView.text = viewModel.data()
}
}
And where ever you create a viewControllers and add as subView, you have to set the delegate of viewModel.
let firstViewController: FirstViewController = createFirstViewController()
let firstViewModel = FirstViewModel()
firstViewModel.delegate = firstViewController
firstViewController.viewModel = firstViewModel
mainViewController.addSubView(firstViewController.view)
Similarly for all other view controllers.
Here's how I would do it:
Create a singleton class.
Configure the singleton's properties in the the main ViewController.
Use didSet to post a Notification.
Add a listener for that Notification in your additional ViewControllers.

iOS , Handle tableview property globally

I'm using tableview in all classes of my project. I just want to remove some default property like table bouncing to all tableview. Instead of remove it in each and every class, is there any option to write single line code that reflects for tableview in all class?
You can use Extension like this.
extension UITableView{
func setTableViewBasicProperties(){
self.backgroundColor = UIColor.gray
//tableview's other propeties
}
}
and simply call method into your ViewController:
yourtableView.setTableViewBasicProperties()
You can extend UITableView class and modify the properties as well as add some methods for added functionality.Extensions add new functionality to an existing class, structure, enumeration, or protocol type. This includes the ability to extend types for which you do not have access to the original source code.
You can extend UITableView as
extension UITableView{
func configureTableView(){
self.alwaysBounceVertical = NO;
//modify other propeties of UITable View
}
}
Now you can set these properties to each of tableview in any class as
self.yourtableView.configureTableView()

Passing data from tableview cell to View Controller Swift 2.1

Anyone know why can't I access the variable 'sendTitle' in prepareForSegue from didSelectRowAtIndexPath? I saw some of the tutorials, they are doing the same thing with me, I've no idea why mine got error.
--What I'm doing now is passing value from tableView cell to another view controller.
I'm using Xcode 7 Swift 2.1
you have to declare sendTitle inside your class to make it visible to all methods. Something like follows.
import UIKit
class viewController: UITableViewController {
var sendTitle:String = ""
override func viewDidLoad() {
super.viewDidLoad()
}
//table view delegate methods
// just use sendTitle = cell.lblTitle.text!
}
Because it is declared privately in your didSelectRowAtIndexPath method. It won't be accessible outside of those function. if you want to access it from another function, declare it as global variable in your view controller.

Swift, how to tell a controller that another controller is its delegate

I'm learning Swift and I'm studying the delegation pattern.
I think I understand exactly what is delegation and how it works, but I have a question.
I have a situation where Controller A is the delegate for Controller B.
In controller B I define a delegate protocol.
In controller B I set a variable delegate (optional)
In controller B I send message when something happens to the delegate
Controller A must adopt method of my protocol to become a delegate
I cannot understand if every delegate controller (in this case A) listens for messages sent by controller B or If I have to tell to controller B that A is now his delegate.
I notice that someone use this code (in controller A)
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "Example" {
let navigationController = segue.destinationViewController as UINavigationController
let controller = navigationController.topViewController as AddItemViewController
controller.delegate = self
}
}
Is this the only way to tell a delegator who is his delegate?
I believe, you need to tell a deligator who is its delegate upon creation of that it. Now, the delegator can be created programatically or through storyboard. So, based on that you have two options, you can tell it who is its delegator programatically like you showed in the code or from IB.
The key here is upon creation. Let's me explain myself. Take the case of a UIView. Say, you want a Custom UIView object(CustomView). So, you drag and drop a UIView in your View Controller and in the identity inspector, you assign its class as of your CustomView's class. So, basically, as soon as the controller is created, your custom view will also be created. Now, you can either say it that the View Controller in which it is created is its delegate or You can go to the IB and connect the view's delegate to the View Controller.
Now, let's assume that you wanted the custom view to be created in your ViewController programatically. In that case, you would probably call the -initWithFrame: method to create the view and upon creation you tell that delegator that who is its delegate like-
myCustomView.delegate = self;
same goes with a View Controller.
controller.delegate = self;
So, basically to tell a delegator who is its delegate, you first need that delegator to be created. At least, that's what I think.
I think one of the best example of delegation is UITableView.
Whenever you want the control of various properties of a tableView e.g. rowHeight etc, you set your controller to be the delegate of your tableview. To set the delegate of your tableView you need to have tableView created obviously as pointed out by #natasha.
So in your case, you can set delegate of your delegator when you create it or when you find a need for the controller to be delegate of your delegator but you definitely need your delegator to be present to set its property.
You can set your controller as delegate at any time when you require control.
I'm sure you want your UIViewController to act like described, but here is a simpler example how to use the delegation pattern with custom classes:
protocol ControllerBDelegate: class {
func somethingHappendInControllerB(value: String)
/* not optional here and passes a value from B to A*/
/* forces you to implement the function */
}
class ControllerB {
var delegate: ControllerBDelegate?
private func someFunctionThatDoSomethingWhenThisControllerIsAlive() {
/* did some magic here and now I want to tell it to my delegate */
self.delegate?.somethingHappendInControllerB(value: "hey there, I'm a magician")
}
func doSomething() {
/* do something here */
self.someFunctionThatDoSomethingWhenThisControllerIsAlive()
/* call the function so the magic can really happen in this example */
}
}
class ControllerA: ControllerBDelegate {
let controllerB = ControllerB()
init() {
self.controllerB.delegate = self /* lets say we add here our delegate*/
self.controllerB.doSomething() /* tell your controller B to do something */
}
func somethingHappendInControllerB(value: String) {
print(value) /* should print "hey there, I'm a magician" */
}
}
I wrote the code from my mind and not testet it yet, but you should get the idea how to use such a pattern.

Accessing uibutton action from a different class Swift

I have an UITableView that is loaded from two custom cell xib files.
The second one contains an UIButton.
But since i've added the custom class for xib - it has its own actions and functions, which i cannot access from ViewController.
My goal is to apply some action on UIButton when the custom cell is loaded in the tableview.
My function is defined in ViewController (because all variables are there) and my UIButton action is defined in Custom class for xib.
How do i connect one to another?
Thank you
Here is the solution in swift
If you want to perform action in another class when an event takes place in another class, then you have to use Protocols in your code, so that you can perform the action in another class.
For example
Declare your protocol like this before the class interface
protocol MyDelegateClass {
func btnAction()
}
Define your protocol in the interface of your class like this
var MyDelegateClass! = nil
Now on your button action trigger the protocol like this
#IBAction func btnProtocolAction(sender: AnyObject) {
[delegate btnAction];
}
Now include the protocol in the class like this
class myActionClass: UIViewController, PopUpViewDelegate {
Now assign the protocol to the MyDelegateClass object like this
myProtocolObject.delegate=self
Also define the class which you have declared in MyDelegateClass like
func btnAction() {
print(#"This method will triggered");
}
Hope this helps you.
You can achieve this by simply posting a notification.
NSNotificationCenter.defaultCenter().postNotificationName("buttonClickedNotification", object: nil)
Post this notification from your button method in custom class. You can also pass any data by using object parameter (Here it is nil).
And observe the notification in your viewController.
NSNotificationCenter.defaultCenter().addObserver(self, selector: "buttonClicked:", name: "buttonClickedNotification", object: nil)
And implement buttonClicked() method in your viewController.
func buttonClicked(data: NSNotification)
{
//If any data is passed get it using
let receivedData:NSDictionary = data.object as! NSDictionary //If data is of NSDictionary type.
}
Write a delegate method. This will connect your ViewController and Custom Class. What have you tried already?

Resources