Accessing value from one class using protocol in other class IOS swift - ios

Hello I am trying to access the variables and function from the class which is following one protocol ios swift in other class please let me know what i am doing wrong.
First image is of protocol and class which is declaring variables and functions and second image is of accessing the protocol, force unwrapping it and accessing values,functions.
code of protocol and first class
import Foundation
import CoreLocation
import UIKit
import Contacts
protocol FilterSessionPresenter: class {
var numberOfSection: Int {get}
func viewLoaded()
func filterTapped()
}
class FilterSessionPresenterImplementation : FilterSessionPresenter {
init() {
print("runnninggg...")
}
func viewLoaded() {
print("Hello")}
func filterTapped() {
print("Hello")}
var numberOfSection: Int {
return 200}
}
code for accessing class
import UIKit
class FilterSessionVC: UIViewController {
var presenter : FilterSessionPresenter!
override func viewDidLoad() {
print(presenter.numberOfSection)
}
}

Related

Using delegates and RxCocoa shows Argument of '#selector' refers to instance that is not exposed to Objective-C

I want to have this delete to be reactive with RxCcocoa and RxSwift using DelegateProxy. I am getting this error:
Argument of '#selector' refers to instance method
'rangeSeekSlider(_:didChange:maxValue:)' that is not exposed to
Objective-C
The delegate I am converting from this library: https://github.com/WorldDownTown/RangeSeekSlider/blob/master/Sources/RangeSeekSliderDelegate.swift
import CoreGraphics
public protocol RangeSeekSliderDelegate: class {
/// Called when the RangeSeekSlider values are changed
///
/// - Parameters:
/// - slider: RangeSeekSlider
/// - minValue: minimum value
/// - maxValue: maximum value
func rangeSeekSlider(_ slider: RangeSeekSlider, didChange minValue: CGFloat, maxValue: CGFloat)
...
}
And here is the the delegate proxy
import RxSwift
import RxCocoa
import RangeSeekSlider
final class RxRangeSeekSliderDelegateProxy:
DelegateProxy<RangeSeekSlider, RangeSeekSliderDelegate>,
RangeSeekSliderDelegate,
DelegateProxyType {
init(rangeSeekSlider: RangeSeekSlider) {
super.init(parentObject: rangeSeekSlider, delegateProxy: RxRangeSeekSliderDelegateProxy.self)
}
static func registerKnownImplementations() {
register { RxRangeSeekSliderDelegateProxy(rangeSeekSlider: $0) }
}
static func currentDelegate(for object: RangeSeekSlider) -> RangeSeekSliderDelegate? {
return object.delegate
}
static func setCurrentDelegate(_ delegate: RangeSeekSliderDelegate?, to object: RangeSeekSlider) {
object.delegate = delegate
}
}
The reactive extension of the slider, this is where I get the error:
import RxSwift
import RxCocoa
import RangeSeekSlider
extension Reactive where Base: RangeSeekSlider {
var delegate: DelegateProxy<RangeSeekSlider, RangeSeekSliderDelegate> {
return RxRangeSeekSliderDelegateProxy.proxy(for: base)
}
var didChange: Observable<(Bool, Bool)> {
let source = delegate.methodInvoked(#selector(RangeSeekSliderDelegate.rangeSeekSlider(_:didChange:maxValue:)))
.map{ (parameters) in
return (parameters[0] as? Bool ?? false, parameters[1] as? Bool ?? false)
}
return source
}
}
The protocol itself needs to be exposed to Objective-C.
Change
public protocol RangeSeekSliderDelegate: class {
to
#objc public protocol RangeSeekSliderDelegate {

Trying to subclass GADRewardBasedVideoAdDelegate on Swift

I am trying to create a singleton class, subclass of GADRewardBasedVideoAdDelegate. Something like this:
import Foundation
import GoogleMobileAds
class MyAdsManager : GADRewardBasedVideoAdDelegate {
private let id : String = "MY_ADMOB_ID"
private var selector : (()->Void)?
static let instance: MyAdsManager = {
return MyAdsManager()
}()
class func getInstance() -> MyAdsManager {
return instance
}
private init() {
loadVideo()
}
//more methods
}
The error message is:
Type 'MyAdsManager' does not conform to protocol 'NSObjectProtocol'
I am not sure if I am doing this correctly, but implementing NSObjectProtocol is not something I am looking for...
Thank you in advance people.
Replace
class MyAdsManager : GADRewardBasedVideoAdDelegate
with
class MyAdsManager : NSObject, GADRewardBasedVideoAdDelegate
Reason
GADRewardBasedVideoAdDelegate inherits from NSObjectProtocol so you have to implement all methods listed in NSObjectProtocol and since these methods are implemented inside NSObject subclasses so it does the job for you

Duplicate codes in Controller

I am currently working on one project. It may potentially have duplicated codes in multiple controllers like below.
Controller A
class A: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
// about 50~70 lines of codes
#IBAction func scanButtonTapped {
// used self (as AVCaptureMetadataOutputObjectsDelegate)
// used view
// called presentViewController(...), which is a func in UIViewController
}
}
Controller B
class B: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
#IBAction func scanButtonTapped {
// will need same logic as in Controller A
}
}
My current solution is have another class C, and move the duplicated codes into it. However, if I do so, controller can cast to AVCaptureMetadataOutputObjectsDelegate, but not to UIViewController.
class C {
func btnTapped (view: UIView, controller: AnyClass) {
// logic is here
// controller can cast to AVCaptureMetadataOutputObjectsDelegate
// but controller cannot cast to UIViewController
}
}
so A and B will have
class A {
#IBAction func scanButtonTapped {
let c = C()
c.btnTapped(view, self)
}
}
My question is if it is possible to cast controller into UIViewController. OR is there another way to refactor the codes properly?
What about extend AVCaptureMetadataOutputObjectsDelegate protocol and create default implementation by protocol extension (POP approach)?
protocol ScanButtonClickable: AVCaptureMetadataOutputObjectsDelegate {
func btnTapped() // this line is optional
}
extension Clickable where Self: UIViewController {
func btnTapped() {
// logic is here
}
}
class A: UIViewController, ButtonClickable {
...
}
class B: UIViewController, ButtonClickable {
...
}
Try this:
//declare your default method to be used across classes
protocol MyProtocol {
func myFunc()
}
//provide the implementation of your default behavior here in myFunc()
extension MyProtocol {
func myFunc() {
print("Default behavior")
}
}
class A: MyProtocol {
}
class B: MyProtocol {
}
let a = A()
a.myFunc()
let b = B()
b.myFunc()
//prints
Default behavior
Default behavior

