I am facing a problem: I have two view controllers, viewController1, and viewController2.
Here is the method I'm concerned about in viewController1:
-(void)msgToServer:(NSString*)identifier:(NSString *)_username{
NSString *message = [NSString stringWithFormat:#"%#|%#|<END>", identifier, _username];
CFDataRef messageData = (CFDataRef)[message dataUsingEncoding:NSUTF8StringEncoding];
CFSocketSendData(s, NULL, messageData, 0);
}
this method is working perfectly in viewController1.
Now I am calling this method from viewController2. I am passing two arguments, identifier and _username. It generates the string perfectly, but when it reaches the last line it misses the value of s -- which is a CFSocketRef.
What should I do so that s will retain its value, even if I am in viewController2?
Code from viewController2 which calls the above method:
- (void)viewDidLoad {
[super viewDidLoad];
WatchListViewController *watchListViewController = [[WatchListViewController alloc]init];
[watchListViewController msgToServer:#"PREQ" :userName];
}
Thanks in advance.
you could use the retain function of NSObject.
- (id)retain
See in Apple Documentation
Also have a look to Object Ownership and Disposal in Memory Management Programming Guide
EDITED:
Try with below code
You might have issue with function prototype,not with retaining.
use below
-(void)msgToServer:(NSString*)identifier withUsername:(NSString *)_username;.
- (void)viewDidLoad {
[super viewDidLoad];
WatchListViewController *watchListViewController = [[WatchListViewController alloc]init];
[watchListViewController msgToServer:#"PREQ" withUsername:userName];
}
-(void)msgToServer:(NSString*)identifier withUsername:(NSString *)_username{
NSString *message = [NSString stringWithFormat:#"%#|%#|<END>", identifier, _username];
CFDataRef messageData = (CFDataRef)[message dataUsingEncoding:NSUTF8StringEncoding];
CFSocketSendData(s, NULL, messageData, 0);
}
Thanx to all who helped me well i solved this problem in this way:
when I push from viewController1 to viewController2 i am passing two parameters "username" and "s" to viewController2 and then I write this method in viewController2.
-(void)msgToServer:(NSString*)identifier:(NSString *)_username{
NSString *message = [NSString stringWithFormat:#"%#|%#|<END>", identifier, _username];
CFDataRef messageData = (CFDataRef)[message dataUsingEncoding:NSUTF8StringEncoding];
CFSocketSendData(s, NULL, messageData, 0);
}
then I am calling this method in the same view controller and it works perfectly. I think this is the only solution which i find. if any body can make it more efficient then you are welcome. :)
Related
SendDataVc.m - Sending data from.
GetDataVC.m - Retrieving the data sent from SendDataVc.m
SendDataVC.m:
NSString *theData = #"Sending data";
GetDataVC *passdataVC = [[GetDataVC alloc] init];
passdataVC.theData = theData;
GetDataVC.h:
#property (strong, nonatomic) NSString *theData;
GetDataVC.m:
-(void) getData
{
NSLog( #"%#", _theData);
}
I tried doing this way but I got null instead.
I think the application doesn't running to the function - (void) getData, you should call this function at - (void)viewDidLoad or - (void)viewWillAppear or something else like below:
- (void)viewDidLoad {
[super viewDidLoad];
[self getData];
}
-(void)getData {
NSLog(#"%#", _theData);
}
You can't instantiate a UIViewController that way.
Use the following approach, in which #"GetDataVC" is the identifier of the view controller you are going to instantiate:
GetDataVC *passdataVC = (GetDataVC*)[self.storyboard instantiateViewControllerWithIdentifier:#"GetDataVC"];
passdataVC.theData = theData;
Where you execute the function getData?
If you execute getData at viewDidLoad or init or somewhere before you set the data.
You can execute the function through a button.
I think that will deal the problem.
Just implement the setter of theData property.
Paste the code below to your GetDataVC.m.
- (void)setTheData:(NSString *)theData {
_theData = theData;
NSLog(#"theData has set: %#", _theData);
}
refrence: Apple Document
I am very new to objective c and OpenEars so please forgive me if I have some messy code and if I am lost in very simple problem.
Anyhow, I have two controllers in this application. The first being the default ViewController and the second one being a new one that I made called ReplyManagerController.
The code in the ViewController basically uses the one in the tutorial with some (maybe more some) changes.
EDIT:
The app is supposed to be a basic app where a user says something and the app replies.
But the original problem was that I could not get the string to display or TTS to work when my ViewController got it's string from another class/controller.
The answer in my below mentions that it was probably because my other class was calling my ViewController without the self.fliteController initialized.
How would I initialize the ViewController with self.fliteController initialized?
ViewController.m
- (void) pocketsphinxDidReceiveHypothesis:(NSString *)hypothesis recognitionScore:(NSString *)recognitionScore utteranceID:(NSString *)utteranceID {
NSString *strResult = hypothesis; //speech to text to string
ReplyManager* replyObject = [[ReplyManager alloc] init];
[replyObject speechResult:(NSString*)strResult viewController:self];
}
- (void) getReply:(NSString*)replyStr{
[self.fliteController say:replyStr withVoice:self.slt];
[self updateText:replyStr];
}
- (IBAction)updateText:(NSString*)replyStr{
labelOne.text = replyStr;
labelOne.adjustsFontSizeToFitWidth = YES;
labelOne.minimumFontSize = 0;
}
Any help will be great! Thanks!
ReplyManager.m
- (void) speechResult:(NSString*)strResult {
NSString *replystr;
NSString *greetings = #"Hi!";
NSString *sorry = #"Sorry I didn't catch that?";
ViewController* getReply = [[ViewController alloc] init];
if ([strResult isEqualToString:#"HELLO"])
{
replystr = greetings;
[getReply getReply:(NSString*)replystr];
}
else
{
replystr = sorry;
[getReply getReply:(NSString*)replystr];
}
}
EDIT 2:
viewDidLoad Method
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.fliteController = [[OEFliteController alloc] init];
self.slt = [[Slt alloc] init];
self.openEarsEventsObserver = [[OEEventsObserver alloc] init];
[self.openEarsEventsObserver setDelegate:self];
}
ViewController* getReply = [[ViewController alloc] init];
Here you init a new ViewController which does not have self.fliteController defined most likely. You need to reuse previos controller, for example like this:
[replyObject speechResult:(NSString*)strResult viewController:self];
So you can use already initialized viewController later. Overall it is better to initialize objects like viewController or replyController beforehand, not inside callback methods.
It sounds like a timing issue where you're trying to use fliteController before it's been initialized.
In your ViewController class, where do you assign a value to the fliteController property? In an initializer? -(void)viewDidLoad?
In ReplyManagerController add:
ViewController* getReply = [[ViewController alloc] init];
// Add these lines
NSLog(getReply.fliteController); // Is this nil?
[getReply.view layoutIfNeeded];
NSLog(getReply.fliteController); // Is it still nil?
Does the above fix the problem? If so, you're probably initializing fliteController in -(void)viewDidLoad. What's the result of the two NSLog statements?
I would like to implement a function to directly share to Sms in the ShareKit Plugin. It have 3 builted-in function to share directly to Facebook, Mail and Twitter. I took a look in plugin code and it seems to me pretty easy, taking as example the function
shareToMail(subject,body);
- (void)shareToMail:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options {
[SHK setRootViewController:self.viewController];
SHKItem *item;
NSString *subject = [arguments objectAtIndex:1];
NSString *body = [arguments objectAtIndex:2];
item = [SHKItem text:body];
item.title = subject;
[SHKMail shareItem:item];
}
It seems that it takes as input the two parameters passed in (objectAtIndex:1 and objectAtIndex:2) and then it assign them to the item object (item = [SHKItem text:body];) for send it to SHKMail method.
That is what I understood, but I'm really a noob in ObjC, so... can someone give me some advice in how to create a function that call the Sms method? I think it is called SHKTextMessage but once again I'm really not sure about this...
if someone need this...
In ShareKitPlugin.m add this:
//at the top, near the other import
#import "SHKTextMessage.h"
//somewhere between #implementation ShareKitPlugin and #end
- (void)shareToSms:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options {
[SHK setRootViewController:self.viewController];
SHKItem *item;
NSString *message = [arguments objectAtIndex:1];
item = [SHKItem text:message];
[SHKTextMessage shareItem:item];
}
In the ShareKitPlugin.js add:
ShareKitPlugin.prototype.shareToSMS = function( message)
{
cordova.exec(null, null, "ShareKitPlugin", "shareToSms", [message] );
};
And now you can share trought Sms using this function:
window.plugins.shareKit.shareToSMS(message);
I'm having trouble with something very basic. I want to call this action:
- (IBAction)changeGreeting:(id)sender {
self.userName = self.textField.text;
NSString *nameString = self.userName;
if ([nameString length]==0) {
nameString = #"World";
}
NSString *greeting = [[NSString alloc] initWithFormat:#"Hello, %#!", nameString];
self.label.text = greeting;
}
When the user presses return after entering text in the text field. This is what I have:
-(BOOL)textFieldShouldReturn:(UITextField *)theTextField{
if (theTextField == self.textField) {
[theTextField resignFirstResponder];
[changeGreeting];
}
return YES;
}
I'm not sure what to put where it says "changeGreeting." Think I'm missing the concept here. Thanks for any help.
Your syntax is wrong. Try this:
[self changeGreeting:self];
In Objective-C the syntax for sending messages (calling functions) is like this:
[receiver message];
Since you implement the changeGreeting: method in the same class as you're calling it from, the receiver will be self. As the parameter (sender) you usually pass the object that sends the message, but since you don't use it in your implementation of changeGreeting: it doesn't really matter what you pass there.
you called the changeGreeting function in wrong way
you should call it like
[self changeGreeting:nil];
Or if you want to track something from the textField then
[self changeGreeting:theTextField];
the sender will get theTextField as parameter if you need some processing on based on the textField.
I am new to ObjC and I am struggling with the CLGeocoder. I want to be able to use reverseGeocodeLocation to obtain a string that contains the user location that I pass to my delegate when the user presses a Done button.
So the user triggers the display of a MapViewController, I call the reverseGeocodeLocation in the viewDidLoad but the [placemarks count = 0] this first time in, and I have no placemark to get the info that I need. The second time the user triggers the display of the MapViewController the placemarks array has been populated and everything works.
I suspect it is something to do with the reverseGeocodeLocation being an asynchronous call - but I cannot figure out how to solve this problem. I have tried searching online but nothing seems to help me understand what I am doing wrong and how i can solve this issue. Thanks in advance.
#interface MapViewController ()
#property (strong, nonatomic) CLGeocoder *geocoder;
#property (readwrite, nonatomic) NSString *theLocationName;
#end
#implementation MapViewController
#synthesize mapView, geocoder, delegate = _delegate, theLocationName = _theLocationName;
- (void)viewDidLoad
{
[super viewDidLoad];
self.mapView.delegate=self;
self.mapView.showsUserLocation = YES;
[self theUserLocation];
}
-(void)theUserLocation
{
if (!geocoder)
{
geocoder = [[CLGeocoder alloc] init];
}
MKUserLocation *theLocation;
theLocation = [self.mapView userLocation];
[geocoder reverseGeocodeLocation:theLocation.location
completionHandler:^(NSArray* placemarks, NSError* error)
{
if ([placemarks count] > 0)
{
CLPlacemark *placemark = [placemarks objectAtIndex:0];
[self setTheLocationName: placemark.locality];
}
}];
- (IBAction)done:(id)sender
{
[[self delegate] mapViewControllerDidFinish:self locationName:[self theLocationName]];
}
#end
This is not exact answer to your question but, if you can switch to other solution apart from CLGeocoder than following function can help you to get address from given latitude, longitude
#define kGeoCodingString #"http://maps.google.com/maps/geo?q=%f,%f&output=csv" //define this at top
-(NSString *)getAddressFromLatLon:(double)pdblLatitude withLongitude:(double)pdblLongitude
{
NSString *urlString = [NSString stringWithFormat:kGeoCodingString,pdblLatitude, pdblLongitude];
NSError* error;
NSString *locationString = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlString] encoding:NSASCIIStringEncoding error:&error];
locationString = [locationString stringByReplacingOccurrencesOfString:#"\"" withString:#""];
return [locationString substringFromIndex:6];
}
Credit : Selected Answer to this question
So the user triggers the display of a MapViewController, I call the reverseGeocodeLocation in the viewDidLoad but the [placemarks count = 0] this first time in, and I have no placemark to get the info that I need. The second time the user triggers the display of the MapViewController the placemarks array has been populated and everything works.
It's not because the call is asynchronous - it's because the first time you call theUserLocation the actual location isn't available. Getting the user's location is not instantaneous - it takes time. However, you're asking for the user's location as soon as the map loads, which in most circumstances won't work.
What you need to do is hook into the MKMapViewDelegate methods, which provide you with callbacks when the location is updated. You can use this to check the location's accuracy, and decide whether it is accurate enough for you to reverse geolocate.