2

In Objective-C, I used this handling of a completion-block that now must be transformed to Swift:

in DetailDisplayController.h

typedef void (^AddedCompletitionBlock)(BOOL saved, NSString *primarykey, NSUInteger recordCount);

@interface DetailDisplayController : UITableViewController

@property (nonatomic, copy) AddedCompletitionBlock completionBlock;
@property (strong, nonatomic) Details *detail;

in DetailDisplayController.m

- (void) saveClicked:(id)sender
{  
   // retrieve PK
   NSString *objectId = [[[_detail objectID] URIRepresentation] absoluteString];

   if (self.completionBlock != nil)
   {
       self.completionBlock(_rowChanged, objectId, [_fetchedResultsController.fetchedObjects count]);
   }

_rowChanged and _fetchedResultsController are instance-variables

and in DetailViewController.m a the calling class, the passed block is used

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
   if ([segue.identifier isEqualToString:@"DetailDisplay"])
   {
       DetailDisplayController *detailDisplayController = segue.destinationViewController; 
       ...
       detailDisplayController.completionBlock = ^(BOOL saved, NSString *sorter, NSUInteger recordCount)
       {
        if (saved)
           ...

How can I do this in Swift?

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Ulli H
  • 1,748
  • 1
  • 19
  • 32
  • Functions in Swift can be passed like variables. – shim Feb 23 '16 at 21:43
  • Ok, i can pass a function from the calling class. But how to share the variables in the called class? – Ulli H Feb 23 '16 at 22:23
  • Please show what you are trying to do and an attempt at a solution (in Swift). – shim Feb 25 '16 at 04:37
  • sorry shim, there is nothing to show cause i dont´t know how to start :-( I´m just googling for an solution. Meanwhile i think, my Swift-knowledge is too poor to resolve this... – Ulli H Feb 25 '16 at 16:23

2 Answers2

8

Here's the equivalent pieces that you need in Swift:

typealias AddedCompletionBlock = (saved: Bool, primaryKey: String, recordCount: Int) -> Void

var completionBlock: AddedCompletionBlock? = nil

completionBlock = {saved, primaryKey, recordCount in
    print("\(saved), \(primaryKey), \(recordCount)")
}

completionBlock?(saved: true, primaryKey: "key", recordCount: 1)

You probably want to have a good read of the "Function Types" and "Closures" sections of the Apple Swift docs.

Ewan Mellor
  • 6,747
  • 1
  • 24
  • 39
  • Hi Ewan, many THX, that´s it. I only had to move the line "completionBlock = {saved, primaryKey, recordCount in" to my DetailViewController.m... And i dont have to read anything, i understood it all ;-) – Ulli H Feb 25 '16 at 21:25
0

In Swift completions are really easy. Here is an example. I press the button to open a SecondVC and then I press a button on the SecondVC to close it and I call a completion which is going to change a label on the FirstVC:

    class ViewController: UIViewController {
    @IBOutlet weak var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func didTapButton(_ sender: Any) {
        let vc = storyboard?.instantiateViewController(withIdentifier: "SecondVC") as! SecondVC
        self.present(vc, animated: true, completion: nil)
        vc.completion = { str in
            self.label.text = str
        }
    }
 }

and this is what the SecondVC looks like:

 class SecondVC: UIViewController {
    var completion:((String)->())?

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func didTapButton(_ sender: Any) {
        completion?("Hello")
        self.dismiss(animated: true, completion: nil)
    }
}
Dinu Nicolae
  • 1,019
  • 2
  • 17
  • 42