Non-generic Swift class can implement UIPickerViewDataSource but Generic version can't - xcode

Swift 1.2 / Xcode 6.3.
Why is this valid:
class RangeDelegateNongeneric: NSObject, UIPickerViewDataSource {
var values = [Int]()
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return values.count
}
}
but this isn't:
class RangeDelegateGeneric<T>: NSObject, UIPickerViewDataSource {
var values = [T]()
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return values.count
}
}
Error: Type RangeDelegateGeneric<T> does not conform to protocol UIPickerViewDataSource
Even more oddly, the Fix-it message: Candidate is not #objc, but protocol requires it prepends #objc to the beginning of each function, but that doesn't Fix-it, and the Fix-it tool is happy to repeatedly prepend #objc!

This is fixed in Swift 2.0, specifically tested in Xcode 7 (beta 5 as of this writing).
99% sure this blog fragment explains it, although a more compiler-nerd-friendly explicit spec statement is bizarrely difficult to find:
https://developer.apple.com/swift/blog/?id=29
[Emphasis mine]
Swift-er SDKs: Swift 2 works even better with the Apple SDKs, thanks
in part to two new features in Objective-C: nullability annotations
and generics. The SDKs have been updated to annotate API that cannot
return nil so you don’t need to use optionals as often. And with a
true generics system employed by the SDKs you can more often preserve
detailed type information in your Swift 2 code.

Related

Error with NSTreeController - this class is not key value coding-compliant for the key

