我有一个包含一些字符串参数的数据结构。结构如下:
struct pulledMessage{
var convoWithUserID: String
var convoWithUserName: String
}
我有一个函数,它根据特定pulledMessage
中的值为变量赋值。对于一些更复杂,超出范围的原因,这些值来自[pulledMessage]
数组。 pulledMessage
总是在实际功能中发生变化,但为了便于说明,我将其作为常量编写:
var messageArray = [pulledMessage]()
func assignValues(){
messageArray.append(pulledMessage(convoWithUserID: "abc123", convoWithUserName: "Kevin"))
let convoWithUserID = messageArray[0].convoWithUserID
let convoWithUserName = messageArray[0].convoWithUserName
print(convoWithUserID) //returns optional("abc123")
print(convoWithUserName) // returns optional("Kevin")
}
我尝试添加!
以不同的方式解包值:
messageArray[0]!.convoWithUserID
这告诉我一个错误,我无法打开非可选类型的pulledMessage
。
messageArray[0].convoWithUserID!
这给了我一个错误,我无法解开非可选类型的字符串
This stack question建议使用if let
删除可选项:
if let convoWithUserIDCheck = messageArray[0].convoWithUserID{
convoWithUserID = convoWithUserIDCheck
}
这给了我一个警告,即没有理由使用非可选类型的字符串if let
。我不知道如何让它停止返回optional()包装的值。
更新:更复杂,更完整的代码
SQL数据库功能:
class FMDBManager: NSObject {
static let shared: FMDBManager = FMDBManager()
let databaseFileName = "messagesBetweenUsers.sqlite"
var pathToDatabase: String!
var database: FMDatabase!
override init() {
super.init()
let documentsDirectory = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString) as String
pathToDatabase = documentsDirectory.appending("/\(databaseFileName)")
}
func loadMessageData(){//will need a struct to load the data into a struct
if openDatabase(){
let query = "select * from messages order by messageNumber asc"
do{
print(database)
let results: FMResultSet = try database.executeQuery(query, values: nil)
while results.next(){
let message = pulledMessage(convoWithUserID: String(describing: results.string(forColumn: "convoWithUserID")), convoWithUserName: String(describing: results.string(forColumn: "convoWithUserName")), messageString: String(describing: results.string(forColumn: "messageString")), senderID: String(describing: results.string(forColumn: "senderID")), timeSent: String(describing: results.string(forColumn: "timeSent")), messageNumber: Int(results.int(forColumn: "messageNumber")))
if messagesPulled == nil{
messagesPulled = [pulledMessage]()
}
messagesPulled.append(message)
print("The message that we have pulled are \(message)")
}
}
catch{
print(error.localizedDescription)
}
database.close()
}
}
}
在应用启动开始时运行数据填充:
func applicationDidBecomeActive(_ application: UIApplication) {
// if FMDBManager.shared.createDatabase() {
// FMDBManager.shared.insertMessageData()
// }else{
// print("Not a chance, sonny")
// FMDBManager.shared.insertMessageData()
// }
FMDBManager.shared.loadMessageData()
}
按顺序组织SQL数据:
struct pulledMessage{//global struct
var convoWithUserID: String
var convoWithUserName: String
var messageString: String
var senderID: String
var timeSent: String
var messageNumber: Int
}
var messagesPulled: [pulledMessage]!
var messageConvoDictionary = [String: [pulledMessage]]()
//For the individual message convos
var fullUnorderedMessageArray = [[pulledMessage]]()
var fullOrderedMessageArray = [[pulledMessage]]()
//For the message table
var unorderedLastMessageArray = [pulledMessage]()
var orderedLastMessageArray = [pulledMessage]()
//For the table messages... FROM HERE..........................................
func organizeSQLData(messageSet: [pulledMessage]){
var i = 0
var messageUserID = String()
while i < messageSet.count{
if (messageSet[i]).convoWithUserID != messageUserID{
print("It wasn't equal")
print(messageSet[i])
messageUserID = messageSet[i].convoWithUserID
if messageConvoDictionary[messageUserID] != nil{
messageConvoDictionary[messageUserID]?.append(messageSet[i])
}else{
messageConvoDictionary[messageUserID] = []
messageConvoDictionary[messageUserID]?.append(messageSet[i])
}
i = i + 1
}else{
messageConvoDictionary[messageUserID]?.append(messageSet[i])
i = i + 1
}
}
}
func getLastMessages(messageSet: [String:[pulledMessage]]){
for (_, messages) in messageSet{
let orderedMessages = messages.sorted(by:{ $0.timeSent.compare($1.timeSent) == .orderedAscending})
let finalMessage = orderedMessages[0]
unorderedLastMessageArray.append(finalMessage)
}
print(unorderedLastMessageArray)
}
func orderLastMessage(messageSet: [pulledMessage]){
orderedLastMessageArray = messageSet.sorted(by:{ $0.timeSent.compare($1.timeSent) == .orderedDescending})
messagesListTableView.reloadData()
print("It wasn't\(orderedLastMessageArray)")
}
func getMessagesReady(){//for observer type function calls
organizeSQLData(messageSet: messagesPulled)
getLastMessages(messageSet: messageConvoDictionary)
orderLastMessage(messageSet: unorderedLastMessageArray)
//This one is for the individual full convos for if user clicks on a cell... its done last because its not required for the page to show up
orderedFullMessageConvos(messageSet: messageConvoDictionary)
let openedMessageConversation = fullOrderedMessageArray[(indexPath.row)]//not placed in its appropriate location, but it is just used to pass the correct array (actually goes in a prepareforSegue)
}
override func viewDidLoad() {
super.viewDidLoad()
getMessagesReady()
}
然后转到新控制器(将openedMessageConversation
传递给messageConvo
)并按下按钮运行此过程:
let newMessage = pulledMessage(convoWithUserID: messageConvo[0].convoWithUserID, convoWithUserName: messageConvo[0].convoWithUserName, messageString: commentInputTextfield.text!, senderID: (PFUser.current()?.objectId)!, timeSent: String(describing: Date()), messageNumber: 0)
messageConvo.append(newMessage)
let newMessageSent = PFObject(className: "UserMessages")
newMessageSent["convoWithUserID"] = newMessage.convoWithUserID
newMessageSent["convoWithUserName"] = newMessage.convoWithUserName
newMessageSent["messageString"] = newMessage.messageString
newMessageSent["senderID"] = newMessage.senderID
let acl = PFACL()
acl.getPublicWriteAccess = true
acl.getPublicReadAccess = true
acl.setWriteAccess(true, for: PFUser.current()!)
acl.setReadAccess(true, for: PFUser.current()!)
newMessageSent.acl = acl
newMessageSent.saveInBackground()
使用数据库中的optional()读取newMessageSent["convoWithUserID"]
和newMessageSent["convoWithUserName"]
。
答案 0 :(得分:1)
事实证明,其原因源自loadMessageData
的函数。使用String(describing: results.string(forColumn:)
需要展开{{1}}。此问题在整个应用程序的整个数据修改过程中传播,并导致我看到的打印语句的results.String(forColumn:)!
包装。