最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

[已解决]SwiftXMPP调试:没有执行到didReceivePresence和didReceiveMessage

XMPP crifan 3260浏览 0评论
用swift代码去调试SwiftXMPP:
[记录]swift中添加支持聊天框架XMPP
输入了正确的用户名和密码,但是最后代码没有其他反应。
感觉像是:
没有执行对应的didReceivePresence和 didReceiveMessage
[iPhone高级] 基于XMPP的IOS聊天客户端程序(全)【转】_sdglyuan00_新浪博客
好像是:
感觉是:
xmppStreamDidAuthenticate
没有被调用到
-》所以也没用调用到goOnline
后来把:
curXmppStream!.hostName = "localhost"

改为:

        print("server=\(server)") //Optional("192.168.1.110")
        if server != nil{
            loginServer = server!
        }
//        curXmppStream!.hostName = "localhost"
        curXmppStream!.hostName = server!
然后可以执行到:
    func xmppStreamDidConnect(sender: XMPPStream) {
           print("xmppStreamDidConnect")
        isOpen = true
        var error: NSError?
        do{
            try curXmppStream!.authenticateWithPassword(password)

            print("authentification successful")
        }catch{
            print("authentification error=\(error)")
        }
    }

但是没有执行到:

    func xmppStreamDidAuthenticate(sender: XMPPStream) {
        print("didAuthenticate")
        goOnline()
    }
搜:
xmpp xmppStreamDidAuthenticate not called
参考:

再次尝试登陆:
        do{
            try curXmppStream!.authenticateWithPassword(password)

            print("authentification successful")

            //second try
            do{
                try curXmppStream!.authenticateWithPassword(password)

                print("authentification successful")

                //second try

            }catch let error{
                print("authentification error=\(error)")
            }

        }catch let error{
            print("authentification error=\(error)")
        }

结果出错:

authentification error=Error Domain=XMPPStreamErrorDomain Code=1 "Please wait until the stream is connected." UserInfo={NSLocalizedDescription=Please wait until the stream is connected.}

找到代理函数定义了:

/**
 * This method is called after the XML stream has been fully opened.
 * More precisely, this method is called after an opening <xml/> and <stream:stream/> tag have been sent and received,
 * and after the stream features have been received, and any required features have been fullfilled.
 * At this point it's safe to begin communication with the server.
**/
- (void)xmppStreamDidConnect:(XMPPStream *)sender;

/**
 * This method is called after registration of a new user has successfully finished.
 * If registration fails for some reason, the xmppStream:didNotRegister: method will be called instead.
**/
- (void)xmppStreamDidRegister:(XMPPStream *)sender;

/**
 * This method is called if registration fails.
**/
- (void)xmppStream:(XMPPStream *)sender didNotRegister:(NSXMLElement *)error;

/**
 * This method is called after authentication has successfully finished.
 * If authentication fails for some reason, the xmppStream:didNotAuthenticate: method will be called instead.
**/
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender;
现在出现另外的问题:
xmppStreamDidConnect被调用了两次
到此第二次调用时出现上面的错误:UserInfo={NSLocalizedDescription=Please wait until the stream is connected.}
搜:
xmpp xmppStreamDidConnect called twice
参考:
搜:
swift xmppStreamDidAuthenticate
后来参考:
添加didNotAuthenticate:
//    //func xmppStream:(XMPPStream *)sender didNotAuthenticate:(NSXMLElement *)error;
//    @objc func xmppStream(sender: XMPPStream?, didNotAuthenticate: NSXMLElement?) {
//
//    }
    func xmppStream(sender: XMPPStream!, didNotAuthenticate error: DDXMLElement!)
    {
        print("didNotAuthenticate")
        print("error=\(error)") //error=<failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><not-authorized/></failure>
    }
此处:
服务器已经挂了
然后对于authenticateWithPassword,也还是返回true的。。。
然后此处didNotAuthenticate会返回:
<failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><not-authorized/></failure>
然后等openfire服务器正常后,还是上述错误。
添加了端口:
        curXmppStream?.hostPort = 7070
后,didNotAuthenticate没有再被执行到。
但是其他的
xmppStreamDidAuthenticate
以及:
didReceiveMessage
didReceivePresence
也都没有被执行到。。。
参考:
然后继续调试。
然后用代码:
//
//  AppDelegate.swift
//  SwiftXMPP
//
//  Created by Felix Grabowski on 10/06/14.
//  Copyright (c) 2014 Felix Grabowski. All rights reserved.
//

import UIKit

