Swift error declaring delegate - ios

I'm new in swift and I'm studying the delegate and protocols. In my test application I'm using this protocol declaration (in ViewController1) and I have this code:
import UIKit
//Protocol declaration
protocol viewController1Delegate
{
func didFinish(controller:ViewController1,text:String)
}
//ViewController1 class
class ViewController1: UIViewController {
//delegate declaration for viewController1
var delegate:ViewController1? = nil
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
valore.text=valoreInput
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func doneWithOK(sender: AnyObject) {
delegate?.didFinish(self,"done")
}
}
My problem is XCode show me an error: ViewController1 does not have a member named didFinisch. What is wrong in my code? Someone can help me to understand the problem?

delegate should be viewController1Delegate? and not ViewController1?.

Related

initWithDelegate for Objective-C class

I have import this Objective-C class in a swift project.
MMLANSCanner.h
#import <Foundation/Foundation.h>
#class Device;
#protocol MMLANScannerDelegate;
#protocol MMLANScannerDelegate <NSObject>
#required
- (void)lanScanDidFinishScanningWithStatus:(MMLanScannerStatus)status;
- (void)lanScanDidFailedToScan;
#optional
- (void)lanScanProgressPinged:(float)pingedHosts from:(NSInteger)overallHosts;
#end
#pragma mark - Public methods
#interface MMLANScanner : NSObject
-(instancetype)initWithDelegate:(id <MMLANScannerDelegate>)delegate;
#property(nonatomic,weak) id<MMLANScannerDelegate> delegate;
#property(nonatomic,assign,readonly)BOOL isScanning;
- (void)start;
- (void)stop;
#end
I successfully created the bridging header and make the MainVC.Swift to conform to MMLANScannerDelegate.
Then I tried to initialise the MMLanScanner with delegate self.
import UIKit
import Foundation
class MainVC: UIViewController, MMLANScannerDelegate {
var presenter = MMLANScanner(delegate:self)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func lanScanDidFindNewDevice(_ device: Device!) {
}
func lanScanDidFailedToScan() {
}
func lanScanDidFinishScanning(with status: MMLanScannerStatus) {
}
func lanScanProgressPinged(_ pingedHosts: Float, from overallHosts: Int) {
}
}
But I get error:
Argument passed to call that takes no arguments
Any ideas how to implement initWithDelegate function that I had in Objective-C?
MLANScanner doesn't take a delegate argument to its init method (delegate is a property of MLANScanner).
You also have a problem with the definition of your presenter property since self isn't valid at the time MainVC is created.
Do this instead:
let presenter = MLANScanner()
override func viewDidLoad() {
super.viewDidLoad()
presenter.delegate = self
}
based on edit to question:
var presenter: MLANScanner!
override func viewDidLoad() {
super.viewDidLoad()
presenter = MLANScanner(delegate: self)
}
Note: My edited answer assumes there is a Swift bridge somewhere that exposes an init(delegate:) method. There may not be and making one is beyond the scope of this question. Since the delegate is not private or read-only you can almost certainly use the first version I posted.

Looking understand why delegate keep alive

I have the following structure
Main ViewController: it is responsible to call the (A) view controller.
(A) ViewController: create an CustomClass instance and has a delegate for this class.
CustomClass: in each period of 1 second, a message is sent to (A) view controller via delegate.
Until here all works fine. Once I returned to Main ViewController the delegate keep alive, in other words, the delegate updates A(ViewController) variable. I checked that viewDidDisappear of (A) ViewController is called.
When I return again from Main ViewController to (A) ViewController, a new variable instance is created. I don't understand this anyway.
Besides this doubt, I would like to understand why the delegate keep alive when I return to main view controller. I am using a UINavigationItem to navigation.
I am a beginner in IOS development.
Thanks advanced!!!
Edit 1:
The (A)ViewController is called from MainViewController by Segue. The segue was added via storyboard.
MainViewController.swift
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
AViewController.swift
class ScanDevices : UIViewController, CustomClassDelegate {
var myInts : [Int] = []
var customClass : CustomClass!
override func viewDidLoad() {
super.viewDidLoad()
print("viewDidLoad")
if customClass == nil {
customClass = CustomClass()
customClass.customClassDelegate = self
}
}
override func viewWillAppear(animated: Bool) {
print("viewWillAppear")
}
override func viewDidAppear(animated: Bool) {
print("viewDidAppear")
}
override func viewWillDisappear(animated: Bool) {
print("viewWillDisappear")
}
override func viewDidDisappear(animated: Bool) {
print("viewDidDisappear")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func didDiscoverPeripheralInt(peripheral: Int) {
myInts.append(peripheral)
print("Number = \(myInts.count)")
}
}
CustomClass.swift
class CustomClass : NSObject {
var customClassDelegate : CustomClassDelegate?
// MARK: init
override init() {
super.init()
NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "writeInt", userInfo: nil, repeats: true)
}
func writeInt () {
CustomClassDelegate?.didDiscoverPeripheralInt(3)
}
}
var customClassDelegate : CustomClassDelegate?
You are holding a string reference to your delegate.
It needs to be
weak var customClassDelegate : CustomClassDelegate?
Take a look at the following document :
http://krakendev.io/blog/weak-and-unowned-references-in-swift
Your CustomClass holds strong reference to the delegate. You have to mark the property with weak:
weak var customClassDelegate : CustomClassDelegate?

