Retrieve content from PubNub messages - ios

I can successfully send and receive messages with PubNub, the problem comes when i try to display content from a message and load it a UITableViewCell's UITextView.
The Second TEST LOG writes out the whole message, that i send from my iPhone (i've already tried it with the Dev Console), but after this the app crashes.
[__NSCFDictionary length]: unrecognized selector sent to instance
I know there is something wrong with a dictionary, but i can't figure it out. I'm using only one NSDictionary for the message i send via PubNub and it "arrives" to the console, therefore I think it works properly. As you can see in the code i've tried some variations, but without any success.
UPDATE
It's working if i send NSString instead of NSDictionary.
#interface ViewController ()
#property (nonatomic, strong) NSString *myIncomeMessage;
#property (nonatomic, strong) NSString *messageFromDict;
#property (nonatomic, strong) NSArray *twoChannels;
#property (nonatomic, strong) NSDictionary *messagePbnb;
//#property (nonatomic, strong) PNMessage *messageNew;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
PNChannel *channel_2 = [PNChannel channelWithName:current.username shouldObservePresence:NO];
PNChannel *channel_1 = [PNChannel channelWithName:self.messageRecipient shouldObservePresence:NO];
[PubNub subscribeOnChannels:self.twoChannels];
[PubNub requestHistoryForChannel:channel_1 from:nil to:nil limit:100 reverseHistory:YES];
[PubNub requestHistoryForChannel:channel_2 from:nil to:nil limit:100 reverseHistory:YES];
[[PNObservationCenter defaultCenter] addMessageReceiveObserver:self withBlock:^(PNMessage *message) {
NSLog(#"OBSERVER: Channel: %#, Message: %#", message.channel.name, message.message);
NSLog(#"Sample TEST LOG %#", message.message);
self.myIncomeMessage = message.message;
NSLog(#"Second TEST LOG %#", self.myIncomeMessage);
// self.messageFromDict = [NSString stringWithFormat:keyMessage, self.messagePbnb];
// self.messageFromDict = [NSString stringWithFormat:keyMessage, message];
}];
[NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(reloadTable) userInfo:nil repeats:YES];
[self setupUIForInput];
}
- (IBAction) inputContent {
NSString *messageContent = self.textView.text;
PNChannel *channel_1 = [PNChannel channelWithName:self.messageRecipient shouldObservePresence:NO];
PNChannel *channel_2 = [PNChannel channelWithName:senderUser.username shouldObservePresence:NO];
self.twoChannels = #[channel_1,channel_2];
[PubNub subscribeOnChannels: self.twoChannels];
self.messagePbnb = #{ #"keyMessage": messageContent, #"keySenderUser": self.senderUser.username, #"keyRecieverChannel": self.messageRecipient} ;
[PubNub sendMessage: self.messagePbnb toChannel:channel_1];
[PubNub sendMessage: self.messagePbnb toChannel:channel_2];
[self.textView resignFirstResponder];
[self reloadInputViews];
}
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 10;
}
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
OutputTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cellThree"];
cell.textOutput.text = self.myIncomeMessage;
-(void)reloadTable{
[tableViewThree reloadData];
}

#sabin, here is an example, using an observer -- you could do a similar thing via a delegate:
[[PNObservationCenter defaultCenter] addMessageReceiveObserver:self
withBlock:^(PNMessage *message) {
id messageData = message.message;
if ([messageData isKindOfClass:[NSDictionary class]]) {
NSString *messageString = [NSString stringWithFormat:#"foo: %#, and bar: <%#>",
[(NSDictionary *)messageData valueForKey:#"foo"],
[(NSDictionary *)messageData valueForKey:#"bar"]];
}
}];
If you then published this from the Web Console (pubnub.com/console):
{"foo":"hey", "bar":"you!"}
You would be able to render a string from the above code (via messageString) that looked like this:
foo: hey, and bar: you!
Let me know if that helped!

Related

Multi watch interface with WatchConnectivity Context

I create an iPhone application (with a view) / Watch (with interface) that displays speed, distance and a timer with a Play / Pause, Stop and Clear.
I used to share WatchConnectivity Application Context data between (Send and receipt of Context). Everything works so far, but I would add another page / interfaces on which exchanges Watch the Context with the iPhone and there I do not know at all how.
My Interface Storyboard
If I turn on the Session 2 interfaces, information is lost
Here is my current code, I want to toggle the display of labels TimeLabel, distanceLabel Label and speed on the second interface
//
// InterfaceController.m
// Watch Extension
//
// Created by Arnaud Roy on 25/10/2015.
// Copyright © 2015 Burotica. All rights reserved.
//
#import "InterfaceController.h"
#import <WatchConnectivity/WatchConnectivity.h>
#interface InterfaceController() <WCSessionDelegate>
#property (strong, nonatomic) WCSession *session;
#property (unsafe_unretained, nonatomic) IBOutlet WKInterfaceButton *startLabel;
#property (unsafe_unretained, nonatomic) IBOutlet WKInterfaceLabel *timeLabel;
#property (unsafe_unretained, nonatomic) IBOutlet WKInterfaceLabel *distanceLabel;
#property (unsafe_unretained, nonatomic) IBOutlet WKInterfaceLabel *vitesseLabel;
#property (nonatomic,assign) BOOL running;
#end
#implementation InterfaceController
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
// Configure interface objects here.
}
- (void)willActivate {
// This method is called when watch view controller is about to be visible to user
[super willActivate];
if ([WCSession isSupported]) {
WCSession *session = [WCSession defaultSession];
session.delegate = self;
[session activateSession];
//NSLog(#"SESSION AVAIBLE");
}
//Objective-C
if ([[WCSession defaultSession] isReachable]) {
//NSLog(#"SESSION REACHABLE");
}
self.running = false;
}
- (void)didDeactivate {
// This method is called when watch view controller is no longer visible
[super didDeactivate];
}
- (IBAction)startButton {
if(self.running == false) {
[self sendCmd:#"start"];
[self.startLabel setTitle:[NSString stringWithFormat:#"PAUSE"]];
self.running = true;
}
else
{
[self sendCmd:#"pause"];
[self.startLabel setTitle:[NSString stringWithFormat:#"PLAY"]];
self.running = false;
}
}
- (IBAction)clearButton {
[self sendCmd:#"clear"];
}
- (IBAction)plusmoinsButton {
[self sendCmd:#"plusmoins"];
}
- (IBAction)stopButton {
[self sendCmd:#"stop"];
}
-(void)sendCmd:(NSString*) cmdSendW{
WCSession *session = [WCSession defaultSession];
NSError *error;
[session updateApplicationContext:#{#"cmdSendW":cmdSendW} error:&error];
}
- (void)session:(nonnull WCSession *)session didReceiveApplicationContext:(nonnull NSDictionary<NSString *,id> *)applicationContext {
NSString *cmdSend = [applicationContext objectForKey:#"cmdSend"];
NSString *timeSend = [applicationContext objectForKey:#"timeSend"];
NSString *distanceSend = [applicationContext objectForKey:#"distanceSend"];
NSString *partielSend = [applicationContext objectForKey:#"partielSend"];
NSString *vitesseSend = [applicationContext objectForKey:#"vitesseSend"];
dispatch_async(dispatch_get_main_queue(), ^{
if([cmdSend isEqual: #"start"])
{
[self.startLabel setTitle:[NSString stringWithFormat:#"PAUSE"]];
[self.timeLabel setText:[NSString stringWithFormat:#"Time : %#", timeSend]];
[self.distanceLabel setText:[NSString stringWithFormat:#"Distance : %#", distanceSend]];
[self.vitesseLabel setText:[NSString stringWithFormat:#"Vitesse : %#", vitesseSend]];
self.running = true;
}
else if([cmdSend isEqual: #"pause"])
{
[self.startLabel setTitle:[NSString stringWithFormat:#"PLAY"]];
[self.timeLabel setText:[NSString stringWithFormat:#"Time : %#", timeSend]];
[self.distanceLabel setText:[NSString stringWithFormat:#"Distance : %#", distanceSend]];
[self.vitesseLabel setText:[NSString stringWithFormat:#"Vitesse : %#", vitesseSend]];
self.running = false;
}
else if([cmdSend isEqual: #"stop"])
{
[self.startLabel setTitle:[NSString stringWithFormat:#"PLAY"]];
[self.timeLabel setText:[NSString stringWithFormat:#"Time : %#", timeSend]];
[self.distanceLabel setText:[NSString stringWithFormat:#"Distance : %#", distanceSend]];
[self.vitesseLabel setText:[NSString stringWithFormat:#"Vitesse : %#", vitesseSend]];
self.running = false;
}
});
}
#end
Thanks for your help
I'd suggest having your UIApplicationDelegate and ExtensionDelegate create an instance of a new object you make that is the WCSessionDelegate. This object will persist incoming data to disk, and post notifications that the backing data store has been updated. Then each of the UI components can monitor for these notifications and update their UIs as appropriate.

Multiple downloading progress bar objective c

I am developing a messaging client (as Whatsapp or Line).
I am in troubles because I need to support multiple-downloading files (and uploading), showing a progress bar into each message that have a current downloading process.
The multi-download and upload process is already developed (and works fine), the issue comes when I try to show that progress into the message progress bar.
My "solution" (I don't know if there is a better way to do it) is adding a field "uploaded" and other "downloaded" into the Message entity in CoreData, which save the upload percent or the download percent, and update that field each time that NSURLConnection calls (in upload progress, in download is different):
- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
but if I try to update the CoreData context inside that method, my user interface freeze.
Ok, that is my problem, I am going to show you the code:
This is my Core Data Message entity:
#property (nonatomic, retain) NSString *ident;
#property (nonatomic, retain) NSString *localId;
#property (nonatomic, retain) NSString *body;
#property (nonatomic, retain) NSString *contentSize;
#property (nonatomic, retain) NSNumber *uploaded;
#property (nonatomic, retain) NSNumber *downloaded;
#property (nonatomic, retain) Avatar *avatar;
#property (nonatomic, retain) Thumbnail *thumbnail;
Here is my class to manage every HTTP connection and here I try to update that entity.
#implementation HTTPConnection
//SOME CODE...
- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
{
if (self.localId) {
float progress = (float)totalBytesWritten/(float)totalBytesExpectedToWrite;
[self performSelectorOnMainThread:#selector(saveProgressInDatabase:) withObject:[NSNumber numberWithFloat:progress] waitUntilDone:YES];
}
}
- (void)saveProgressInDatabase:(NSNumber *)progress
{
NSManagedObjectContext *context = [[[AppDelegate alloc]init]managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:MESSAGE_ENTITY
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"localId = %#", self.localId];
[fetchRequest setPredicate:predicate];
NSError *coreError = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&coreError];
Message *currentMessage = [fetchedObjects objectAtIndex:0];
[currentMessage setUploaded:progress];
[context save:&coreError];
[[NSNotificationCenter defaultCenter] postNotificationName:UPLOAD_UPDATED_NOTIFICATION object:self];
}
And here I show the message list and send the messages in a table view:
#implementation TimelineViewController
//SOME CODE...
- (void)viewWillAppear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(updateTable)
name:UPLOAD_UPDATED_NOTIFICATION
object:nil];
}
- (void)updateTable
{
NSError *error;
[[self fetchedResultsController] performFetch:&error];
if ([[_fetchedResultsController sections]count]>0) {
[table reloadData];
NSIndexPath *scrollIndexPath = [NSIndexPath indexPathForRow:([table numberOfRowsInSection:[[_fetchedResultsController sections]count]-1] - 1) inSection:[[_fetchedResultsController sections]count]-1];
[table scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
}
}
//SOME CODE...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
Message *info = [_fetchedResultsController objectAtIndexPath:indexPath];
//MORE CODE...
if ([info contentSize]!=NULL) {
[cell.progressBar setHidden:NO];
[cell.progressBar setProgress:[[info uploaded]floatValue]];
}
}
//CODE...
- (IBAction)sendMessageAction:(id)sender
{
CommandServices *services = [[CommandServices alloc]init];
[services sendMessageToGroup:message withMedia:attachedMedia withLocalId:localId];
}
I don't know if that is enough to understand my issue, so I am going to ask two main questions:
Is that a nice way to manage multiple-download with multiple progress bar? I mean, saving the progress into the entity... Or, how could I do it?
Why my app is freeze when I upload or download a file? Maybe I am doing too many access to CoreData?
Thanks so much!
My guess is that you should use the following code to get the NSManagedObjectContext:
AppDelegate *app = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = [app managedObjectContext];
instead of:
NSManagedObjectContext *context = [[[AppDelegate alloc]init]managedObjectContext];
Well...after few days thinking about my issue, I realize I was doing too many database access and because of that my app freeze.
I solved it passing to my HTTPConnection object, an instance of the progress bar I want to manage. And I save the progress download/upload only when finishing.
So that is my solution:
In HTTPConnection:
+ (void)setProgressBar:(UIProgressView *)progress
{
[downloadConnection setProgressBar:progress];
}
//CODE...
- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
{
float progress = (float)totalBytesWritten/(float)totalBytesExpectedToWrite;
if (self.progressBar) {
self.progressBar.progress = progress;
}
if (progress == 1.0) {
[self saveProgressInDatabase:[NSNumber numberWithFloat:progress]];
}
}
And in my message list:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Message *info = [_fetchedResultsController objectAtIndexPath:indexPath];
//MORE CODE...
if (([info contentSize]!=NULL)&&([[info uploaded]floatValue]<1.0)) {
[HTTPConnection setProgressBar:cell.progressBar];
[cell.progressBar setHidden:NO];
} }
Thanks for your help!

Clean array by using delegate

I made an AR app that recognize image and show the object recognized in an AlertView. In the AlertView I have 2 buttons: Add and Cancel, I'm using the UIAlertViewDelegate to understand which button the user pressed. If the user press the Add button, the object recognized will be stored in an array. I pass this array to another ViewController, in which I set up a TableView. On the bottom of this TableView there's a button "Pay" to go to another ViewController in which I display the total price of the object recognized. From the last ViewController I can press a button to pay the objects I selected by using the AR. Now when I press this button the app close this ViewController and go back to the first ViewController, but the array in which I stored the object that the AR recognized it's full. To delete the content of this array I thought that the best way is to use the delegation methods, so I made this:
PaymentViewController.h
#import <UIKit/UIKit.h>
#protocol PaymentViewControllerDelegate;
#interface PaymentViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *labelTotal;
- (IBAction)buttonClosePaymentVC:(id)sender;
- (IBAction)buttonPay:(id)sender;
#property(nonatomic,strong)NSString *total;
#property(assign) id<PaymentViewControllerDelegate> delegate;
#end
#protocol PaymentViewControllerDelegate <NSObject>
- (void)cleanReportArray;
#end
PaymentViewController.m
#import "PaymentViewController.h"
#interface PaymentViewController () <UIAlertViewDelegate>
#end
#implementation PaymentViewController
#synthesize delegate = _delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.labelTotal.text = self.total;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)buttonClosePaymentVC:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)buttonPay:(id)sender {
NSString *pay = [NSString stringWithFormat:#"Stai per pagare %#, procedi?", self.total];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"HelloMS" message:pay delegate:self cancelButtonTitle:#"Si" otherButtonTitles:#"No", nil];
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
// Procedura per il pagamento e cancellazione del file plist
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"objects.plist"];
NSError *error;
if (![[NSFileManager defaultManager]removeItemAtPath:path error:&error]) {
NSLog(#"Errore: %#", error);
}
__weak UIViewController *vcThatPresentedCurrent = self.presentingViewController;
[self dismissViewControllerAnimated:YES completion:^{
[vcThatPresentedCurrent dismissViewControllerAnimated:YES completion:nil];
}];
[self.delegate cleanReportArray];
}
if (buttonIndex == 1) {
// Non deve far nulla: fa scomparire l'UIAlertView
}
}
Here I post to you the method of the class that will use the delegate:
Interface of the ScannerViewController.m
#interface ScannerViewController () <MSScannerSessionDelegate, PaymentViewControllerDelegate, UIActionSheetDelegate, UIAlertViewDelegate>
#property (weak) IBOutlet UIView *videoPreview;
- (IBAction)stopScanner:(id)sender;
#end
In ViewDidLoad I inserted this rows:
PaymentViewController *pay = [[PaymentViewController alloc]init];
[pay setDelegate:self];
And in the ScannerViewController.m I implemented the method I declared in PaymentViewController.h:
- (void)cleanReportArray {
[arrayObjectAdded removeAllObjects];
}
I tested my app on my iPhone, the app works fine until I try to pay the objects I scanned by camera, indeed, I tried to pay the object, but it doesn't clean the array in which I stored the objects scanned.
What's wrong in my code? I used an tutorial on the web to understand better how the delegation method works. I hope you can help me to fix this issue, thank you
UPDATE:
here i will post my ScannerViewController code:
ScannerViewController.h
#import <UIKit/UIKit.h>
#interface ScannerViewController : UIViewController
#end
ScannerViewController.m
#import "ScannerViewController.h"
#import "PaymentViewController.h"
#import "ReportViewController.h"
#import "MSScannerSession.h"
#import "MSResult.h"
#import "XmlReader.h"
static int kMSScanOptions = MS_RESULT_TYPE_IMAGE |
MS_RESULT_TYPE_EAN8 |
MS_RESULT_TYPE_EAN13;
#interface ScannerViewController () <MSScannerSessionDelegate, PaymentViewControllerDelegate, UIActionSheetDelegate, UIAlertViewDelegate>
#property (weak) IBOutlet UIView *videoPreview;
- (IBAction)stopScanner:(id)sender;
#end
#implementation ScannerViewController {
MSScannerSession *_scannerSession;
NSString *nameOfObjectScanned;
XmlReader *reader;
NSMutableArray *arrayObjectAdded;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
_scannerSession = [[MSScannerSession alloc] initWithScanner:[MSScanner sharedInstance]];
[_scannerSession setScanOptions:kMSScanOptions];
[_scannerSession setDelegate:self];
}
return self;
}
- (void)session:(MSScannerSession *)scanner didScan:(MSResult *)result {
if (!result) {
return;
}
[_scannerSession pause];
NSString *resultStr = nil;
if (result) {
switch ([result getType]) {
case MS_RESULT_TYPE_IMAGE:
resultStr = [NSString stringWithFormat:#"Immagine trovata: %#", [result getValue]];
break;
case MS_RESULT_TYPE_EAN8:
case MS_RESULT_TYPE_EAN13:
resultStr = [NSString stringWithFormat:#"EAN trovato: %#", [result getValue]];
break;
default:
break;
}
}
dispatch_async(dispatch_get_main_queue(), ^{
UIActionSheet *asView = [[UIActionSheet alloc]initWithTitle:resultStr delegate:self cancelButtonTitle:#"OK" destructiveButtonTitle:nil otherButtonTitles:nil, nil];
asView.actionSheetStyle = UIActionSheetStyleBlackTranslucent;
[asView showInView:self.view];
[self addObjectToList:resultStr];
});
}
- (void)addObjectToList:(NSString *)objectName {
// Ricerca dell'oggetto
NSString *object = [objectName substringFromIndex:18];
if ([object isEqualToString:#"Binario_con_coppia"]) {
[self showAlert:object];
}
if ([object isEqualToString:#"Dadi_colorati"]) {
[self showAlert:object];
}
if ([object isEqualToString:#"Dadi_rossi"]) {
[self showAlert:object];
}
if ([object isEqualToString:#"Bici_da_corsa"]) {
[self showAlert:object];
}
}
- (void)showAlert:(NSString*)name {
name = [name stringByReplacingOccurrencesOfString:#"_" withString:#" "];
nameOfObjectScanned = name;
NSString *message = [NSString stringWithFormat:#"Ho riconosciuto questo oggetto: %#, vuoi aggiungerlo al carrello?", name];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"HelloMS" message:message delegate:self cancelButtonTitle:#"Aggiungi" otherButtonTitles:#"Annulla", nil];
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
NSLog(#"Aggiungi");
for (int i = 0; i < [reader.objArray count]; i++) {
if ([[reader.objArray[i]objectForKey:#"name"] isEqualToString:nameOfObjectScanned]) {
// Salvo il nome dell'oggetto trovato, il prezzo e la descrizione
NSString *name = [reader.objArray[i]objectForKey:#"name"];
NSString *desc = [reader.objArray[i]objectForKey:#"desc"];
NSString *price = [reader.objArray[i]objectForKey:#"price"];
NSDictionary *newObjectAdded = [[NSDictionary alloc]init];
newObjectAdded = #{#"name": name,
#"desc": desc,
#"price": price};
[arrayObjectAdded addObject:newObjectAdded];
}
}
} else {
NSLog(#"Annulla");
}
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
[_scannerSession resume];
}
- (void)viewDidLoad
{
[super viewDidLoad];
arrayObjectAdded = [[NSMutableArray alloc]init];
CALayer *videoPreviewLayer = [self.videoPreview layer];
[videoPreviewLayer setMasksToBounds:YES];
CALayer *captureLayer = [_scannerSession previewLayer];
[captureLayer setFrame:[self.videoPreview bounds]];
[videoPreviewLayer insertSublayer:captureLayer below:[[videoPreviewLayer sublayers] objectAtIndex:0]];
reader = [[XmlReader alloc]init];
[reader parseXml];
[_scannerSession startCapture];
PaymentViewController *pay = [[PaymentViewController alloc]init];
[pay setDelegate:self];
}
- (void)cleanReportArray {
[arrayObjectAdded removeAllObjects];
}
- (void)dealloc {
[_scannerSession stopCapture];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)stopScanner:(id)sender {
ReportViewController *reportVC = [[ReportViewController alloc]initWithNibName:#"ReportViewController" bundle:nil];
reportVC.reportArray = arrayObjectAdded;
[reportVC setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[self presentViewController:reportVC animated:YES completion:nil];
}
#end
To recognize picture I'm using this AR SDK. I hope you can help me to understand where's my issue
Your problem is that in viewDidLoad you have the code:
PaymentViewController *pay = [[PaymentViewController alloc]init];
[pay setDelegate:self];
this is the last thing you do in that method. So the instance of PaymentViewController that you create and set the delegate on is immediately destroyed (by ARC).
You need to modify your code so that you call setDelegate: on the actual instance of PaymentViewController that is presented on screen as this is the instance that needs to use the delegate (it receives the callback from the alert view).

XMPPFramework delegate functions being called in simulator but not on phone

I'm following the tutorial at:
http://mobile.tutsplus.com/tutorials/iphone/building-a-jabber-client-for-ios-server-setup/ to set up an iOS app with an ejabberd server. So far I have pretty much copied the code over to a new project.
My problem is that the XMPP delegate functions AppDelegate.m are not being called when run on the phone. Everything works fine in Simulator and the two functions below are called.
- (void)xmppStreamDidConnect:(XMPPStream *)sender {
NSLog(#"in WSAppDelegate - xmppStreamDidConnect");
isOpen = YES;
NSError *error = nil;
[[self xmppStream] authenticateWithPassword:password error:&error];
}
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender {
NSLog(#"in WSAppDelegate - xmppStreamDidAuthenticate");
[self goOnline];
}
I am able to connect on both the phone and simulator as this call runs without error:
[xmppStream connect:&error]
Here is my AppDelegate.h code:
#import <UIKit/UIKit.h>
#import "XMPPRoster.h"
#import "XMPP.h"
#import "SMChatDelegate.h"
#import "SMMessageDelegate.h"
#class SMBuddyListViewController;
#interface WSAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
SMBuddyListViewController *viewController;
XMPPStream *xmppStream;
XMPPRoster *xmppRoster;
NSString *password;
BOOL isOpen;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet SMBuddyListViewController *viewController;
#property (nonatomic, readonly) XMPPStream *xmppStream;
#property (nonatomic, readonly) XMPPRoster *xmppRoster;
#property (nonatomic, assign) id _chatDelegate;
#property (nonatomic, assign) id _messageDelegate;
- (BOOL)connect;
- (void)disconnect;
#end
And AppDelegate.m:
#import "WSBuddyListViewController.h"
#interface WSAppDelegate()
- (void)setupStream;
- (void)goOnline;
- (void)goOffline;
#end
#implementation WSAppDelegate
#synthesize xmppStream;
#synthesize xmppRoster;
#synthesize window;
#synthesize viewController;
#synthesize _chatDelegate;
#synthesize _messageDelegate;
- (void)applicationWillResignActive:(UIApplication *)application {
[self disconnect];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[self setupStream];
BOOL connected = NO;
connected = [self connect];
NSLog(#"*** connected = %i", connected);
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
return YES;
}
- (void)setupStream {
NSLog(#"in WSAppDelegate - setupStream");
xmppStream = [[XMPPStream alloc] init];
[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xmppStream setHostName:#"localhost"];
}
- (void)goOnline {
NSLog(#"in WSAppDelegate - goOnline");
XMPPPresence *presence = [XMPPPresence presence];
[[self xmppStream] sendElement:presence];
}
- (void)goOffline {
XMPPPresence *presence = [XMPPPresence presenceWithType:#"unavailable"];
[[self xmppStream] sendElement:presence];
}
- (BOOL)connect {
NSLog(#"in WSAppDelegate - connect");
[self setupStream];
NSString *jabberID = [[NSUserDefaults standardUserDefaults] stringForKey:#"userID"];
NSString *myPassword = [[NSUserDefaults standardUserDefaults] stringForKey:#"userPassword"];
if (![xmppStream isDisconnected]) {
NSLog(#"in WSAppDelegate - connect - if (![xmppStream isDisconnected]) ");
return YES;
}
if (jabberID == nil || myPassword == nil) {
NSLog(#"in WSAppDelegate - connect - if (jabberID == nil || myPassword == nil)");
return NO;
}
[xmppStream setMyJID:[XMPPJID jidWithString:jabberID]];
password = myPassword;
NSError *error = nil;
if (![xmppStream connect:&error])
{
NSLog(#"in WSAppDelegate - connect - if (![xmppStream connect:&error]))");
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:[NSString stringWithFormat:#"Can't connect to server %#", [error localizedDescription]]
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
return NO;
}
return YES;
}
- (void)disconnect {
[self goOffline];
[xmppStream disconnect];
[_chatDelegate didDisconnect];
}
#pragma mark -
#pragma mark XMPP delegates
- (void)xmppStreamDidConnect:(XMPPStream *)sender {
NSLog(#"in WSAppDelegate - xmppStreamDidConnect");
isOpen = YES;
NSError *error = nil;
[[self xmppStream] authenticateWithPassword:password error:&error];
}
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender {
NSLog(#"in WSAppDelegate - xmppStreamDidAuthenticate");
[self goOnline];
}
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq {
return NO;
}
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message {
NSLog(#"in WSAppDelegate - xmppStream:(XMPPStream *)sender didReceiveMessage");
NSString *msg = [[message elementForName:#"body"] stringValue];
NSString *from = [[message attributeForName:#"from"] stringValue];
NSMutableDictionary *m = [[NSMutableDictionary alloc] init];
[m setObject:msg forKey:#"msg"];
[m setObject:from forKey:#"sender"];
[_messageDelegate newMessageReceived:m];
}
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence {
NSLog(#"in WSAppDelegate - xmppStream:(XMPPStream *)sender didReceivePresence:");
NSString *presenceType = [presence type]; // online/offline
NSString *myUsername = [[sender myJID] user];
NSString *presenceFromUser = [[presence from] user];
if (![presenceFromUser isEqualToString:myUsername]) {
if ([presenceType isEqualToString:#"available"]) {
[_chatDelegate newBuddyOnline:[NSString stringWithFormat:#"%##%#", presenceFromUser, #"localhost"]];
} else if ([presenceType isEqualToString:#"unavailable"]) {
[_chatDelegate buddyWentOffline:[NSString stringWithFormat:#"%##%#", presenceFromUser, #"localhost"]];
}
}
}
- (void)dealloc {
[xmppStream removeDelegate:self];
[xmppRoster removeDelegate:self];
[xmppStream disconnect];
}
#end
If you look at your setupStream method, you are using the name "localhost." This is leading me to believe the server is on your development machine, and the device is trying to connect to itself (localhost). You will have to replace that with your server name.
This likely works in the simulator because the the client and server are one and the same.
UPDATE:
I just read through the tutorial, and it does not do a good job at all at describing how it would work on real device.
as Mike D said, you're connecting to the server which is on your machine([xmppStream setHostName:#"localhost"];)
In order to connect to the "localhost" you have to change hosts file on your device(/etc/hosts), but that is forbidden by Apple, since your app cant change stuff outside the sandbox.(unless the device is jailbroken).
I've done this stuff on an android phone, when faced similar problem in the past.
Check this discussion(Does hosts file exist on the iPhone? How to change it?)

Decoder crashing through a bluetooth connection

I have an object that I want to send to another device via bluetooth. I have successfully setup the bluetooth connection and transferred an encoded NSString; however, I haven't figured out how to use the archiving and encoding tools correctly to send an Object.
I want to send the object defined below called ChatMessage. It implements the NSCoding delegate methods initWithCoder and encodeWithCoder as seen below.
In the second code snippet, I have the code for sending and receiving the data i.e. the methods that result in the de-encoder being called.
It keeps crashing on the last line of the decode method. I've been struggling to figure it out what is going wrong. Any help would be greatly appreciated!
#interface ChatMessage : NSObject <NSCoding> {
NSString *sender;
NSString *message;
}
#property (nonatomic, retain) NSString *sender;
#property (nonatomic, retain) NSString *message;
#end
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:sender forKey:#"sender"];
[coder encodeObject:message forKey:#"message"];
}
- (id)initWithCoder:(NSCoder *)coder {
sender = [[coder decodeObjectForKey:#"sender"] retain];
message = [[coder decodeObjectForKey:#"message"] retain];
return self;
}
In my View, the protocol for the PeerPicker Delegate functions.
- (void) receiveData:(NSData *)data
fromPeer:(NSString *)peer
inSession:(GKSession *)session
context:(void *)context {
ChatMessage *aMsg = [[ChatMessage alloc] init];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]
initForReadingWithData:data];
#try {
aMsg = [unarchiver decodeObjectForKey:#"myMessage"];
}
#catch (NSException *exception) {
NSLog(#"Error: %#", exception);
}
#finally {
}
if (!messages) messages = [[NSMutableArray alloc] init];
[messages addObject:aMsg];
// reload the table
[messageList reloadData];
[unarchiver finishDecoding];
[unarchiver release];
[data release];
}
--- The code was crashing because I had
[data release];
I found this using the instruments tool.

Resources