Swift 3 : Delegate within TapGestureRecognizer in Generics doesn't get called - swift

I have a protocol like so :
public protocol SubmitAgeDelegate : class {
func changeSubmitButtonBool()
}
The problem is I want to call it in a generics class.
open class GenericController<UICollectionViewCell,UICollectionReusableView> {
weak var submitAgeDelegate: SubmitAgeDelegate?
Within a UITapGestureRecognizer
func tapGestureDidRecognize(_ gesture: UITapGestureRecognizer) {
if let myAgeDelegate = self.submitAgeDelegate {
print("inside delegate") //Never gets inside
myAgeDelegate.changeSubmitButtonBool()
}
}
Not too sure why it never gets called? Similar ways have worked in regular classes withing IBAction functions.
In my other class :
open class MyCell: ActionCell, SubmitAgeDelegate {
weak var submitAgeDelegate: SubmitAgeDelegate?
public override init(frame: CGRect) {
super.init(frame: frame)
submitAgeDelegate = self
initialize()
}
// Delegate
public func changeSubmitButtonBool(){
print("called ")
}

You are never setting the submitAgeDelegate of the GenericController. Having a member of the same name in your MyCell class doesn't help.
You need to get a reference to your GenericController in order to set its delegate; there's no way around that. (This doesn't have anything to do with generics; it's the same for non-generic classes.) Since it looks like you're using it as a UICollectionViewCell, you might use the reference that you make in tableView:cellForRowAtIndexPath: or similar.

Related

How can I remove or disable some initialization from NSView class in my sub?

I want remove (frame: ) and (coder: ) initialization from my sub class coming from my NSView super class, I tried this code but I was unable to do it, how can I make my sub just be initialized with init()? I have to say I tried to use override but it seems cannot help me to reach my goal of having just init() as initialization.
class MyNSView: NSView {
convenience init() {
self.init()
}
}
No, you can't remove it.
init(frame: is the designated initializer of NSView
As convenience initializer you have to call it – on self, not on super
class MyNSView: NSView {
convenience init() {
self.init(frame: .zero)
}
}
However if the view is designed in Interface Builder then init(coder will be called.
Try using required keyword while implementing the init() method.
class MyNSView: NSView {
required init() {
super.init(frame: .zero)
}
}
You'll be able to initialize instances of your class by simply using
let myView = MyNSView()

Delegate Method is not called in UIButton class

I have a UIbutton class - from which I would like to call an 'adjust constraints' method after the user makes changes on the setting screen. I have created some protocols and all seems in order but it is not calling the method from the subview UIButton after the user closes the Setting Screen.
I have tried some of the other solutions here - that hasn't worked and I think it might be because I am using a UIButton class and I can't reinstantiate it, or call the instantiation? Either way, it never calls the method from the delegate.
Is using protocols the right way to solve this problem and if so, what am I missing?
Basically I have 3 files; the MainVC which I set as my first delegate (it gets triggered from my SettingScreenVC when user is done making changes to Setting Screen):
class MainVC: UIViewController, SettingScreenDelegate {
weak var numButtonDelegate: Buttons_Numeric?
func settingSetButtonConstraints() {
numButtonDelegate?.setupButtonConstraints()
}
}
Then in my Setting Screen I call the MainVC after the user made some changes to their settings:
class MainVC: SettingScreenVC {
weak var delegate: SettingScreenDelegate?
func closeSettings() {
delegate?.settingSetButtonConstraints()
}
}
Then in my Buttons_Numeric class I declare the function and the UIButton class delegate:
protocol numButtonDelegate: class {
func setupButtonConstraints()
}
class Buttons_Numeric: UIButton, numButtonDelegate {
weak var numButtonDelegate: Buttons_Numeric?
required init(coder aDecoder:NSCoder) { super.init(coder: aDecoder)!}
override init(frame:CGRect) {super.init(frame: frame)
self.numButtonDelegate = self
setupButtonConstraints()
}
override func awakeFromNib() {
self.numButtonDelegate = self
setupButtonConstraints()
}
func setupButtonConstraints() {
//SET UP CONSTRAINTS
}
}
Ok so couple of things you need to understand about delegates:
if you create a delegate, you need to conform to the delegate somewhere.
the conforming class should be assigned to the instance of the delegate.
With that in mind lets try to fix the code:
first the settings screen:
protocol SettingScreenDelegate: class {
func settingSetButtonConstraints()
}
class SettingScreenVC {
weak var delegate: SettingScreenDelegate?
func closeSettings() {
delegate?.settingSetButtonConstraints()
}
}
So far so good now the mainScreen should conform to the SettingScreenDelegate and be assigned to its delegate:
class MainVC: UIViewController, SettingScreenDelegate {
weak var button: Buttons_Numeric!
func openSettingsScreen() {
let settingsScreen = ... // the setting screen instanciation
settingsScreen.delegate = self // the MainVC
}
func settingSetButtonConstraints() {
self.button.setupButtonConstraints()
}
}
Now for the last step, the MainVC should have an instance of the button, then the only thing we need to do is call the function 'setupButtonConstraints' from the MainVC which means we do not need the delegate at the button.
class Buttons_Numeric: UIButton {
required init(coder aDecoder:NSCoder) { super.init(coder: aDecoder)!}
override init(frame:CGRect) {super.init(frame: frame)
setupButtonConstraints()
}
override func awakeFromNib() {
setupButtonConstraints()
}
func setupButtonConstraints() {
//SET UP CONSTRAINTS
}
}
You need to assign a value to the delegate variable. I would do it like this if the answer is always self
class Example: SomeDelegate {
lazy var someDelegate: SomeDelegate? = self
}
Otherwise you'll want to do it in the class' initializer or ViewDidLoad.

My delegate function is not being called in Swift

I have a main view titled NoteTakerViewController. I have a weatherGetterController class with a protocol that returns 5 days of weather with a protocol function called getMyWeather. However the protocol function is not being called that returns the weather data to NoteTakerViewController. I am certain I have everything set up correctly with the delegates but perhaps I do not.
This is really not a duplicate of Swift Delegate Not Being Called as the solution on that page did not work.
Any help you could provide would be great.
Here's the relevant code snippets:
My weatherGetterController class:
protocol WeatherGetterControllerDelegate {
func getMyWeather(weather: [FiveDayForecast])
}
class WeatherGetterController: UIViewController, CLLocationManagerDelegate {
var weatherGetterDelegate: WeatherGetterControllerDelegate?
And in the WeatherGetterController "getWeather" function call. The line
self.weatherGetterDelegate?.getMyWeather(weather: myForecast)
is not being called.
func getWeather() {
...
getNetWeather { (fetchedInfo) in
if let fetchedInfo2 = fetchedInfo {
//self.updateUI(mainWeather: fetchedInfo2)
//need to call delegate here
let myForecast = self.figureFive(weather: fetchedInfo2)
//return the forecast
print(myForecast)
self.weatherGetterDelegate?.getMyWeather(weather: myForecast)
}
}
Finally the function implementation in NoteTakerViewController:
class NoteTakerViewController: UIViewController, ..., UITextFieldDelegate, WeatherGetterControllerDelegate
func getMyWeather(weather: [FiveDayForecast]) {
print("get my weather")
print(weather)
}
Through debugging I can see that "weatherGetterDelegate" is set to nil and I don't know why.
Thanks
First you need to make WeatherGetterController a property in NoteTakerViewController or a local variable where you call it but I will use the first option.
class NoteTakerViewController: UIViewController, ..., WeatherGetterControllerDelegate {
var weatherGetterController: WeatherGetterController?
//...
func viewDidLoad() {
//....
weatherGetterController = WeatherGetterController()
weatherGetterController?.delegate = self
}
//And then in some other part of your code you do
func someFunc() {
self.weatherGetterController?.getWeather()
I am curious why WeatherGetterController is define to be a viewcontroller, is that really correct?
class WeatherGetterController: UIViewController, CLLocationManagerDelegate {
Personally I would remove that part
class WeatherGetterController: CLLocationManagerDelegate {
Put this in init of WeatherGetterController
public weak var weatherGetterDelegate: WeatherGetterControllerDelegate?
/* if you are not initializing it anywhere else
and if you are initializing it anywhere else then make sure you are
initializing WeatherGetterController there too and then put delegate
of WeatherGetterController to NoteTakerViewController object
else write the below code */
var model = NoteTakerViewController()
public override init() {
self. weatherGetterDelegate = model
}

Swift: Generic Protocol Cannot invoke with an argument list of type

Trying to create a generic protocol with associatedtype.
I get an error when I try to access a method from the delegate:
Cannot invoke 'numberOfSections' with an argument list of type '(containerView: UITableView)'
Code:
protocol ViewDelegate: class {
associatedtype ContainerView
associatedtype Model
func numberOfSections(containerView: ContainerView)
func aMethodThatTakesNoArugments()
}
class ViewController: UIViewController {
var newView = AnyView<ViewController>()
override func viewDidLoad() {
super.viewDidLoad()
newView.delegate = self
}
}
extension ViewController: ViewDelegate {
typealias ContainerView = UITableView
typealias Model = Int
func numberOfSections(containerView: ContainerView) {
// do something with containerView
}
func aMethodThatTakesNoArugments() {}
}
class AnyView<Delegate: ViewDelegate>: UIView {
weak var delegate: Delegate?
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func getData() {
delegate?.aMethodThatTakesNoArugments() // This compiles fine
delegate?.numberOfSections(containerView: UITableView()) // Get a compiler error on this line (I am passing an argument):
// Cannot invoke 'numberOfSections' with an argument list of type '(containerView: UITableView)'
}
}
I have a feeling I am missing something. Method that takes no arguments compiles fine; however if I call a method that does take an arugment, I get a compile error.
Your error is due to the compiler not being able to tell what Type ContainerView is supposed to be.
You're only defining it for ViewController, but the Delegate could be literally any class or struct, not just ViewController.
There are a number of ways to fix this, but it's unclear what exactly you're trying to accomplish here, so I'll just give a couple examples:
as #OOPer mentioned, you could constraint your Delegate generic to force conformance to UITableView:
class AnyView<Delegate: ViewDelegate>: UIView where Delegate.ContainerView == UITableView
A similar option would be to simply define the protocol with the desired type:
protocol ViewDelegate: class {
func numberOfSections(containerView: ContainerView)
func aMethodThatTakesNoArugments()
}
If you need more flexibility, another option would be to add another generic Type:
class AnyView<Delegate: ViewDelegate, ContainerViewType>: UIView where Delegate.ContainerView == ContainerViewType

Delegation on a class in Swift

I have a delegation/initialization problem I can't seem to solve. Basically I have a storyboard with a few View controllers. Inside the storyboard there is this "View controller" which consists of a UITableview that I have connected with a DeviceListViewController class so that it populates the information. In here I have declared the following protocol:
protocol DeviceListViewControllerDelegate: UIAlertViewDelegate {
var connectionMode:ConnectionMode { get }
func connectPeripheral(peripheral:CBPeripheral, mode:ConnectionMode)
func stopScan()
func startScan()
}
and inside the class itself I have a init method like this (which is probably wrong but I didn't know what else I could do at this point):
convenience init(aDelegate: DeviceListViewControllerDelegate) {
self.init()
self.delegate = aDelegate
}
Then there is this second class that is not attached to any view controller called BLEMainViewController. It should be a singleton handling all the bluetooth actions. This means I should be able to delegate some stuff between DevicelistViewController and BLEMainViewController.
In the BLEMainViewController I have inherited the DeviceListViewControllerDelegate:
class BLEMainViewController: NSObject, DeviceListViewControllerDelegate {
var deviceListViewController:DeviceListViewController!
var delegate: BLEMainViewControllerDelegate?
static let sharedInstance = BLEMainViewController()
}
override init() {
super.init()
// deviceListViewController.delegate = self
deviceListViewController = DeviceListViewController(aDelegate: self)
}
The problem is that BLEMainViewController is not attached to any View Controller (and it shouldn't IMO) but it needs to be initialized as a singleton in order to handle all the BLE actions. Can anyone point me in the right direction (with an example preferably) on how to work around this?
I think you simply used wrong code architecture.
The BLEManager is a shared-instance, you can call it from everywhere, set it properties, and call its methods.
Its can delegate your view-controller with any predefine events you will add to its protocol and provide proper implementation
Here is some code, hope it helps
protocol BLEManagerDelegate{
func bleManagerDidStartScan(manager : BLEManager)
}
class BLEManager: NSObject {
static let sharedInstance = BLEManager()
var delegate: BLEManagerDelegate?
var devices : [AnyObject] = []
func startScan(){
delegate?.bleManagerDidStartScan(self)
//do what ever
}
func stopScan(){
}
}