@available(iOS 8.0, *)
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, XMPPStreamDelegate {

    var window: UIWindow?
    var viewController: BuddyListViewController?
    var password: String = ""
    var isOpen: Bool = false
    var curXmppStream: XMPPStream?
     var chatDelegate: ChatDelegate?
     var messageDelegate: MessageDelegate?
    var loginServer: String = ""


    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }

    func applicationWillResignActive(application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }

    func applicationWillEnterForeground(application: UIApplication) {
        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(application: UIApplication) {
        print("applicationDidBecomeActive")
        self.connect()
    }

    func applicationWillTerminate(application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }


    func setupStream() {
        print("setupStream")
        curXmppStream = XMPPStream()

        curXmppStream!.addDelegate(self, delegateQueue: dispatch_get_main_queue())
    }

    func connect() -> Bool {
        print("connecting")
        setupStream()

        //NSUserDefaults.standardUserDefaults().setValue("[email protected]", forKey: "userID")
        let b = NSUserDefaults.standardUserDefaults().stringForKey("userID")
        print("user defaults: " + "\(b)") //Optional("[email protected]")

        let jabberID: String? = NSUserDefaults.standardUserDefaults().stringForKey("userID")
        print("jabberID=\(jabberID)") //Optional("[email protected]")
        let myPassword: String? = NSUserDefaults.standardUserDefaults().stringForKey("userPassword")
        print("myPassword=\(myPassword)") //Optional("password1")
        let server: String? = NSUserDefaults.standardUserDefaults().stringForKey("loginServer")
        print("server=\(server)") //Optional("192.168.1.110")
        if server != nil{
            loginServer = server!
        }
//        curXmppStream!.hostName = "localhost"
        curXmppStream!.hostName = server!
//        curXmppStream?.myJID.domain = "localhost"
        //curXmppStream!.hostPort = 5222
        //curXmppStream!.hostPort = 7070

        print("curXmppStream=\(curXmppStream)") //Optional(<XMPPStream: 0x7fd0f8feb950>)

        if let stream = curXmppStream {
            if !stream.isDisconnected() {
                return true
            }

            if jabberID == nil || myPassword == nil{
                print("no jabberID set:" + "\(jabberID)")
                print("no password set:" + "\(myPassword)")
                return false
            }

            stream.myJID = XMPPJID.jidWithString(jabberID)
            password = myPassword!

            do{
                try stream.connectWithTimeout(XMPPStreamTimeoutNone)
            }catch let error{
                let alert = UIAlertController(title: "Alert", message: "Cannot connect to : \(error)", preferredStyle: UIAlertControllerStyle.Alert)

                alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))
                self.window?.rootViewController?.presentViewController(alert, animated: true, completion: nil)

                return false
            }

        }
        return true
    }

    func disconnect() {
        goOffline()
        curXmppStream!.disconnect()
        print("disconnecting")
    }

    func goOffline() {
        print("goOffline")
        let presence = XMPPPresence(type: "unavailable")
        curXmppStream!.sendElement(presence)
    }

    func goOnline() {
        let presence = XMPPPresence()
        //        let presence = XMPPPresence(type: "away")
        curXmppStream!.sendElement(presence)
    }


    func xmppStreamDidConnect(sender: XMPPStream) {
        print("xmppStreamDidConnect")
        isOpen = true
        do{
            try curXmppStream!.authenticateWithPassword(password)
            print("authentification successful")
        }catch let error{
            print("authentification error=\(error)")
        }
    }

    func xmppStreamDidAuthenticate(sender: XMPPStream) {
        print("didAuthenticate")

        print("sender.isAuthenticated()=\(sender.isAuthenticated())") //true
        print("sender.myJID=\(sender.myJID)") //[email protected]/8f0a93af
        print("sender.myJID.domain=\(sender.myJID.domain)") //192.168.1.110
        print("sender.myJID.domainJID()=\(sender.myJID.domainJID())") //192.168.1.110

        goOnline()
    }

    func xmppStream(sender: XMPPStream!, didNotAuthenticate error: DDXMLElement!)
    {
        print("didNotAuthenticate")
        print("error=\(error)") //error=<failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><not-authorized/></failure>
        print("sender.myJID=\(sender.myJID)") //[email protected]
        print("sender.myJID.domain=\(sender.myJID.domain)") //192.168.1.110
        print("sender.myJID.domainJID()=\(sender.myJID.domainJID())") //192.168.1.110
    }

    //when receive add friend request
    func xmppStream(sender: XMPPStream!, didReceivePresenceSubscriptionRequest presence: XMPPPresence!)
    {
        print("didReceivePresenceSubscriptionRequest")
        print("sender=\(sender), presence=\(presence)")
    }

    //when send new message to friend
    func xmppStream(sender: XMPPStream!, didSendMessage message: XMPPMessage!) {
        print("Did send message \(message)")
    }

    //when receive new message from friend
    func xmppStream(sender: XMPPStream?, didReceiveMessage: XMPPMessage?) {
        if let message:XMPPMessage = didReceiveMessage {
            print("message: \(message)")
            if let msg: String = message.elementForName("body")?.stringValue() {
                if let from: String = message.attributeForName("from")?.stringValue() {
                    let m: NSMutableDictionary = [:]
                    m["msg"] = msg
                    m["sender"] = from
                    print("messageReceived")
                    if messageDelegate != nil
                    {
                    messageDelegate!.newMessageReceived(m)
                    }
                }
            } else { return }
        }
    }

    //when receive friend become online
    func xmppStream(sender: XMPPStream?, didReceivePresence: XMPPPresence?) {
        print("didReceivePresence")

        if let presence = didReceivePresence {
            let presenceType = presence.type()
            let myUsername = sender?.myJID.user
            let presenceFromUser = presence.from().user

         print(chatDelegate)
            if chatDelegate != nil {

                if presenceFromUser != myUsername {
                    if presenceType == "available" {
                        chatDelegate?.newBuddyOnLine("\(presenceFromUser)" + "@" + "\(loginServer)")
                    } else if presenceType == "unavailable" {
                        chatDelegate?.buddyWentOffline("\(presenceFromUser)" + "@" + "\(loginServer)")
                    }
                }
            }
            print(presenceType)
        }
    }

