jonthornham jonthornham - 3 months ago 8
Swift Question

Swift Delegation Issue

I use delegation in Swift on a regular basis and have implemented it successfully on a number of projects. I am currently having an issue I don't understand. After my CreateMessageBEDelegate delegate fires the call back method, the CreateMessageBE object is nil in MessageViewController. When testing the message object in CreateMessageBE prior to the call back I can see that it is not nil.

The info below is a walk through of the code. Any idea why this is not working?

UPDATED
Specific Problem - createMessageBE is nil, see not below.

func createMessageBEWithMessageSenderAndMessageReceiverDidSuceed(createMessageBEInput: CreateMessageBE)
{
self.message = self.createMessageBE?.message // createMessageBE is nil

// Update Backendless
self.updateBackendless = UpdateBackendless(messageBEWithMessageSenderAndMessageReceiver: self.message!, delegateInput: self)
}


MessageViewController

class MessageViewController : UIViewController, FindMessageSenderDelegate, FindMessageReceiverDelegate, CreateMessageBEDelegate, UpdateBackendlessDelegate
{
// Backendless Property
let backendless = Backendless.sharedInstance()

// Message Properties
var messageSender : BackendlessUser?
var MessageReceiver : BackendlessUser?
var messageText : String?
var message : MessageBE?

var findMessageSender : FindMessageSender?
var findMessageReceiver : FindMessageReceiver?
var createMessageBE : CreateMessageBE?
var updateBackendless : UpdateBackendless?

func findMessageReceiverDidFindUsernameMessageReceiver(findMessageReceiverInput : FindMessageReceiver)
{
// Set the Message User Message Receiver
self.messageReceiver = self.findMessageReceiver!.messageReceiver

self.createMessageBE = CreateMessageBE(guestMessageUserInput: self.guestMessageUser!, messageReceiverInput: self.messageReceiver!, messageInput: self.message!, delegateInput: self)
//print(self.createMessageBE) If I call this here self.createMessage is not nil in the delegate call back. If I do not call it, it is nil.
}

func createMessageBEWithMessageSenderAndMessageReceiverDidSuceed(createMessageBEInput: CreateMessageBE)
{
// Set the MessageBE Property
self.message = self.createMessageBE?.message

// Update Backendless
self.updateBackendless = UpdateBackendless(messageBEWithMessageSenderAndMessageReceiver: self.message!, delegateInput: self)
}


Here is the CreateMessageBE class

import Foundation
import CoreData

protocol CreateMessageBEDelegate
{
func createMessageBEWithMessageSenderAndMessageReceiverDidSuceed(createMessageBEInput : CreateMessageBE) -> ()
}

class CreateMessageBE : NSObject
{
// Properties
var message : MessageBE?

// Backendless Property
let backendless = Backendless.sharedInstance()

// Delegate Property
var delegate : CreateMessageBEDelegate?

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// Custom Init Method
init(messageSenderInput: BackendlessUser, messageReceiverInput: BackendlessUser, messageTextInput: String, delegateInput: CreateMessageBEDelegate)
{
super.init()

// Create MessageBE for Message User Sender and Message User Receiver
self.message = MessageBE(messageSenderInput: messageSenderInput, messageReceiverInput: messageReceiverInput, messageTextInput: messageTextInput)
self.delegate = delegateInput

self.returnMessageBEWithMessageSenderAndMessageReceiver()
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

func returnMessageBEWithMessageSenderAndMessageReceiver()
{
// Return the created MessageBE to MessageViewController
if self.message != nil
{
print("In the createMessageBEDelegate and printing self.message \(self.message)")
self.delegate?.createMessageBEWithMessageSenderAndMessageReceiverDidSuceed(self)
}
else
{
// Report error.
}
}
}


Here is the MessageBE class

import Foundation
import UIKit

class MessageBE: NSObject
{
// This is a custom class used to access Message Objects that are stored Backendless.
var objectId : String?
var created : NSDate?
var updated : NSDate?
var messageSender : BackendlessUser?
var messageReceiver : BackendlessUser?
var messageText : String?
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

init(messageSenderInput: BackendlessUser, messageReceiverInput: BackendlessUser, messageTextInput: Double)
{
self.messageSender = messageSenderInput
self.messageReceiver = messageReceiverInput
self.messageText = messageTextInput
}
}

Answer

I figured out the issue with my code. It the problem was that I was trying to access self.createMessageBE in the delegate call back before the instantiation of self.createMessageBE was complete. The order and placement of my methods was wrong. Below I show the initial code and then the new updated code.

You can see that the placement of the call returnMessageBEWithMessageSenderAndMessageReceiver() is what makes the difference. With this call in the correct location, self.createMessageBE is not nil since it's been instantiated. I hope this helps someone else.

MessageViewController Class

Original Code

    func findMessageReceiverDidFindUsernameMessageReceiver(findMessageReceiverInput : FindMessageReceiver)
        {
            // Set the Message User Message Receiver
            self.messageReceiver = self.findMessageReceiver!.messageReceiver

            // Create createMessageBE
            self.createMessageBE = CreateMessageBE(guestMessageUserInput: self.guestMessageUser!, messageReceiverInput: self.messageReceiver!, messageInput: self.message!, delegateInput: self)     
        }

New Code

func findMessageReceiverDidFindUsernameMessageReceiver(findMessageReceiverInput : FindMessageReceiver)
    {
        // Set the Message User Message Receiver
        self.messageReceiver = self.findMessageReceiver!.messageReceiver

        self.createMessageBE = CreateMessageBE(guestMessageUserInput: self.guestMessageUser!, messageReceiverInput: self.messageReceiver!, messageInput: self.message!, delegateInput: self)
        self.createMessageBE?.returnMessageBEWithMessageSenderAndMessageReceiver()
    }

CreateMessageBE Class

Original Code

// Custom Init Method
    init(messageSenderInput: BackendlessUser, messageReceiverInput: BackendlessUser, messageTextInput: String, delegateInput: CreateMessageBEDelegate)
    {
        super.init()

        // Create MessageBE for Message User Sender and Message User Receiver
        self.message = MessageBE(messageSenderInput: messageSenderInput, messageReceiverInput: messageReceiverInput, messageTextInput: messageTextInput)
        self.delegate = delegateInput

        self.returnMessageBEWithMessageSenderAndMessageReceiver()
    }

New Code

// Custom Init Method
    init(messageSenderInput: BackendlessUser, messageReceiverInput: BackendlessUser, messageTextInput: String, delegateInput: CreateMessageBEDelegate)
    {
        super.init()

        // Create MessageBE for Message User Sender and Message User Receiver
        self.message = MessageBE(messageSenderInput: messageSenderInput, messageReceiverInput: messageReceiverInput, messageTextInput: messageTextInput)
        self.delegate = delegateInput
    }