Ich habe eine App, die einen Tab-Leiste-Controller hat. Und in einer Registerkarte befindet sich ein Navigationscontroller, der über einen ViewController verfügt. Jetzt enthält diese Ansicht eine Messaging-Schnittstelle und mein Problem war, dass mit dem Hinzufügen der Tab-Leiste mein Textfeld am unteren Rand der Ansicht abgeschnitten wurde. Um dies zu lösen, habe ich einige der Forschung und einfach hinzugefügt, um die einzelnen Zeile:App stürzt nach Aktion in der Tab-Leiste anzeigen Controller
self.edgesForExtendedLayout = .None
, die das Problem gelöst. Mein Textfeld anzeigte, und der Benutzer kann es auswählen und modifizieren etc. Allerdings, wenn der Benutzer Hits senden, meine App stürzt ab mit der Meldung:
fatal error: unexpectedly found nil while unwrapping an Optional value
Ich habe keine Ahnung, was das Problem, weil alles sein könnte funktioniert perfekt bis dahin ...
Der gesamte Code für meine Viewcontroller wie folgt:
class ChatViewController: JSQMessagesViewController, CLLocationManagerDelegate {
// MARK: Properties
//Location
var city: String = ""
var state: String = ""
var country: String = ""
var locationManager = CLLocationManager()
var locationId: String = ""
func getLocation() -> String {
if city == ("") && state == ("") && country == (""){
return "Anonymous"
}
else {
if country == ("United States") {
return self.city + ", " + self.state
}
else {
return self.city + ", " + self.state + ", " + self.country
}
}
}
//Firebase
var rootRef = FIRDatabase.database().reference()
var messageRef: FIRDatabaseReference!
var locationRef: FIRDatabaseReference!
//JSQMessages
var messages = [JSQMessage]()
var outgoingBubbleImageView: JSQMessagesBubbleImage!
var incomingBubbleImageView: JSQMessagesBubbleImage!
override func viewDidLoad() {
super.viewDidLoad()
self.edgesForExtendedLayout = .None
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
//collect user's location
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
locationManager.requestLocation()
locationManager.startUpdatingLocation()
}
title = "Group Chat"
setupBubbles()
// No avatars
collectionView!.collectionViewLayout.incomingAvatarViewSize = CGSizeZero
collectionView!.collectionViewLayout.outgoingAvatarViewSize = CGSizeZero
// Remove file upload icon
self.inputToolbar.contentView.leftBarButtonItem = nil;
messageRef = rootRef.child("messages")
locationRef = rootRef.child("locations")
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
observeMessages()
}
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//--- CLGeocode to get address of current location ---//
CLGeocoder().reverseGeocodeLocation(manager.location!, completionHandler: {(placemarks, error)->Void in
if let pm = placemarks?.first
{
self.displayLocationInfo(pm)
}
})
}
func displayLocationInfo(placemark: CLPlacemark?)
{
if let containsPlacemark = placemark
{
//stop updating location
locationManager.stopUpdatingLocation()
self.city = (containsPlacemark.locality != nil) ? containsPlacemark.locality! : ""
self.state = (containsPlacemark.administrativeArea != nil) ? containsPlacemark.administrativeArea! : ""
self.country = (containsPlacemark.country != nil) ? containsPlacemark.country! : ""
print(getLocation())
}
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("Error while updating location " + error.localizedDescription)
}
override func collectionView(collectionView: JSQMessagesCollectionView!,
messageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageData! {
return messages[indexPath.item]
}
override func collectionView(collectionView: JSQMessagesCollectionView!,
messageBubbleImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageBubbleImageDataSource! {
let message = messages[indexPath.item] // 1
if message.senderId == senderId { // 2
return outgoingBubbleImageView
} else {
return incomingBubbleImageView
}
}
override func collectionView(collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return messages.count
}
override func collectionView(collectionView: JSQMessagesCollectionView!,
avatarImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageAvatarImageDataSource! {
return nil
}
private func setupBubbles() {
let factory = JSQMessagesBubbleImageFactory()
outgoingBubbleImageView = factory.outgoingMessagesBubbleImageWithColor(
UIColor.jsq_messageBubbleBlueColor())
incomingBubbleImageView = factory.incomingMessagesBubbleImageWithColor(
UIColor.jsq_messageBubbleLightGrayColor())
}
func addMessage(id: String, text: String) {
let message = JSQMessage(senderId: id, displayName: "", text: text)
messages.append(message)
}
override func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = super.collectionView(collectionView, cellForItemAtIndexPath: indexPath)
as! JSQMessagesCollectionViewCell
let message = messages[indexPath.item]
if message.senderId == senderId {
cell.textView!.textColor = UIColor.whiteColor()
} else {
cell.textView!.textColor = UIColor.blackColor()
}
return cell
}
override func didPressSendButton(button: UIButton!, withMessageText text: String!, senderId: String!,
senderDisplayName: String!, date: NSDate!) {
let itemRef = messageRef.childByAutoId()
let messageItem = [
"text": text,
"senderId": senderId
]
itemRef.setValue(messageItem)
let locRef = locationRef.childByAutoId()
let locItem = [
senderId : [
"location": getLocation()
]
]
locRef.setValue(locItem)
// Retrieve data from Firebase Realtime database
FIRDatabase.database().reference().child("locations").child(senderId).child("location").observeSingleEventOfType(.Value, withBlock: { (snapshot) in
self.locationId = snapshot.value!["location"] as! String
}) { (error) in
print(error.localizedDescription)
}
JSQSystemSoundPlayer.jsq_playMessageSentSound()
finishSendingMessage()
}
private func observeMessages() {
let messagesQuery = messageRef.queryLimitedToLast(25)
messagesQuery.observeEventType(.ChildAdded) { (snapshot: FIRDataSnapshot!) in
let id = snapshot.value!["senderId"] as! String
let text = snapshot.value!["text"] as! String
self.addMessage(id, text: text)
self.finishReceivingMessage()
}
}
override func textViewDidChange(textView: UITextView) {
super.textViewDidChange(textView)
}
override func collectionView(collectionView: JSQMessagesCollectionView!, attributedTextForCellBottomLabelAtIndexPath indexPath: NSIndexPath!) -> NSAttributedString! {
let message = messages[indexPath.item]
// Call data I have retrieved below with message
let text = "From: " + locationId
if message.senderId == senderId {
return nil
} else {
return NSAttributedString(string: text)
}
}
override func collectionView(collectionView: JSQMessagesCollectionView, layout collectionViewLayout: JSQMessagesCollectionViewFlowLayout, heightForCellBottomLabelAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return kJSQMessagesCollectionViewCellLabelHeightDefault
}
}
Vielen Dank für jede Hilfe im Voraus!
In welcher Zeile stürzt Ihre App ab? Woher kommt die Variable 'collectionView'? Im Allgemeinen haben Sie eine Menge Kraftauswürfe, '!' Im Code, versuchen Sie, Ihren Code zu überprüfen und umzuformen, um diese zu vermeiden. Dies wird höchstwahrscheinlich Ihren Absturz beheben – Kumuluzz