assigned delegate, but function is not called

Hi guys i would want to fire a method in SecondViewController from FirstViewController when the condition is meet. So i have used delegate to do so and my code is as follow:
FirstViewController:
import UIKit
import CoreBluetooth
import Foundation
class BluetoothViewController: UIViewController, ValueChangedDelegate {
if (characteristic.UUID == CBUUID(string: "2AF0")){
DataReceived.Single_Axis = Double(CharValue)
func peripheral(peripheral: CBPeripheral!, didUpdateValueForCharacteristic characteristic: CBCharacteristic!, error: NSError!) {
let singleaxisview = SingeAxisViewController()
singleaxisview.delegate = self
singleaxisview.valueChangedNotifyEveryone()
println("btfired")
}
SecondViewController
import UIKit
import CoreGraphics
protocol ValueChangedDelegate
{
func valueChanged(nValue : String)
}
class SingeAxisViewController: UIViewController {
var delegate : ValueChangedDelegate?
func valueChangedNotifyEveryone()
{
println("hello")
delegate?.valueChanged("changed value")
}
Can somebody point out to me what i missed?
Instead of BTController!.delegate = self you will have to use object of FirstViewController and set the delegate and you will also need to initialise the FirstViewController object. here is a sample code if you want to implement it. the first view controller implements the delegate methods and on call of btnClicked the second view controller is called and you get the response back to first view controller in the valueChanged method
import UIKit
class FirstViewController: UIViewController, ValueChangedDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
lbl.text = "inital value"
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
#IBOutlet weak var lbl: UILabel!
#IBAction func btnClicked(sender: AnyObject)
{
let secondViewController = SecondViewController()
secondViewController.delegate = self
secondViewController.valueChangedNotifyEveryone()
}
func valueChanged(nValue : String)
{
print(nValue)
lbl.text = nValue
}
}
Second view controller which implements the protocol and the also calls the protocol method from valueChangedNotifyEveryone method
import UIKit
protocol ValueChangedDelegate
{
func valueChanged(nValue : String)
}
class SecondViewController: UIViewController {
var delegate : ValueChangedDelegate?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func valueChangedNotifyEveryone()
{
delegate?.valueChanged("changed value")
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}

IOS Swift - Passing data between view controllers using container view

I am a little confused on how to use container views correctly, i will try to explain it the best i can.
I have a main view controller that has an animation function.
import UIKit
class MainViewController: UIViewController,UIPickerViewDataSource,UIPickerViewDelegate {
// Run view setups
override func viewDidLoad() {
super.viewDidLoad()
}
func closePicker(){
self.view.layoutIfNeeded();
UIView.animateWithDuration(0.5, animations: {
self.countryPickerConst.constant = -206;
self.view.layoutIfNeeded();
})
}
}
In interface builder i have added a container view with a new view controller that contains a button like so:
import UIKit
class ContainerViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func runAnimation(sender: UIButton) {
//I want to call the function in my other view controller
}
}
In the action runAnimation i want to call the function in the MainViewController. If i just create an instance of MainViewController and call the function it seems to loose its 'self' relevance.
If someone could explain to me the best practice for doing things like this that would be great.
Thanks
From your explanation MainViewController is the parent of ContainerViewController so to access closePicker from ContainerViewController you would do:
#IBAction func runAnimation(sender: UIButton) {
(self.parentViewController as! MainViewController).closePicker()
}

Delegate Not Called In SWIFT iOS

I am Created 2 Views, One is and Used Protocol and Delegate. For first view the Delegate function is not called.
My FirstView Controller : Here I am Accessing the Delegate Function.
import UIKit
class NextViewController: UIViewController,DurationSelectDelegate {
//var secondController: DurationDel?
var secondController: DurationDel = DurationDel()
#IBAction func Next(sender : AnyObject)
{
let nextViewController = DurationDel(nibName: "DurationDel", bundle: nil)
self.navigationController.pushViewController(nextViewController, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
secondController.delegate=self
}
func DurationSelected() {
println("SUCCESS")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
My SecondView Controller : Here I Am creating Delegate.
import UIKit
protocol DurationSelectDelegate {
func DurationSelected()
}
class DurationDel: UIViewController {
var delegate: DurationSelectDelegate?
#IBAction func Previous(sender : AnyObject) {
//let game = DurationSelectDelegate()
delegate?.DurationSelected()
self.navigationController.popViewControllerAnimated(true)
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
To me, it looks like you're pushing a view controller that you haven't actually set the delegate for. If you change your "Next" function, to include the line
nextViewController.delegate = self
You should see that the delegation works. In doing this, you can also probably remove the creation of "secondController", as it looks like that's redundant.
The naming convention you have followed would confuse fellow developers in your team. The instance should have been
let durationDel = DurationDel(nibName: "DurationDel", bundle: nil)
And then as #Eagerod mentioned, the delegate you would set is
durationDel.delegate = self

Resources