I am new to Swift and trying to learn how to implement NSTreeController with NSOutlineView. I've been following several guides which shows such examples, but I keep getting an error. I followed step by step and/or try to run their source codes if available, but I was getting same error. I come to think there is some change in Swift 4 which makes these Swift 3 examples to produce error. As there are not many examples done in Swift 4, I decided I'd give a try by asking the question here.
The error I'm getting is:
this class is not key value coding-compliant for the key isLeaf.
I believe that error is coming from the key path set up for NSTreeController:
However I am not sure what needs to be done to fix the error.
I have simple model class called Year.
class Year: NSObject {
var name: String
init(name: String) {
self.name = name
}
func isLeaf() -> Bool {
return true
}
}
My view controller looks like this.
class ViewController: NSViewController, NSOutlineViewDataSource, NSOutlineViewDelegate {
#IBOutlet weak var outlineView: NSOutlineView!
#IBOutlet var treeController: NSTreeController!
override func viewDidLoad() {
super.viewDidLoad()
addData()
outlineView.delegate = self
outlineView.dataSource = self
}
func addData() {
let root = ["name": "Year", "isLeaf": false] as [String : Any]
let dict: NSMutableDictionary = NSMutableDictionary(dictionary: root)
dict.setObject([Year(name: "1999"), Year(name: "2000")], forKey: "children" as NSCopying)
treeController.addObject(dict)
}
func isHeader(item: Any) -> Bool {
if let item = item as? NSTreeNode {
return !(item.representedObject is Year)
} else {
return !(item is Year)
}
}
func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
if isHeader(item: item) {
return outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "HeaderCell"), owner: self)!
} else {
return outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "DataCell"), owner: self)!
}
}
}
When I run the program, it causes no issue, but when I expand the node to show the two children of the root, it is giving the error I mentioned above.
Because is isLeaf is used in KVO by NSOutlineView, you have to add #objc in front of isLeaf function:
#objc func isLeaf() -> Bool {
return true
}
The class to which you are binding needs to be KVO compliant.
So, it needs to be a subclass of NSObject.
And the objc runtime needs access.
One way to do this:
#objcMembers
class FileSystemItem: NSObject {
Or, you can annotate each field/function with #objc
Full Example

Swift 3 - How to use enum raw value as NSNotification.Name?

I'm using Xcode 8 beta 5 and I'm trying to setup an enum of notifications like this
enum Notes: String {
case note1
case note2
}
Then trying to use them as the notification names
NotificationCenter.default.post(name: Notes.note1.rawValue as NSNotification.Name,
object: nil, userInfo: userInfo)
But I'm getting an error.
Cannot convert value of type 'String' to specified type 'NSNotification.Name'
Is there a work around, or am I missing something? It works in Xcode 7.3.1
Any help would be appreciated.
Here you go, Use Swift 3 & Xcode 8.0
enum Notes: String {
case note1 = "note1"
case note2 = "note2"
var notification : Notification.Name {
return Notification.Name(rawValue: self.rawValue )
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.post(name: Notes.note2.notification ,object: nil, userInfo: nil)
}
}
Another way
import UIKit
extension Notification.Name
{
enum MyNames
{
static let Hello = Notification.Name(rawValue: "HelloThere")
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.post(name: Notification.Name.MyNames.Hello ,object: nil, userInfo: nil)
}
}
I am doing this way, For me this is more simple way to manage Notification names.
Swift 3.0 and Xcode 8.0
Using extension of Notification.Name, we can define static names inside that as following.
extension Notification.Name {
static let newPasscodeSet = Notification.Name("newPasscodeSet")
static let userLoggedIn = Notification.Name("userLoggedIn")
static let notification3 = Notification.Name("notification3")
}
We can use that names like this:
override func viewDidLoad() {
NotificationCenter.default.addObserver(self, selector: #selector(self.newPasscodeSetAction), name: .newPasscodeSet, object: nil)
}
func newPasscodeSetAction() {
// Code Here.
}
Hope this simple way helpful for you.
As far as I know, there was no type NSNotification.Name in Swift 2.2.1/SDKs bundled in Xcode 7.3.1, so I'm curious how you have made it work.
Anyway you need to write something like this if you want to utilize your enum:
NotificationCenter.default.post(name: NSNotification.Name(Notes.note1.rawValue),
object: nil, userInfo: userInfo)
By the way, my best recommendation to define your own Notification.Name is using extension which defines static properties:
extension Notification.Name {
static let note1 = NSNotification.Name("note1")
static let note2 = NSNotification.Name("note2")
}
(It's a little bit longer than enum..., but) you can use it like this:
NotificationCenter.default.post(name: .note1,
object: nil, userInfo: userInfo)
Maybe another approach in swift 4.2
extension Notification.Name{
struct RecordListNotification {
static let recordListDidChange:Notification.Name = Notification.Name("recordListDidChange")
static let recordListTimeDidChange = Notification.Name("recordListTimeDidChange")
}
}
and then
NotificationCenter.default.post(name: Notification.Name.RecordListNotification.recordListTimeDidChange, object: nil)
also to avoid verbose:
typealias RecordListNotification = Notification.Name.RecordListNotification
And it can be used:
NotificationCenter.default.post(name: RecordListNotification.recordListTimeDidChange, object: nil)

Swift Type Inference Not Working (Xcode 7.1.1)

This is my first question on StackOverflow so please go easy on me.
I've been struggling with getting Swift to invoke the appropriate generic overload.
Suppose I have the following protocol -
protocol MyProtocol { }
And I have the following generic methods -
func foo<T>() -> T
func foo<T: MyProtocol>() -> T
One would expect that invoking foo() with a return type of T conforming to MyProtocol would invoke the appropriate overload.
let bar: MyProtocol = foo()
The above code actually invokes the following function during runtime and Cmd + Click in the IDE navigates to the wrong overload as well.
func foo<T>() -> T
For some reason I cannot get this to work properly in Xcode 7.1.1.
Am I missing something completely fundamental here or is this another Swift quirk?
EDIT
Adding an example of this behavior in action as per matt's request.
protocol MyProtocol { }
class MyProtoClass : MyProtocol { }
class Bar {
func foo<T>(value: T) {
print("T is Generic")
}
func foo(value: MyProtocol) {
print("T conforms to MyProtocol")
}
}
class MyClass<T> {
var value: T
init(value: T) { self.value = value }
var b = Bar()
func print() {
b.foo(value)
}
}
MyClass<MyProtocol>(value: MyProtoClass()).print()
MyClass<String>(value: "").print()
Copying and pasting the above code into a Swift command line application and executing yields the following output.
T is Generic
T is Generic
I think the problem here is that protocols in generics (and generally in Swift) don't work the way you want them to. They are not acting as first-class types. I know that's rather vague... but look at it this way; if you eliminate the func foo<T>(value: T) version of foo, your code won't even compile. In other words, Swift isn't making a choice of foo and choosing wrong; it's saying that b.foo(a1.value) does not call func foo<T: MyProtocol>(value: T).
I have a vague feeling that this is related to my question here:
Protocol doesn't conform to itself?
Okay, I am going to answer my own question here.
After some investigation it seems that Swift wants you to implement an extension with a type constraint on the generic parameter.
extension MyClass where T : MyProtocol {
func print() {
b.foo(value)
}
}
I know this doesn't really solve the problem but it was sufficient enough for me as a work around in my real world use case.
The above sample would wind up looking something like the following.
protocol MyProtocol { }
class MyProtoClass : MyProtocol { }
class Bar {
func foo<T>(value: T) {
print("T is Generic")
}
func foo(value: MyProtocol) {
print("T conforms to MyProtocol")
}
}
class MyClass<T> {
var value: T
init(value: T) { self.value = value }
var b = Bar()
func print() {
b.foo(value)
}
}
extension MyClass where T : MyProtocol {
func print() {
b.foo(value)
}
}
MyClass<MyProtoClass>(value: MyProtoClass()).print()
MyClass<String>(value: "").print()

Use of unresolved identifier 'dispatch_get_main_queue' using SWIFT

I am having difficulty using 'dispatch_get_main_queue()' in SWIFT with the base SDK set to 10.9. The code that I am using is a simple dispatch_async call shown below:
dispatch_async(dispatch_get_main_queue()){
// Code here
}
However it is generating the error: Use of unresolved identifier 'dispatch_get_main_queue'. It works as expected when the base SDK is set to 10.10, but not at 10.9. I use it in objective-c in non-swift applications which use the base SDK 10.9 but I cannot figure out why it is not working with Swift.
I have tried to look into it but have currently been unable to find anything about why this is happening and what I can do to resolve it/achieve similar functionality. I would be very grateful if anyone can shed any light on this or point me in the right direction.
So my question is: Is there a way I can resolve this (or at least achieve similar functionality)?
EDIT 1 -
This is the full function I have created:
func addSubview(aView: NSView, fillView: Bool, removeExisting: Bool)
{
dispatch_async(dispatch_get_main_queue()){
if (aView != nil)
{
if (removeExisting)
{
for (var subview: NSView) in self.subviews() as NSView[]
{
subview.removeFromSuperview();
}
}
if (fillView)
{
aView.setAutoresizingMask(NSViewWidthSizable | NSViewHeightSizable);
aView.setFrame(NSMakeRect(0, 0, self.frame().size.width, self.frame().size.height));
}
self.addSubview(aView);
}
}
}
EDIT 2 - Replaced 'if (aView != null)' to 'if (aView != nil)' as suggested. I am not sure how I managed to make that rookie error!
Use it in a function. This should work:
func test() {
dispatch_async(dispatch_get_main_queue()) {
}
}
Works fine on my laptop with deployment target 10.9
Or in your app delegate maybe something like this:
func applicationDidFinishLaunching(aNotification: NSNotification?) {
// Insert code here to initialize your application
dispatch_async(dispatch_get_main_queue()) {
}
}
First you should replace if (aView != null) to if (aView != nil)
Swift uses nil not null
If view can be nil you should use optional type:
func addSubview(view: NSView?, fillView: Bool, removeExisting: Bool) {
dispatch_async(dispatch_get_main_queue()){
if let aView = view {
if removeExisting {
...

Delegates in swift?

How does one go about making a delegate, i.e. NSUserNotificationCenterDelegate in swift?
Here's a little help on delegates between two view controllers:
Step 1: Make a protocol in the UIViewController that you will be removing/will be sending the data.
protocol FooTwoViewControllerDelegate:class {
func myVCDidFinish(_ controller: FooTwoViewController, text: String)
}
Step2: Declare the delegate in the sending class (i.e. UIViewcontroller)
class FooTwoViewController: UIViewController {
weak var delegate: FooTwoViewControllerDelegate?
[snip...]
}
Step3: Use the delegate in a class method to send the data to the receiving method, which is any method that adopts the protocol.
#IBAction func saveColor(_ sender: UIBarButtonItem) {
delegate?.myVCDidFinish(self, text: colorLabel.text) //assuming the delegate is assigned otherwise error
}
Step 4: Adopt the protocol in the receiving class
class ViewController: UIViewController, FooTwoViewControllerDelegate {
Step 5: Implement the delegate method
func myVCDidFinish(_ controller: FooTwoViewController, text: String) {
colorLabel.text = "The Color is " + text
controller.navigationController.popViewController(animated: true)
}
Step 6: Set the delegate in the prepareForSegue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "mySegue" {
let vc = segue.destination as! FooTwoViewController
vc.colorString = colorLabel.text
vc.delegate = self
}
}
And that should work. This is of course just code fragments, but should give you the idea. For a long explanation of this code you can go over to my blog entry here:
segues and delegates
If you are interested in what's going on under the hood with a delegate I did write on that here:
under the hood with delegates
Delegates always confused me until I realized that a delegate is just a class that does some work for another class. It's like having someone else there to do all the dirty work for you that you don't want to do yourself.
I wrote a little story to illustrate this. Read it in a Playground if you like.
Once upon a time...
// MARK: Background to the story
// A protocol is like a list of rules that need to be followed.
protocol OlderSiblingDelegate: class {
// The following command (ie, method) must be obeyed by any
// underling (ie, delegate) of the older sibling.
func getYourNiceOlderSiblingAGlassOfWater()
}
// MARK: Characters in the story
class BossyBigBrother {
// I can make whichever little sibling is around at
// the time be my delegate (ie, slave)
weak var delegate: OlderSiblingDelegate?
func tellSomebodyToGetMeSomeWater() {
// The delegate is optional because even though
// I'm thirsty, there might not be anyone nearby
// that I can boss around.
delegate?.getYourNiceOlderSiblingAGlassOfWater()
}
}
// Poor little sisters have to follow (or at least acknowledge)
// their older sibling's rules (ie, protocol)
class PoorLittleSister: OlderSiblingDelegate {
func getYourNiceOlderSiblingAGlassOfWater() {
// Little sis follows the letter of the law (ie, protocol),
// but no one said exactly how she had to respond.
print("Go get it yourself!")
}
}
// MARK: The Story
// Big bro is laying on the couch watching basketball on TV.
let bigBro = BossyBigBrother()
// He has a little sister named Sally.
let sally = PoorLittleSister()
// Sally walks into the room. How convenient! Now big bro
// has someone there to boss around.
bigBro.delegate = sally
// So he tells her to get him some water.
bigBro.tellSomebodyToGetMeSomeWater()
// Unfortunately no one lived happily ever after...
// The end.
In review, there are three key parts to making and using the delegate pattern.
the protocol that defines what the worker needs to do
the boss class that has a delegate variable, which it uses to tell the worker class what to do
the worker class that adopts the protocol and does what is required
Real life
In comparison to our Bossy Big Brother story above, delegates are often used for the following practical applications:
Communication: one class needs to send some information to another class.
Code example 1: sending data from one view controller to another
Code example 2: sending text input from a custom keyboard to a text field
Customization: one class wants to allow another class to customize it.
The great part is that these classes don't need to know anything about each other beforehand except that the delegate class conforms to the required protocol.
I highly recommend reading the following two articles. They helped me understand delegates even better than the documentation did.
What is Delegation? – A Swift Developer’s Guide
How Delegation Works – A Swift Developer’s Guide
One more note
Delegates that reference other classes that they do not own should use the weak keyword to avoid strong reference cycles. See this answer for more details.
It is not that different from obj-c.
First, you have to specify the protocol in your class declaration, like following:
class MyClass: NSUserNotificationCenterDelegate
The implementation will look like following:
// NSUserNotificationCenterDelegate implementation
func userNotificationCenter(center: NSUserNotificationCenter, didDeliverNotification notification: NSUserNotification) {
//implementation
}
func userNotificationCenter(center: NSUserNotificationCenter, didActivateNotification notification: NSUserNotification) {
//implementation
}
func userNotificationCenter(center: NSUserNotificationCenter, shouldPresentNotification notification: NSUserNotification) -> Bool {
//implementation
return true
}
Of course, you have to set the delegate. For example:
NSUserNotificationCenter.defaultUserNotificationCenter().delegate = self;
I got few corrections to post of #MakeAppPie
First at all when you are creating delegate protocol it should conform to Class protocol. Like in example below.
protocol ProtocolDelegate: class {
func myMethod(controller:ViewController, text:String)
}
Second, your delegate should be weak to avoid retain cycle.
class ViewController: UIViewController {
weak var delegate: ProtocolDelegate?
}
Last, you're safe because your protocol is an optional value. That means its "nil" message will be not send to this property. It's similar to conditional statement with respondToselector in objC but here you have everything in one line:
if ([self.delegate respondsToSelector:#selector(myMethod:text:)]) {
[self.delegate myMethod:self text:#"you Text"];
}
Above you have an obj-C example and below you have Swift example of how it looks.
delegate?.myMethod(self, text:"your Text")
Here's a gist I put together. I was wondering the same and this helped improve my understanding. Open this up in an Xcode Playground to see what's going on.
protocol YelpRequestDelegate {
func getYelpData() -> AnyObject
func processYelpData(data: NSData) -> NSData
}
class YelpAPI {
var delegate: YelpRequestDelegate?
func getData() {
println("data being retrieved...")
let data: AnyObject? = delegate?.getYelpData()
}
func processYelpData(data: NSData) {
println("data being processed...")
let data = delegate?.processYelpData(data)
}
}
class Controller: YelpRequestDelegate {
init() {
var yelpAPI = YelpAPI()
yelpAPI.delegate = self
yelpAPI.getData()
}
func getYelpData() -> AnyObject {
println("getYelpData called")
return NSData()
}
func processYelpData(data: NSData) -> NSData {
println("processYelpData called")
return NSData()
}
}
var controller = Controller()
DELEGATES IN SWIFT 2
I am explaining with example of Delegate with two viewControllers.In this case, SecondVC Object is sending data back to first View Controller.
Class with Protocol Declaration
protocol getDataDelegate {
func getDataFromAnotherVC(temp: String)
}
import UIKit
class SecondVC: UIViewController {
var delegateCustom : getDataDelegate?
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func backToMainVC(sender: AnyObject) {
//calling method defined in first View Controller with Object
self.delegateCustom?.getDataFromAnotherVC(temp: "I am sending data from second controller to first view controller.Its my first delegate example. I am done with custom delegates.")
self.navigationController?.popViewControllerAnimated(true)
}
}
In First ViewController Protocol conforming is done here:
class ViewController: UIViewController, getDataDelegate
Protocol method definition in First View Controller(ViewController)
func getDataFromAnotherVC(temp : String)
{
// dataString from SecondVC
lblForData.text = dataString
}
During push the SecondVC from First View Controller (ViewController)
let objectPush = SecondVC()
objectPush.delegateCustom = self
self.navigationController.pushViewController(objectPush, animated: true)
First class:
protocol NetworkServiceDelegate: class {
func didCompleteRequest(result: String)
}
class NetworkService: NSObject {
weak var delegate: NetworkServiceDelegate?
func fetchDataFromURL(url : String) {
delegate?.didCompleteRequest(result: url)
}
}
Second class:
class ViewController: UIViewController, NetworkServiceDelegate {
let network = NetworkService()
override func viewDidLoad() {
super.viewDidLoad()
network.delegate = self
network.fetchDataFromURL(url: "Success!")
}
func didCompleteRequest(result: String) {
print(result)
}
}
Very easy step by step (100% working and tested)
step1: Create method on first view controller
func updateProcessStatus(isCompleted : Bool){
if isCompleted{
self.labelStatus.text = "Process is completed"
}else{
self.labelStatus.text = "Process is in progress"
}
}
step2: Set delegate while push to second view controller
#IBAction func buttonAction(_ sender: Any) {
let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "secondViewController") as! secondViewController
secondViewController.delegate = self
self.navigationController?.pushViewController(secondViewController, animated: true)
}
step3: set delegate like
class ViewController: UIViewController,ProcessStatusDelegate {
step4: Create protocol
protocol ProcessStatusDelegate:NSObjectProtocol{
func updateProcessStatus(isCompleted : Bool)
}
step5: take a variable
var delegate:ProcessStatusDelegate?
step6: While go back to previous view controller call delegate method so first view controller notify with data
#IBAction func buttonActionBack(_ sender: Any) {
delegate?.updateProcessStatus(isCompleted: true)
self.navigationController?.popViewController(animated: true)
}
#IBAction func buttonProgress(_ sender: Any) {
delegate?.updateProcessStatus(isCompleted: false)
self.navigationController?.popViewController(animated: true)
}
Simple Example:
protocol Work: class {
func doSomething()
}
class Manager {
weak var delegate: Work?
func passAlong() {
delegate?.doSomething()
}
}
class Employee: Work {
func doSomething() {
print("Working on it")
}
}
let manager = Manager()
let developer = Employee()
manager.delegate = developer
manager.passAlong() // PRINTS: Working on it
Delegates are a design pattern that allows one object to send messages to another object when a specific event happens.
Imagine an object A calls an object B to perform an action. Once the action is complete, object A should know that B has completed the task and take necessary action, this can be achieved with the help of delegates!
Here is a tutorial implementing delegates step by step in swift 3
Tutorial Link
Here is real life delegate scenario
Lets make our own UITextField and UITextFieldDelegate
// THE MYSTERIOUS UITEXTFIELD
protocol UITextFieldDelegate {
func textFieldDidChange(_ textField: UITextField) -> Void
}
class UITextField {
var delegate: UITextFieldDelegate?
private var mText: String?
var text: String? {
get {
return mText
}
}
init(text: String) {
}
init() {
}
func setText(_ text: String) {
mText = text
delegate?.textFieldDidChange(self)
}
}
// HERE IS MY APP
class Main {
let textfield = UITextField()
func viewDidLoad() {
print("viewDidLoad")
textfield.delegate = self
textfield.setText("Hello")
}
}
extension Main: UITextFieldDelegate {
func textFieldDidChange(_ textField: UITextField) {
print(textField.text ?? "No string")
}
}
let main = Main()
main.viewDidLoad()
Here Simple Code Example of Delegate:
//MARK: - Protocol ShowResult
protocol ShowResult: AnyObject {
func show(value: Int)
}
//MARK: - MyOperation Class
class MyOperation {
weak var delegate: ShowResult?
func sum(fNumber: Int, sNumber: Int) {
delegate?.show(value: fNumber + sNumber)
}
}
//MARK: - ViewController Class
class ViewController: UIViewController,ShowResult {
var myOperation: MyOperation?
override func viewDidLoad() {
super.viewDidLoad()
loadMyOperation()
myOperation?.delegate = self
myOperation?.sum(fNumber: 100, sNumber: 20)
}
private func loadMyOperation() {
if myOperation == nil {
myOperation = MyOperation()
}
}
func show(value: Int) {
print("value: \(value)")
}
}
The solutions above seemed a little coupled and at the same time avoid reuse the same protocol in other controllers, that's why I've come with the solution that is more strong typed using generic type-erasure.
#noreturn public func notImplemented(){
fatalError("not implemented yet")
}
public protocol DataChangedProtocol: class{
typealias DataType
func onChange(t:DataType)
}
class AbstractDataChangedWrapper<DataType> : DataChangedProtocol{
func onChange(t: DataType) {
notImplemented()
}
}
class AnyDataChangedWrapper<T: DataChangedProtocol> : AbstractDataChangedWrapper<T.DataType>{
var base: T
init(_ base: T ){
self.base = base
}
override func onChange(t: T.DataType) {
base.onChange(t)
}
}
class AnyDataChangedProtocol<DataType> : DataChangedProtocol{
var base: AbstractDataChangedWrapper<DataType>
init<S: DataChangedProtocol where S.DataType == DataType>(_ s: S){
self.base = AnyDataChangedWrapper(s)
}
func onChange(t: DataType) {
base.onChange(t)
}
}
class Source : DataChangedProtocol {
func onChange(data: String) {
print( "got new value \(data)" )
}
}
class Target {
var delegate: AnyDataChangedProtocol<String>?
func reportChange(data:String ){
delegate?.onChange(data)
}
}
var source = Source()
var target = Target()
target.delegate = AnyDataChangedProtocol(source)
target.reportChange("newValue")
output: got new value newValue
In swift 4.0
Create a delegate on class that need to send some data or provide some functionality to other classes
Like
protocol GetGameStatus {
var score: score { get }
func getPlayerDetails()
}
After that in the class that going to confirm to this delegate
class SnakesAndLadders: GetGameStatus {
func getPlayerDetails() {
}
}
In swift 5
I am a beginner, I think this is easiest way to understand in practical scenario
Note:Any improvisations are most appreciated
protocol APIService {
func onSuccessResponse() -> AnyObject
func onFailureResponse() -> AnyObject
}
class APIHelper{
var delegate : APIService?
func postUsersDataAPI() {
//assuming API communication is success
if(success){
let _: AnyObject? = delegate?.onSuccessResponse()
}else if(failure){
let _: AnyObject? = delegate?.onFailureResponse()
}
}
func getAllUsersAPI() {
//assuming API communication is success
if(success){
let _: AnyObject? = delegate?.onSuccessResponse()
}else if(failure){
let _: AnyObject? = delegate?.onFailureResponse()
}
}
}
class ViewController:UIViewController,APIService {
func onSuccessResponse() -> AnyObject {
print("onSuccessResponse") as AnyObject
}
func onFailureResponse() -> AnyObject {
print("onFailureResponse") as AnyObject
}
#IBAction func clickBtnToPostUserData(_ sender: Any) {
let apiHelper = APIHelper()
apiHelper.delegate = self
apiHelper.postAPI()
}

Resources