How to retrieve passed data from another view controller? - Objective-C - objective-c

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

Related

Open ears text to speech (voice) not working when getting string from another class/controller (IOS, Objective c)

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?

ShareKit: Customizing text for different sharers (SHKActionSheet)

According to the official FAQ from ver.2 to customize your text/content depending on what sharer was selected by the user, you need:
subclass from SHKActionSheet and override
dismissWithClickedButtonIndex
set your new subclass name in
configurator (return it in (Class)SHKActionSheetSubclass;).
It doesn't work for me. But even more: I put
NSLog(#"%#", NSStringFromSelector(_cmd));
in (Class)SHKActionSheetSubclass to see if it's even got called. And it's NOT ;(( So ShareKit doesn't care about this config option...
Has anybody worked with this before?
thank you!
UPD1: I put some code here.
Here's how my subclass ITPShareKitActionSheet looks like. According to the docs I need to override dismissWithClickedButtonIndex:animated:, but to track if my class gets called I also override the actionSheetForItem::
+ (ITPShareKitActionSheet *)actionSheetForItem:(SHKItem *)item
{
NSLog(#"%#", NSStringFromSelector(_cmd));
ITPShareKitActionSheet *as = (ITPShareKitActionSheet *)[super actionSheetForItem:item];
return as;
}
- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animate
{
NSLog(#"%#", NSStringFromSelector(_cmd));
NSString *sharersName = [self buttonTitleAtIndex:buttonIndex];
[self changeItemForService:sharersName];
[super dismissWithClickedButtonIndex:buttonIndex animated:animate];
}
And here's what I do in code to create an action sheet when user presses 'Share' button:
- (IBAction)shareButtonPressed:(id)sender
{
// Create the item to share
SHKItem *item = [SHKItem text:#"test share text"];
// Get the ShareKit action sheet
ITPShareKitActionSheet *actionSheet = [ITPShareKitActionSheet actionSheetForItem:item];
// Display the action sheet
[actionSheet showInView:self.view]; // showFromToolbar:self.navigationController.toolbar];
}
When I run this code, press 'Share' button and select any sharer I expect to get two lines in log:
actionSheetForItem: - custom action sheet got created
dismissWithClickedButtonIndex:animated: - custom mechanics to
process action sheet's pressed button got called.
But for some reason I get only the first line logged.
I was having the same issues but I've suddenly got it to call my Subclass successfully.
Firstly My Configurator is setup as so:
-(Class) SHKActionSheetSubclass{
return NSClassFromString(#"TBRSHKActionSheet");
}
Now My Subclass:
.h File
#import "SHKActionSheet.h"
#interface TBRSHKActionSheet : SHKActionSheet
#end
.m implementation override:
#import "TBRSHKActionSheet.h"
#import "SHKActionSheet.h"
#import "SHKShareMenu.h"
#import "SHK.h"
#import "SHKConfiguration.h"
#import "SHKSharer.h"
#import "SHKShareItemDelegate.h"
#implementation TBRSHKActionSheet
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
+ (SHKActionSheet *)actionSheetForItem:(SHKItem *)i
{
NSLog(#"%#", NSStringFromSelector(_cmd));
SHKActionSheet *as = [self actionSheetForType:i.shareType];
as.item = i;
return as;
}
- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated
{
NSInteger numberOfSharers = (NSInteger) [sharers count];
// Sharers
if (buttonIndex >= 0 && buttonIndex < numberOfSharers)
{
bool doShare = YES;
SHKSharer* sharer = [[NSClassFromString([sharers objectAtIndex:buttonIndex]) alloc] init];
[sharer loadItem:item];
if (shareDelegate != nil && [shareDelegate respondsToSelector:#selector(aboutToShareItem:withSharer:)])
{
doShare = [shareDelegate aboutToShareItem:item withSharer:sharer];
}
if(doShare)
[sharer share];
}
// More
else if ([SHKCONFIG(showActionSheetMoreButton) boolValue] && buttonIndex == numberOfSharers)
{
SHKShareMenu *shareMenu = [[SHKCONFIG(SHKShareMenuSubclass) alloc] initWithStyle:UITableViewStyleGrouped];
shareMenu.shareDelegate = shareDelegate;
shareMenu.item = item;
[[SHK currentHelper] showViewController:shareMenu];
}
[super dismissWithClickedButtonIndex:buttonIndex animated:animated];
}
Finally on my implementation file I've not modified the call to SHKActionSheet as Vilem has suggested because of some dependancies that seemed to cause conflicts for me.
So this is my caller (straight from tutorial):
NSURL *url = [NSURL URLWithString:#"http://getsharekit.com"];
SHKItem *item = [SHKItem URL:url title:#"ShareKit is Awesome!" contentType:SHKURLContentTypeWebpage];
// Get the ShareKit action sheet
SHKActionSheet *actionSheet = [SHKActionSheet actionSheetForItem:item];
// ShareKit detects top view controller (the one intended to present ShareKit UI) automatically,
// but sometimes it may not find one. To be safe, set it explicitly
[SHK setRootViewController:self];
// Display the action sheet
[actionSheet showFromToolbar:self.navigationController.toolbar];
This Calls no problems for me.
edit: by far the best way to achieve this is to use SHKShareItemDelegate. More info is in ShareKit's FAQ.

Passing data between view controllers in storyboards using segue

I'm new at iOS development and after reading many tutorials about passing variables and i still need your help.
This function in my PP.m file:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"Btn1Transport"])
{
[segue.destinationViewController setMyData:(50)];
NSLog(#"Transporter1");
}
if ([segue.identifier isEqualToString:#"Btn2Transport"])
{
[segue.destinationViewController setMyData:(100)];
NSLog(#"Transporter2");
}
}
This is in my Category.m file:
- (void)viewDidLoad{
[super viewDidLoad];
recipeLabel.text = #"Hello"; //for test, is working
}
-(void)setMyData:(int)myData
{
NSLog(#"Happines %d",myData);
NSString* result = [NSString stringWithFormat:#"%d", myData];
recipeLabel.text = result; //not working
}
The problem is at the line NSLog(#"Happines %d",myData); my data prints just fine, but not gets set to recipeLabel. So for testing if it works i made recipeLabel.text = #"Hello"; and the label is just fine. What am I doing wrong? And sorry for the beginner question.
No, you can't write to the TextLabel directly from the prepareForSegue event, the value will be overwritten when the destination view controller will load ...
You have to set a variable in the destination view controller and then you have to set the value of your label equal to the value of the variable in the viewDidLoad event of the destination view controller to make it works ...
//The variable myIntVar is a private variable that should be declared in the header file as private
- (void)viewDidLoad{
[super viewDidLoad];
recipeLabel.text = myIntVar; //set the value equal to the variable defined in the prepareForSeque
}
-(void)setMyData:(int)myData
{
NSLog(#"Happines %d",myData);
NSString* result = [NSString stringWithFormat:#"%d", myData];
myIntVar = result;
}

Need to retain a CFSocketRef?

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. :)

passing button id from one .m to another .m

Need to pass a button id from one .m to another and clear my table view at the same time so i can load new data in. Nothing seems to be happening, the table still contains what it was populated with on viewDidLoad and the background image does not change. Please help.
There are no warning or errors so im not sure what im doing wrong but the value of senderIdentifier in ClassTwo.h is always 0
Thank you.
in my classOne.m i have the following button action
-(IBAction) btnPushViewtabel:(id)sender{
ClassTwo *classtwo = [[ClassTwo alloc]init];
classtwo.myTable = nil;
classtwo.senderIdentifier = [sender tag];
[self.view addSubview:viewtableController.view];
}
in ClassTwo.h
#interface ClassTwo : UIViewController <UITableViewDelegate, UITableViewDataSource> {
....
int senderIdentifier;
}
#property (nonatomic, readwrite) int senderIdentifier;
in ClassTwo.m
if(senderIdentifier == 0){
// getNewData
//set background img1
} else {
// getNewData
//set background img2
}
if(mySenderIdentifier == 0){ //
getNewData //set background img1 }
else { // getNewData //set
background img2 }
what method is this code block in?
Edit:
This Line:
classtwo.mySenderIdentifier = [sender
tag];
is called after:
viewDidLoad
In other words- when you are checking it you havn't actually set it yet.
There are a number of ways to solve this but my personal preference would be to create a custom init method for classTwo like this:
-(id)initWithSenderIdentifier:(int)identifier{
if(self=[super init]){
self.senderIdentifier = identifier;
self.myTable = nil;
}
return self;
}
Or elimate the need to store the int (given that's only used to set the background once)
-(id)initWithSenderIdentifier:(int)identifier{
if(self=[super init]){
if(identifier)//set backgroundimg1;
else //set backgroundimg2;
self.myTable = nil;
}
return self;
}
you use it like this:
ClassTwo *classtwo = [[ClassTwo alloc]
initWithSenderIdentifier:[sender tag]];
If this is helpful, please mark it was answered