i am making a chat app with xmpp framework.
I have setup XMPPFramework in my project by referring this link:- http://code.tutsplus.com/tutorials/building-a-jabber-client-for-ios-xmpp-setup--mobile-7190
In this message sending is working perfectly and in receive message it is show in alertview as it is in code. When message received this method is calling which is in Appdelegate.m file:-
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{ DDLogVerbose(#"%#: %#", THIS_FILE, THIS_METHOD);
// A simple example of inbound message handling.
if ([message isChatMessageWithBody])
{
XMPPUserCoreDataStorageObject *user = [xmppRosterStorage userForJID:[message from]
xmppStream:xmppStream
managedObjectContext:[self managedObjectContext_roster]];
NSString *body = [[message elementForName:#"body"] stringValue];
NSString *displayName = [user displayName];
if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:displayName
message:body
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
}
else
{
// We are not active, so use a local notification instead
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.alertAction = #"Ok";
localNotification.fireDate=[NSDate dateWithTimeIntervalSinceNow:1.0];
localNotification.alertBody = [NSString stringWithFormat:#"From: %#\n%#",displayName,body];
NSLog(#"localNotification.alertBody:-%#",localNotification.alertBody);
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
}
}
}
And i want to show that received messages in conversation view (in tableview) which is in an other class.
Here the code which is displaying send messages in tableview
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell=nil;
cell=[tableView dequeueReusableCellWithIdentifier:#"MessageCellIdentifier" forIndexPath:indexPath];
cell.textLabel.text=[[messages objectAtIndex:indexPath.row] objectForKey:#"msg"];
cell.detailTextLabel.text=#"You";
cell.textLabel.textAlignment=NSTextAlignmentRight;
return cell;
}
So, my question is how to take that received messages in array or in dictionary and take that to tableview cell for row at indexpath to show in tableview.
As far as I understand, you want to display a chat view between two people ?
I made a Swift Wrapper around the XMPPFramework, it uses JSQMessageViewController for the UI.
It will simplify the development of a basic chat app.
You can check it out here.
Related
I am working on Homekit iOS app. I have a question that I have an accessory and When I change its power characteristic value using the HomeKit Simulator the delegates of HMAccessory are caliing but in case If I change the powr characteristic value programmatically (Using the writevalue ) the delegate methods are not being called. Please let me know any ideas of suggestions.
Code
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
selectedDevice.delegate = self;
}
HMAccessoryDelegate
- (void)accessory:(HMAccessory *)accessory service:(HMService *)service didUpdateValueForCharacteristic:(HMCharacteristic *)characteristic;
{
NSLog(#"changed");
}
Write Function
UISwitch *sw = [[UISwitch alloc] initWithFrame:CGRectMake(230, 5, 51, 31)];
[cell addSubview:sw];
sw.on = YES;
[sw addTarget:self action:#selector(updateState:) forControlEvents:UIControlEventValueChanged];
-(void)updateState:(UISwitch*)sender
{
HMCharacteristic *characteristic = self.selectedService.characteristics[tag];
[characteristic enableNotification:YES completionHandler:^(NSError *error)
{
if(!error)
{
}
}];
if([characteristic.characteristicType isEqualToString:HMCharacteristicTypePowerState])
{
id val = characteristic.value;
NSString *str = [NSString stringWithFormat:#"%#",val];
if([str isEqualToString:#"0"])
{
id a = characteristic.value;
BOOL b = [a boolValue];
NSNumber *c = [NSNumber numberWithBool:!b];
AppDelegate *appDel = [[UIApplication sharedApplication] delegate];
[characteristic writeValue:c completionHandler:^(NSError *error) {
if (error) {
UIAlertView *alertController = [[UIAlertView alloc] initWithTitle:#"Error" message:[appDel handleErrorCodes:error.code] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alertController show];
return;
}
else
{
[serviceCharacteristicsTableView reloadData];
}
}];
}
}
Please let me know if I am not clear
The documentation says that the delegate method is not called when you set the value programatically:
This method is called as a result of a change in value initiated by
the accessory. Programmatic changes initiated by the app do not result
in this method being called.
If you want to do something after writing the characteristic's value succeeded (or failed), you can do it in the completionHandler: block of writeValue:completionHandler: method.
I have an UITableView, with cells that you can tap on.
When you tap, some actions are run, but that is not important in this context. First time I press, it handles the tap correctly. Second time it is running the code, but all View updates like showing a UIAlertView or showing a new view is delayed. But not delayed by time - It's waiting for me to touch the screen. No matter where I press or how long I wait, I just have to press. And it's every time but the first.
My TableView is set to single selection and not to show selection on touch. Any Ideas why it does this?
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([cell isKindOfClass:[DetailTableViewCell class]]) {
DetailTableViewCell *detailCell = (DetailTableViewCell *)cell;
NSString *hourString = [detailCell hourString];
if (!detailCell.booking) {
NSDate *rightNow = [NSDate new];
NSDate *cellDate = [self.currentDate dateWithHour:indexPath.row andMinutes:0];
// Only allow future bookings (but allow people people to book within the hour)
if([rightNow compare:[cellDate nextHour]] == NSOrderedAscending){
[self performSegueWithIdentifier:#"roomBooking" sender:indexPath];
return;
} else {
[[[UIAlertView alloc] initWithTitle:#"Error" message:#"We currently do not allow our users make bookings in the past" delegate:nil cancelButtonTitle:#"Gotcha" otherButtonTitles:nil] show];
return;
}
} else if ([detailCell.booking hasPhoneNumber]) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:#"telprompt://%ld",(long)[detailCell.booking telephone]]]];
return;
} else {
//TODO: FIND OUT IF BOOKING IS OWNED BY THE CURRENT USER
[[[UIAlertView alloc] initWithTitle:#"Booking"
message:[NSString stringWithFormat:#"You are now removing the booking at %#.", hourString]
delegate:nil
cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
#weakify(self);
[self.room removeBookingWithId:[detailCell.booking.bookingId integerValue] andCompletion:^(BOOL success, NSError *error) {
#strongify(self);
if (success) {
#weakify(self);
[self.room.location updateBookingsWithCompletion:^(BOOL success, NSError *error) {
#strongify(self);
if (success) {
[self.calendar reloadData];
}
}];
}
}];
return;
}
}
}
SelectionStyle was set to None, but we changed it to something else, which solved the problem.
Click on the TableViewCell itself.
In your properties section locate: "Selection"
Set to: Blue/Grey/Default.
I'm making a UITableView where you can click on a tableviewcell and this should trigger a phone call to a phone number in an array.
The phone numbers are listed in an array, and these are also shown in the tableviewcell.
_Number = #[#"100",
#"101",
#"070 245 245"];
I'm new at this and I don't know how to start with this, I already got my tableviewcontroller and tableviewcell classes which are working.
Gratz and thanks in advance
You can do following :
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *phoneNumber = [Number objectAtIndex:indexPath.row];
NSURL *phoneNumberURL = [NSURL URLWithString:[NSString stringWithFormat:#"tel:%#", phoneNumber]];
if( [[UIApplication sharedApplication] canOpenURL:phoneNumberURL] )
{
[[UIApplication sharedApplication] openURL:phoneNumberURL];
}
else
{
UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:#"Alert!!!" message:#"Not able to make a phone call." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
}
I'm using apple push notification service in my project.
Please follow the 2 ways of opening the app and handling this push notifications. In the second scenario I do not know how to handle it. Do you know how?
The push notification arrived to my device,
Scenario 1:
I clicked on the push notification.
The - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo function AppDelegate.m file catches this function.
Scenario 2:
I normally opened the device (by clicking on the app)
How can I handle the push notification?
The other answers show how to get the notification data when the user taps the notification.
The difference between the two nethods shown is that one is called when app is already running, either in foreground or background, while the other is called when app is not running at all.
On your second case, when the user doesn't tap the notification, the notification data isn't passed to the app when you open it with the launch Icon.
First scenario:
- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo
{
NSLog (#"APNS: notification received: %#", userInfo);
NSString *message = nil;
id alert = [userInfo objectForKey:#"aps"];
if ([alert isKindOfClass:[NSString class]])
{
message = alert;
}
else if ([alert isKindOfClass:[NSDictionary class]])
{
message = [alert objectForKey:#"alert"];
}
if (message)
{
if (![message isEqualToString:#""])
{
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle: #"notification"
message: message
delegate: nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
}
}
Second scenario:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSLog (#"LAUNCH OPTIONS: %#",launchOptions);
id remoteNotificationValue = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (remoteNotificationValue)
{
NSString *message = nil;
id alert = [remoteNotificationValue objectForKey:#"aps"];
if ([alert isKindOfClass:[NSString class]])
{
message = alert;
}
else if ([alert isKindOfClass:[NSDictionary class]])
{
message = [alert objectForKey:#"alert"];
}
if (message)
{
if (![message isEqualToString:#""])
{
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle: #"notification"
message: message
delegate: nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
}
}
....
Of course you might want to make a special method that handles notifications and is called from both scenarios (with NSDictionary * parameter) so your code would be more readable. Sometimes APNS notifications are useful also when app is running - empty notification (with no payload) might be used to trigger the data synchronization with server to avoid polling for example.
You can get the arrived notifications when the app starts with the following code (e.g: in application:didFinishLaunchingWithOptions):
NSDictionary *remoteNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
Here is a more thorough explanation: How to manage notification when users click on badge
You can handle that like this
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Checking if app was launched from the notification
if (launchOptions != nil) {
NSDictionary *dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (dictionary != nil){
// Read dictionary and do something since the app
// was launched from the notification.
}
}
Here is an example of what the dictionary object contains
NSString *message = #"";
NSString *badge = #"";
NSString *sound = #"";
if([dictionary objectForKey:#"alert"]) {
message = [dictionary objectForKey:#"alert"];
}
if([dictionary objectForKey:#"badge"]) {
badge = [dictionary objectForKey:#"badge"];
}
if([dictionary objectForKey:#"sound"]) {
sound = [dictionary objectForKey:#"sound"];
}
Hope it helps!
I am new to ios and PNS, i am working on push notification in which i am getting URL in notification based on this i need to show image into image view. i got PNS succesfully also got URL using payload but its not showing in image view in another class
Below is code i am using
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo {
if (application.applicationState == UIApplicationStateActive) // If app is running and you got notification then show it
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Did receive a Remote Notification" message:[NSString stringWithFormat:#"You Have a Notification :\n%#",userInfo[#"aps"][#"alert"]]delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
NSLog(#"Payload: %#", userInfo);
imageURL = userInfo[#"aps"][#"alert"];
MainViewController *mv = [[MainViewController alloc] init];
[mv.ansinage setImage:[UIImage imageNamed:#"cartoon.png"]]; // Right now i am setting image in resource but still not setting in mainviewcontrller when i am open app
}
-(void) sshowansimage:(NSString *) strImageURL{
NSURL *imageURL = [NSURL URLWithString:strImageURL];
NSLog(#"coming URL is %#", strImageURL);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSData *imageData = [NSData dataWithContentsOfFile:strImageURL];
[self performSelectorOnMainThread:#selector(showImage:) withObject:imageData waitUntilDone:YES];
});
}
-(void)showImage:(NSData*)imageAsData
{
NSLog(#"IN image view mthhod data is %d",imageAsData.length);
ansinage.image = [UIImage imageWithData:imageAsData];
}