swift类中的AWS配置行导致线程1:EXC_BAD_INSTRUCTION

时间:2017-06-18 09:35:32

标签: ios swift amazon-web-services

我构建了一个允许用户与AWS Lex聊天机器人通信的应用程序,但现在的问题是当用户点击按钮开始与机器人的对话时崩溃并给我一个线程1:此行上的EXC_BAD_INSTRUCTION 错误:

let configuration = AWSServiceConfiguration(region: botRegion!, credentialsProvider: AWSIdentityManager.default().credentialsProvider)

我真的很想知道是什么导致它表现得像这样,因为Xcode没有强调代码的任何重要部分。

以下是我感兴趣的代码的全部内容。

import Foundation
import UIKit
import Photos
import JSQMessagesViewController
import AWSLex
import AWSMobileHubHelper

let ClientSenderId = "Client"
let ServerSenderId = "Server"

class JeevesChatViewController: JSQMessagesViewController, JSQMessagesComposerTextViewPasteDelegate {

// The name of the bot.
var botName: String?

// The bot region
var botRegion: AWSRegionType?

// The bot alias
var botAlias: String?

// The messages communicated between the client and the server
var messages: [JSQMessage]?

// The interaction kit client
var interactionKit: AWSLexInteractionKit?

// The session attributes
var sessionAttributes: [AnyHashable: Any]?

// Contents of outgoing image
var outgoingBubbleImageData: JSQMessagesBubbleImage?

// Contents of incoming image
var incomingBubbleImageData: JSQMessagesBubbleImage?

// Used to store task completion source of iteraction kit
var textModeSwitchingCompletion: AWSTaskCompletionSource<NSString>?

// The client image
var clientImage: JSQMessagesAvatarImage?

// The bot image
var serverImage: JSQMessagesAvatarImage?

override func viewDidLoad() {
    super.viewDidLoad()

    // Make the initial setup for the bot.
    // Error occurs here - fatal error: unexpectedly found nil while unwrapping an Optional value
    let configuration = AWSServiceConfiguration(region: botRegion!, credentialsProvider: AWSIdentityManager.default().credentialsProvider)

    // Setup interaction kit configuration
    let botConfig = AWSLexInteractionKitConfig.defaultInteractionKitConfig(withBotName:botName!, botAlias: botAlias!)

    // Disable automatic voice playback
    botConfig.autoPlayback = false

    // Register the interaction kit client
    AWSLexInteractionKit.register(with: configuration!, interactionKitConfiguration: botConfig, forKey: botName!)

    // Fetch and set the interaction kit client
    self.interactionKit = AWSLexInteractionKit.init(forKey: botName!)

    // Set the interaction kit delegate
    // Remove 'as? AWSLexInteractionDelegate' statement later
    self.interactionKit?.interactionDelegate = self

    // Setup JSQMessagesViewController configuration
    self.showLoadEarlierMessagesHeader = false

    // Initialise the avatars for client and server here.


    // Setup the default keyboard type.
    self.inputToolbar.contentView?.textView?.keyboardType = UIKeyboardType.default

    // Initialise the messages list
    self.messages = [JSQMessage]()

    // Set the colours for messages bubbles 
    let bubbleFactory = JSQMessagesBubbleImageFactory()
    self.outgoingBubbleImageData = bubbleFactory?.outgoingMessagesBubbleImage(with: UIColor.jsq_messageBubbleGreen())
    self.incomingBubbleImageData = bubbleFactory?.incomingMessagesBubbleImage(with: UIColor.jsq_messageBubbleBlue())

    self.inputToolbar.contentView?.leftBarButtonItem = nil

    self.senderDisplayName = "User"

    self.senderId = ClientSenderId
}

// MARK: - JSQMessagesViewController delegate methods

override func didPressSend(_ button: UIButton!, withMessageText text: String!, senderId: String!, senderDisplayName: String!, date: Date!) {
    let message = JSQMessage(senderId: senderId, senderDisplayName: senderDisplayName, date: date, text: text)
    self.messages?.append(message!)

    if let textModeSwitchingCompletion = textModeSwitchingCompletion {
        textModeSwitchingCompletion.set(result: text as NSString)
        self.textModeSwitchingCompletion = nil
    }
    else {
        self.interactionKit?.text(inTextOut: text)
    }
    self.finishSendingMessage(animated: true)
}

override func collectionView(_ collectionView: JSQMessagesCollectionView, messageDataForItemAt indexPath: IndexPath) -> JSQMessageData {

    return self.messages![indexPath.item]
}

override func collectionView(_ collectionView: JSQMessagesCollectionView, didDeleteMessageAt indexPath: IndexPath) {
    // Nothing happens here
}

override func collectionView(_ collectionView: JSQMessagesCollectionView, messageBubbleImageDataForItemAt indexPath: IndexPath) -> JSQMessageBubbleImageDataSource {

    let message = self.messages![indexPath.item]
    if (message.senderId == self.senderId) {
        return self.outgoingBubbleImageData!
    }
    return self.incomingBubbleImageData!
}

override func collectionView(_ collectionView: JSQMessagesCollectionView, avatarImageDataForItemAt indexPath: IndexPath) -> JSQMessageAvatarImageDataSource? {

    let message = messages![indexPath.item]
    if message.senderId == ClientSenderId {
        return self.clientImage
    }
    return self.serverImage
}

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    if let messages = messages {
        return messages.count
    }
    return 0
}

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = (super.collectionView(collectionView, cellForItemAt: indexPath) as! JSQMessagesCollectionViewCell)
    let msg = self.messages?[indexPath.item]
    if !msg!.isMediaMessage {
        if (msg?.senderId == self.senderId) {
            cell.textView?.textColor = UIColor.black
        }
        else {
            cell.textView?.textColor = UIColor.white
        }
    }
    return cell
}

