QBChat/XEP-0045/ leavRoom automatically after coming back from backbround? (Quickblox) - quickblox

When coming back from background, our app automatically reconnects to chat server and enters a room.
All goes well and the chat room history is loaded successfully. But all of a sudden we receive "QBChat/XEP-0045/ leavRoom" and can't send messages to room because "room is not joined".
Any thoughts on why this behaviour accours?

I recommend to use the next logic:
#property (strong, nonatomic) QBChatRoom *testRoom;
Join
[[QBChat instance] setDelegate:self];
[[QBChat instance] createOrJoinRoomWithName:#"myRoom" membersOnly:NO persistent:YES];
#pragma mark -
#pragma mark QBChatDelegate
- (void)chatRoomDidEnter:(QBChatRoom *)room{
// retain current room
self.testRoom = room;
}
Leave
[[QBChat instance] leaveRoom:testRoom];
#pragma mark -
#pragma mark QBChatDelegat
- (void)chatRoomDidLeave:(NSString *)roomName{
// release room
self.testRoom = nil;
}
I think your issue is with self.testRoom = nil;, you don't do it. But you should.
Try this suggestion.
http://quickblox.com/developers/SimpleSample-chat_users-ios#Joining.2Fleaving_rooms

Related

How to confirm system alert like allow notification

If the app is installed at the first time, need to allow notification, how can I confirm it? Is someone encountered?
you should typically be mocking notifications and other data requests in order to prevent the dialogs from coming up. You could also accept the notification manually and re-run your tests. We experimented with using the private UIAutomation framework for this and saw we could achieve this with it. For example, for pressing the left alert button.
#interface SystemAlert : NSObject
- (void)tapLeftButton;
#end
#interface SystemAlert (ForMethodCompletionOnly)
+ (id)localTarget;
- (id)frontMostApp;
- (id)alert;
- (id)buttons;
#end
#implementation SystemAlert
+ (void)load {
dlopen([#"/Developer/Library/PrivateFrameworks/UIAutomation.framework/UIAutomation" fileSystemRepresentation], RTLD_LOCAL);
}
- (void)tapLeftButton {
id localTarget = [NSClassFromString(#"UIATarget") localTarget];
id app = [localTarget frontMostApp];
id alert = [app alert];
id button = [[alert buttons] objectAtIndex:0];
[button tap];
}
#end

NSSpeechRecognizer and .delegate=self; Problems

I've run into an issue with this little Objective-C project I'm doing and it's proving to be a bit of a roadblock. I'm playing around with Apple's NSSpeechRecognizer software on El Capitan, and I'm trying to get this guy running properly so that when the riddle I give it is posed to the user, the user can respond with a word to "do something cool". As it stands right now, the delegate method:
-(void) speechRecognizer:(NSSpeechRecognizer *)sender didRecognizeCommand:(NSString *)command { ... }`
is never even called, even though it appears the recognition icon is correctly detecting the answer to the riddle.
The problem is that your main function has a loop that is continually checking whether the speech has been recognizing. You are not giving NSSpeechRecognizer a chance to actually deliver any messages to you.
Your app needs to let the main "run loop" run, so it can deliver messages. Normally, in an OS X app, your main would just call NSApplicationMain, which does this for you.
Your code is effectively this:
#interface RecognizerDelegate : NSObject <NSSpeechRecognizerDelegate>
#property (nonatomic) NSSpeechRecognizer *recognizer;
#property (nonatomic) BOOL didRecognize;
#end
#implementation RecognizerDelegate
- (id)init
{
if ((self = [super init])) {
self.didRecognize = NO;
self.recognizer = [[NSSpeechRecognizer alloc] init];
self.recognizer.listensInForegroundOnly = NO;
self.recognizer.blocksOtherRecognizers = YES;
self.recognizer.delegate = self;
self.recognizer.commands = #[ #"hello" ];
[self.recognizer startListening];
}
return self;
}
- (void)speechRecognizer:(NSSpeechRecognizer *)sender didRecognizeCommand:(NSString *)command
{
self.didRecognize = YES;
}
#end
int main(int argc, const char * argv[])
{
#autoreleasepool
{
RecognizerDelegate *recognizerDelegate = [[RecognizerDelegate alloc] init];
while (recognizerDelegate.didRecognize == NO) {
// do nothing
}
NSLog(#"Recognized!");
}
return 0;
}
That while loop is doing nothing useful, just running your CPU in a loop and wasting time and energy. You are not letting any other code in NSSpeechSynthesizer, or any of the system frameworks like Foundation or AppKit, get the chance to do anything. So, nothing happens.
To fix this in the short term: you can let the main run loop run for a little while in each pass through the loop. This code would let the system run for a second, then would return to your code, so you could check again:
while (recognizerDelegate.didRecognize == NO) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
}
The longer-term fix would be to move your code out of main and to structure it like a real OS X app. Instead of using a loop to poll a condition like recognizerDelegate.didRecognize, you would just trigger the "next thing" directly from delegate methods like -speechRecognizer:didRecognizeCommand:, or you would use things like NSTimer to run code periodically.
For more details, see the Apple doc Cocoa Application Competencies for OS X, specifically the "Main Event Loop" section.
I had the same problem using NSSpeechRecognizer. The callback function:
func speechRecognizer(_ sender: NSSpeechRecognizer,
didRecognizeCommand command: String) {}
...was never called, even though everything appeared to be working.
There were three things I changed to get the code working.
1) I had to enable the entitlement in my "sandboxed" mode application to allow for microphone use.
... I also did these other two things, as well.
2) I added the "Privacy - Microphone Usage Description" in the info.pList, and set the string value to "I want to listen to you speak"
3) I added the "Privacy - Speech Recognition Usage Description" in the info.pList, and set the string value to "I want to write down what you say"

How to create an event loop in Objective C?

I'm trying to use the CoreBluetooth module to list all the detected Bluetooth devices in a command-line OSX application.
What I have looks like this, so far:
#import CoreBluetooth;
#interface MyCentralManager : NSObject<CBCentralManagerDelegate>
- (void) centralManagerDidUpdateState: (CBCentralManager *) central;
- (void) centralManager:(CBCentralManager *) central
didDiscoverPeripheral:(CBPeripheral *) peripheral
advertisementData:(NSDictionary *) advertisementData
RSSI:(NSNumber *)RSSI;
#end
#implementation MyCentralManager
- (void) centralManagerDidUpdateState: (CBCentralManager *) central
{
NSLog(#"State changed...");
}
- (void) centralManager:(CBCentralManager *) central
didDiscoverPeripheral:(CBPeripheral *) peripheral
advertisementData:(NSDictionary *) advertisementData
RSSI:(NSNumber *)RSSI
{
NSLog(#"Discovered %#", peripheral.name);
}
#end
int main() {
MyCentralManager* myCentralManager = [[MyCentralManager alloc] init];
CBCentralManager* cbCentralManager = [[CBCentralManager alloc] initWithDelegate:myCentralManager queue:nil options:nil];
NSLog(#"Scanning devices now !");
[cbCentralManager scanForPeripheralsWithServices:nil options:nil];
sleep(5); // Wait 5 seconds before stopping the scan.
[cbCentralManager stopScan];
NSLog(#"Scanning devices ended.");
return 0;
}
Now this doesn't work at all as I never get any "State changed..." nor "Discovered ..." log output.
I never actually written any Objective C application before so I'm probably missing the obvious. If I had to guess what I'm doing wrong I would assume that:
I actually have to wait for the CentralManager to be in the appropriate state before starting the scan.
I never actually get inside the state changed delegate method so I assume that my first mistake is: instead of just sleep()'ing, I have to run an event loop of some sort so that the underlying system has a chance to notify me of the state change.
I'm basically stuck at this point: I don't have a GUI, nor do I want one but couldn't figure out a way to run an event loop (assuming that's actually what is missing). How can I do that ?
As I said, this is actually my first attempt with Objective C, so don't be afraid to state the obvious.
Simply run the thread's run loop
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:5]];
More information here.
BTW: You do not have to declare the methods already declared in the protocol.

Automatic chatroomDidLeave after chatDidFail. Why? Oh why? [Quickblox]

Every time we try to reconnect after a chatDidFail event, we:
login in chat
enter room
automatically get kicked out of the the room (chatRoomDidLeave event)
when we try to re-join the room, we get kicked out again (chatRoomDidLeave)
and it loops
why, oh why?
Why does Quickblox kicks us out of any room after we try to reconnect following a chatDidFail event?
All we do is:
-(void)chatDidFailWithError:(int)code
{
[[QBChat instance] loginWithUser:currentUser];
}
- (void)chatRoomDidLeave:(NSString *)roomName
{
[[QBChat instance] createOrJoinRoomWithName:#"roomName" membersOnly:NO persistent:YES];
}
We're running out of ideas on this one...
I managed to resolve this. It seems that Quickblox chat implementation isn't able to recover on it's own, when the application goes background and you don't leave the chat room.
This can be solved by having the ChatManager (your own singleton class used to manage chat connections) to store the currently shown room (self.currentRoom) and automatically leave the room, and log out when application resigns active. And when the application will enter foreground, you log in and rejoin the room.
Add these to the singleton class (id)init:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleApplicationWillResignActiveNotification:) name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleApplicationEnterForegroundNotification:) name:UIApplicationWillEnterForegroundNotification object:nil];
And the property implementation for the current room:
#property (nonatomic, strong) QBChatRoom *currentRoom;
And then implement the corresponding handlers (you can also invalidate the presence timer here):
- (void)handleApplicationWillResignActiveNotification:(NSNotification *)notification
{
lg(#"Application resigning active");
if (self.currentRoom) {
if (self.presenceTimer) {
[self.presenceTimer invalidate];
self.presenceTimer = nil;
}
[self leaveRoom:self.currentRoom clearRoom:NO];
[[QBChat instance] logout];
}
}
- (void)handleApplicationEnterForegroundNotification:(NSNotification *)notification
{
lg(#"Application entering foreground.");
if (![[QBChat instance] loginWithUser:self.currentUser]) {
lg(#"Logging in failed for some reason.");
}
}
Then in chatDidLogin you do the following:
- (void)chatDidLogin
{
...
if (self.currentRoom) {
lg(#"Auto-joining current room.");
[self joinRoom:self.currentRoom completionBlock:nil];
}
...
}
Store the room reference when you enter a room:
- (void)chatRoomDidEnter:(QBChatRoom *)room
{
...
self.currentRoom = room;
...
}
Make sure that you don't clear self.currentRoom when you leave the room on UIApplicationWillResignActiveNotification, so that there's a reference for the current room when the application comes foreground.

Countdown timer using NSTimer in "0:00" format

I have been researching for days on how to do this and nobody has an answer.
I am creating an app with 5 timers on the same view.
I need to create a timer that counts down from "15:00" (minutes and seconds), and, another that counts down from "2:58" (minutes and seconds). The 15 minute timer should not repeat, but it should stop all other timers when it reaches "00:00." The "2:58" timer should repeat until the "15:00" or "Game Clock" reaches 0. Right now, I have scrapped almost all of my code and I'm working on the "2:58" repeating timer, or "rocketTimer."
Does anyone know how to do this?
EDIT 2:
My simulator will not even run the app so I currently have no idea if the timer is actually working or not, but from my previous attempts, it has not worked. It doesn't show up in the format that I want and it counts down by 2's (from the last time it actually worked). The problem is, also, that I'm not fluent in objective-C. I can write pseudocode all day, just like everyone else, but I cannot put what I want into code because I do not fully understand the NSTimer.
EDIT:
In my output, I get this error "terminate called after throwing an instance of 'NSException'"
and this error?
Here is my code:
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController {
//Rocket Timer
int totalSeconds;
bool timerActive;
NSTimer *rocketTimer;
IBOutlet UILabel *rocketCount;
int newTotalSeconds;
int totalRocketSeconds;
int minutes;
int seconds;
}
- (IBAction)Start;
#end
and my .m
#import "FirstViewController.h"
#implementation FirstViewController
- (NSString *)timeFormatted:(int)newTotalSeconds
{
int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
return [NSString stringWithFormat:#"%i:%02d"], minutes, seconds;
}
-(IBAction)Start {
newTotalSeconds = 178; //for 2:58
newTotalSeconds = newTotalSeconds-1;
rocketCount.text = [self timeFormatted:newTotalSeconds];
if(timerActive == NO){
timerActive = YES;
newTotalSeconds = 178;
[rocketTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timerLoop) userInfo:nil repeats:YES];
}
else{
timerActive = NO;
[rocketTimer invalidate];
rocketTimer = nil;
}
}
-(void)timerLoop:(id)sender {
totalSeconds = totalSeconds-1;
rocketCount.text = [self timeFormatted:totalSeconds];
}
- (void)dealloc
{
[super dealloc];
[rocketTimer release];
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
timerActive = NO;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
There are a few problems with your code!
The bad news is, that none of them relate to the crash you are seeing.
The first and most obvious problem
Actually, you never stop your countdown!
After you've scheduled the timer in Start, your timerLoop:-method will be called every second. But you forgot to check whether totalSeconds has become negative...
The second problem
-(NSString *)timeFormatted:(int)newTotalSeconds will not work the way you expect it to! Actually, I'm pretty damn sure that Xcode gives you a compiler warning stating "Local declaration of 'newTotalSeconds' hides instance variable".
Try it out: In Start, replace the line rocketCount.text = [self timeFormatted:newTotalSeconds]; with the line rocketCount.text = [self timeFormatted:42]; and set a breakpoint after it.
The third problem (which actually are a couple of problems in one place)
Your dealloc is plain wrong:
First and foremost, it's not the best idea to have any calls after [super dealloc]. Second, "ur doin it wrong": Considering your Start-method, you don't own the timer so you must not release it. Instead, if the timer was still valid, you'd need to invalidate it. But this won't even become a problem, because as long as rocketTimer is scheduled, your viewController will not be dealloced (unless you have an error within your memory-management elsewhere). I've written a fairly complete example explaining this behavior in an earlier post.
So, what caused the crash?
Honestly:
No clue!
In order to find out what exactly went wrong, try adding a breakpoint to -[NSException raise]. Alternatively, you can modify the main function in main.m to be the following:
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int response;
#try {
response = UIApplicationMain(argc, argv, nil, nil);
} #catch (NSException *e) {
NSLog(#"%#: %#\nCall-stack:\n%#", [e name], [e reason], [e callStackSymbols]);
response = 1;
}
return response;
}
That will tell you in which method your program actually crashed.
Where is rocketTimer instantiated? You seem to have left that very important detail out. My guess is that rocketTimer isn't being correctly retained by your code and that is causing your crash when trying to access that object after it has been deallocated.
I'd suggest synthesizing your property and then using the built-in setting by setting self.rocketTimer when you initialize.
FirstViewController.h
#interface FirstViewController : UIViewController {
NSTimer *rocketTimer;
}
#property (nonatomic, retain) NSTimer *rocketTimer;
- (IBAction)Start;
#end
FirstViewController.m
#implementation FirstViewController
#synthesize rocketTimer;
// test of implementation
// ...
If the problem is that it's not repeating, i'd let the timerLoop method check the value of totalSeconds before substracting. If it's 0, let it set it to 178 again.
If the problem lies somewhere else, please tell us where, and give us a little more information on what the problem is and what you've tried already next time.