//    func xmppRoster(sender: XMPPRoster!, didReceiveRosterItem item: DDXMLElement!) {
//        print("Did receive Roster item")
//    }


}
正常执行后,代码中也执行到了:
didReceivePresence
swiftxmpp run into didReceivePresence
Mac下的Aduim中,可以获得用户上线通知了:
mac adium can got online notice
点击通知可以进入聊天窗口:
adium chat with test user 2
然后停止调试代码,则Adium中也可以检测到用户下线了:
adium test user 2 got offline
然后经过调试,终于可以显示出buddy用户列表了:
after debug show buddy list
然后对于SwiftXMPP的demo的代码经过一定修改:
主要是:
ChatViewController.swift
中的cellForRowAtIndexPath:
  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
    print("ChatViewController cellForRowAtIndexPath")

    let s = messages.objectAtIndex(indexPath.row) as! NSDictionary
    let cellIdentifier = "MessageCellIdentifier"
    var cell:UITableViewCell? = tableView.dequeueReusableCellWithIdentifier(cellIdentifier)! as UITableViewCell
    if !(cell != nil) {
      cell = UITableViewCell(style: .Value1, reuseIdentifier: cellIdentifier)
    }

    if let c = cell {
//      println(s)
      c.textLabel!.text = s["msg"] as? String
      c.detailTextLabel!.text = s["sender"] as? String
      c.accessoryType = .None
      c.userInteractionEnabled = false
    }

    return cell!
  }
中的:
MessageCellIdentifier
c.detailTextLabel!.text
实际上此处的Storyboard中是没有对应的cell的,所以去添加上:
add tableviewcell title subtitle and text
找到:
Main.Storyboard中的Chat View Controller中的TView,然后在其中,
参考上面的Buddy的List View的也有个UserCellIdentifier
去给Chat也加一个TableViewCell,从右下角的地方拖动过来一个,放到TView的下面子节点
然后再去设置:
Identified设置为,代码中的,MessageCellIdentifier-》代码中才能用tableView.dequeueReusableCellWithIdentifier(“MessageCellIdentifier”)
Style设置为Subtitle-》这样代码cell中才有detailText可用。
最后调试使得部分的逻辑跑通了:
adium and iOS simulator can send and receive messag ok for swiftxmpp
即:
从别的客户端,比如Mac的Aduim中发送消息,iOS模拟器中,即代码中,是可以收到消息的
但是:从(iOS模拟器中点击发送内容)代码中发送数据,到对应用户,在其他客户端中,却没有收到消息。。
但是也还是先把现在,部分可用的项目,打包,留存与此:
https://github.com/crifan/SwiftXMPP_Crifan/blob/master/SwiftXMPP_CrifanLi_20151126_receiveMsgOk.zip
然后好再去解决:

转载请注明:在路上 » [已解决]SwiftXMPP调试:没有执行到didReceivePresence和didReceiveMessage

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
91 queries in 0.189 seconds, using 22.26MB memory