ios - NSStreamDelegate not receiving NSStreamEvent.HasSpaceAvailable: -



ios - NSStreamDelegate not receiving NSStreamEvent.HasSpaceAvailable: -

i had code working in project, in class next signature:

class viewcontroller: uiviewcontroller, nsstreamdelegate, uitextfielddelegate {

then moved connection it's own class, can potentially reuse in each connection:

class xmppconnection: nsobject, nsstreamdelegate

when did this, moved viewdidload() code init(). tried putting init code in separate function, , calling function after instantiating class. did not alter anything.

i can switch between 2 projects, old , new, create sure it's not server problem, , doing confirms it's not.

after each run of application, result different. either not phone call hasspaceavailable , sits there, or there (lldb) error thrown on thread 1 in class class appdelegate: uiresponder, uiapplicationdelegate, fbloginviewdelegate. error may related facebook integration though, lldb there not much at. however, each , every run, hasspaceavailable never called, unlike other project.

here's total code of nsstreamdelegate, there no confusion. class meant standard method of connection using xmpp protocol.

import uikit import foundation class xmppconnection: nsobject, nsstreamdelegate { //nsobject var input : nsinputstream? var output: nsoutputstream? //let xmlstream: string = "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' version='1.0' xmlns='jabber:client' to='mydomain.com' xml:lang='en' xmlns:xml='http://www.w3.org/xml/1998/namespace'>" allow xmlstream: string = "<stream:stream to='mydomain.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>" var xmlauth: string? allow xmlstreamend: string = "</stream:stream>" allow xmlresource: string = "<iq type='set' id='bind_1'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>oneside</resource></bind></iq>" allow xmlsession: string = "<iq type='set' id='sess_1'><session xmlns='urn:ietf:params:xml:ns:xmpp-session'/></iq>" allow xmlstarttls: string = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"; var messagestobesent:[string] = [] var lastsentmessageid = 0 var lastreceivedmessageid = 0 init(facebookid: string) { super.init() allow username = "admin@mydomain.com" //should hash device id allow password = "123456" //hash var utf8authstr = "\0\(username)\0\(password)".datausingencoding(nsutf8stringencoding) allow base64str = utf8authstr!.base64encodedstringwithoptions(nsdatabase64encodingoptions.fromraw(0)!) xmlauth = "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='plain'>\(base64str)</auth>" //println(xmlauth) self.connecttosocket("mydomain.com", port: 5222) send(self.xmlstream) //send(self.xmlstarttls) /*send(self.xmlauth!) send(self.xmlstream) send(self.xmlresource) send(self.xmlsession)*/ //sendmessage("hi") } func connecttosocket(host: string, port: int) { nsstream.getstreamstohostwithname(host, port: port, inputstream: &(self.input), outputstream: &(self.output)) self.input!.delegate = self self.output!.delegate = self self.input!.scheduleinrunloop(nsrunloop.currentrunloop(), formode: nsdefaultrunloopmode) self.output!.scheduleinrunloop(nsrunloop.currentrunloop(), formode: nsdefaultrunloopmode) self.input!.open() self.output!.open() println("connected") //let byteswritten = self.output!.write(unsafepointer(data.bytes), maxlength: data.length) //println(byteswritten) } //the delegate receives message when given event has occurred on given stream. func stream(thestream: nsstream!, handleevent streamevent: nsstreamevent) { println("message received") switch streamevent { case nsstreamevent.none: println("nsstreamevent.none") case nsstreamevent.opencompleted: println("nsstreamevent.opencompleted") case nsstreamevent.hasbytesavailable: println("nsstreamevent.hasbytesavailable") if allow inputstream = thestream as? nsinputstream { //println("is nsinputstream") if inputstream.hasbytesavailable { //println("hasbytesavailable") allow buffersize = 1024 var buffer = array<uint8>(count: buffersize, repeatedvalue: 0) var bytesread: int = inputstream.read(&buffer, maxlength: buffersize) //println(bytesread) if bytesread >= 0 { lastreceivedmessageid++ var output: string = nsstring(bytes: &buffer, length: bytesread, encoding: nsutf8stringencoding) //println("output is") println(output) } else { println("error") // handle error } } } case nsstreamevent.hasspaceavailable: println("nsstreamevent.hasspaceavailable") send(nil) //send next item //send next message or //what if there no next message send, , instead waiting user input? case nsstreamevent.erroroccurred: println("nsstreamevent.erroroccurred") case nsstreamevent.endencountered: println("nsstreamevent.endencountered") default: println("default") } } func send(message:string?){ if (self.output!.hasspaceavailable){ //stream ready input //println("true hasspaceavailable") var data:nsdata var thismessage:string if message == nil{ // no message specified if messagestobesent.count != 0{ //messages waiting sent thismessage = messagestobesent[0] info = messagestobesent[0].datausingencoding(nsutf8stringencoding, allowlossyconversion: false)! messagestobesent.removeatindex(0) } else{ //no info sent //no message specified , nil sent homecoming } } else{ thismessage = message! info = message!.datausingencoding(nsutf8stringencoding, allowlossyconversion: false)! } //println("sent following") wait() allow byteswritten = self.output!.write(unsafepointer(data.bytes), maxlength: data.length) lastsentmessageid++ //println(thismessage) //println("message sent server , response is") //println(byteswritten) //int count } else{ //steam busy println("no space available in stream") if message != nil{ messagestobesent.append(message!) } } } func sendmessage(message:string, from:string, to:string){ allow xmlmessage = "<message to='\(to)@mydomain.com' from='\(from)@mydomain.com' type='chat' xml:lang='en'> <body>\(message)</body></message>" send(xmlmessage) } func wait() { while true { //println("waiting") if lastsentmessageid == lastreceivedmessageid { break } nsrunloop.currentrunloop().rununtildate(nsdate(timeintervalsincenow: 0.1)); nsthread.sleepfortimeinterval(0.1) } } }

so can see 2 things may have caused this. either moving it's own class, , making instance of it, or alter of inheritance. thinking first possiblity, looking threading lines of code: self.input!.scheduleinrunloop(nsrunloop.currentrunloop(), formode: nsdefaultrunloopmode)

after checking streamstatus.toraw(), says 1 nsstreamstatusopening. i'm not sure if ever changes.

i reproduce problem if xmppconnection stored in local variable, e.g.

func application(application: uiapplication, didfinishlaunchingwithoptions launchoptions: [nsobject: anyobject]?) -> bool { allow conn = xmppconnection(facebookid: "...") homecoming true }

the instance deallocated when method returns. on other hand stream delegates still point instance, causes crashes. delegate property of nsstream declared as

unowned(unsafe) var delegate: nsstreamdelegate?

which swift equivalent of "assign" aka "unsafe_unretained". hence setting delegate not retain object, , deallocating object not set property nil (as weak references).

if instance stored in property, e.g.

class appdelegate: uiresponder, uiapplicationdelegate { var window: uiwindow? var conn : xmppconnection! func application(application: uiapplication, didfinishlaunchingwithoptions launchoptions: [nsobject: anyobject]?) -> bool { conn = xmppconnection(facebookid: "...") homecoming true } // ... }

then code worked correctly in test.

ios swift tcp xmpp nsstream

Comments

Popular posts from this blog

Delphi change the assembly code of a running process -

json - Hibernate and Jackson (java.lang.IllegalStateException: Cannot call sendError() after the response has been committed) -

C++ 11 "class" keyword -