override func collectionView(_ collectionView: JSQMessagesCollectionView, attributedTextForCellTopLabelAt indexPath: IndexPath) -> NSAttributedString? {
    if indexPath.item % 3 == 0 {
        let message = self.messages?[indexPath.item]
        return JSQMessagesTimestampFormatter.shared().attributedTimestamp(for: message!.date)
    }
    return nil
}

override func collectionView(_ collectionView: JSQMessagesCollectionView, attributedTextForMessageBubbleTopLabelAt indexPath: IndexPath) -> NSAttributedString? {
    let message = self.messages?[indexPath.item]

    // iOS 7 sender name labels
    if (message?.senderId == self.senderId) {
        return nil
    }

    if indexPath.item - 1 > 0 {
        let previousMessage = self.messages?[indexPath.item - 1]
        if (previousMessage?.senderId == message?.senderId) {
            return nil
        }
    }

    // Do not specify attributes to use the default values.
    return NSAttributedString(string: message!.senderDisplayName)
}

override func collectionView(_ collectionView: JSQMessagesCollectionView, attributedTextForCellBottomLabelAt indexPath: IndexPath) -> NSAttributedString? {
    return nil
}

func composerTextView(_ textView: JSQMessagesComposerTextView, shouldPasteWithSender sender: Any) -> Bool {
    return true
}

}

 // MARK: - Bot Interaction Kit
 extension JeevesChatViewController: AWSLexInteractionDelegate {

func interactionKit(_ interactionKit: AWSLexInteractionKit, onError error: Error) {
    print("Error occurred: \(error)")
}

func interactionKit(_ interactionKit: AWSLexInteractionKit, switchModeInput: AWSLexSwitchModeInput, completionSource: AWSTaskCompletionSource<AWSLexSwitchModeResponse>?) {
    self.sessionAttributes = switchModeInput.sessionAttributes
    DispatchQueue.main.async(execute: {
        let message: JSQMessage

        // Handle a successful transaction
        if (switchModeInput.dialogState == AWSLexDialogState.readyForFulfillment) {
            // Currently just displaying the slots return on ready for fulfillment
            if let slots = switchModeInput.slots {
                message = JSQMessage(senderId: ServerSenderId, senderDisplayName: "", date: Date(), text: "Slots:\n\(slots)")
                self.messages?.append(message)
                self.finishSendingMessage(animated: true)
            }
        } else {
                message = JSQMessage(senderId: ServerSenderId, senderDisplayName: "", date: Date(), text: switchModeInput.outputText!)
                self.messages?.append(message)
                self.finishSendingMessage(animated: true)
            }
    })
    // This can be expanded to take input from the user.
    let switchModeResponse  = AWSLexSwitchModeResponse()
    switchModeResponse.interactionMode = AWSLexInteractionMode.text
    switchModeResponse.sessionAttributes = switchModeInput.sessionAttributes
    completionSource?.set(result: switchModeResponse)

}

func interactionKitContinue(withText interactionKit: AWSLexInteractionKit, completionSource: AWSTaskCompletionSource<NSString>) {
    textModeSwitchingCompletion = completionSource
}
}

1 个答案:

答案 0 :(得分:0)

您尚未正确设置您的credentialsProvider。 AWSIdentityManager从未被初始化为:

let configuration = AWSServiceConfiguration(region: botRegion!, credentialsProvider: AWSIdentityManager.default().credentialsProvider)

如果您使用AWS for S3存储桶,则应使用隐身模式,因此

let cognitoIdentityPoolId = //"XYZ"
let cognitoUnauthRoleArn = //"XYZ"
let cognitoAuthRoleArn =  //"XYZ"
let credentialsProvider = AWSCognitoCredentialsProvider(regionType: #Wherever, identityPoolId: cognitoIdentityPoolId, unauthRoleArn: cognitoUnauthRoleArn, authRoleArn: cognitoAuthRoleArn, identityProviderManager: nil)

然后您可以将您的行更改为:

let configuration = AWSServiceConfiguration(region: botRegion!, credentialsProvider: credentialsProvider)