how to inject a delegate in swift using typhoon?

Using typhoon I'm trying to inject the type of "worker" in my view controller. my "Worker" requires a delegate so that when the work is done, it calls this method. I need to set my view controller to be the delegate of the worker class that was injected. in other words a circular dependency.
Updated question with source:
//my typhoon assembly class
import Typhoon
class Assembly : TyphoonAssembly {
public dynamic func viewController() -> AnyObject {
return TyphoonDefinition.withClass(ViewController.self) {
(definition) in
definition.injectProperty("worker", with: self.foo())
definition.scope = TyphoonScope.Singleton
}
}
public dynamic func foo() -> AnyObject {
return TyphoonDefinition.withClass(Foo.self) {
(definition) in
definition.injectProperty("delegate", with: self.viewController())
}
}
}
Foo is where the work done, it implements WorkHandler protocol and has a delegate of type SomeProtocol to call when work has finished:
import Foundation
#objc
protocol SomeProtocol: class {
optional func hasFinishedWork(value: Bool)
}
protocol WorkHandler : class {
func doSomething()
}
class Foo: WorkHandler{
//how will this get set?
var delegate:SomeProtocol?
func doSomething(){
print("doing the work")
delegate?.hasFinishedWork!(true)
}
}
And my ViewController conforms to SomeProtocol like so:
import UIKit
class ViewController: UIViewController, SomeProtocol{
var worker:WorkHandler?
override func viewDidLoad() {
super.viewDidLoad()
worker?.doSomething();
}
#objc func hasFinishedWork(value: Bool){
print("The work was all done")
}
}
above code gives the following error when it runs:
2016-02-29 20:25:43.250 TestApp[30604:5316415] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Subclass of NSProxy or NSObject is required.'
Is anyone able to help with this?
Turns out i had to make my protocol to inherit from NSObject:
#objc
protocol SomeProtocol: class {
optional func hasFinishedWork(value: Bool)
}
#objc
protocol WorkHandler : class {
func doSomething()
}
class Foo: NSObject, WorkHandler{
//how will this get set?
var delegate:SomeProtocol?
#objc func doSomething(){
print("doing the work")
delegate?.hasFinishedWork!(true)
}
}
Now it works as expected.

Swift delegate does not inherit NSObject

I am trying to implement some sort of delegate broadcaster (Observer Pattern) in Swift to register multiple delegates. To use the "isEqual" function I need the generic to inherit from NSObject
To avoid duplicate code I prepared a generic DelegateBroadcaster:
import UIKit
class DelegateBroadcaster<T : NSObject>: NSObject {
var delegates : [T]
override init() {
delegates = []
}
func addDelegate(newDelegate : T) {
delegates.append(newDelegate)
}
func removeDelegate(oldDelegate : T) {
for i in 0...delegates.count-1 {
if (oldDelegate.isEqual(delegates[i])) {
delegates.removeAtIndex(i)
break
}
}
}
}
and subclass this for any specific broadcaster.
import UIKit
class NavigationControllerBroadcaster : DelegateBroadcaster<UINavigationControllerDelegate> {
}
But I get a strange error: "DelegateBroadcaster requires that 'UINavigationControllerDelegate' inherit from NSObject"
This is strange because the class reference by apple (Class Reference) says that UINavigationControllerDelegate inherits from NSObject.
So why do I get an error?
You are confusing class NSObject (NSObject class) and protocol NSObject (NSObject protocol, in Swift called NSObjectProtocol).
UINavigationControllerDelegate is a protocol and cannot inherit from class NSObject, it inherits from NSObjectProtocol (switch your documentation to Swift, you will see the difference).
UINavigationControllerDelegate is not a concrete type, it is a Protocol and therefore cannot be used as the type signature for the DelegateBroadcaster

Resources