Objective C : Use of undeclared identifier - function

Helo,
I use WM for my developpement. WM create this code in 'WDObjectiveC.mm':
#include <stdint.h>
#import <UIKit/UIKit.h>
#import <Exe/www/lib/wdHTML.h>
void activeDelegate(void*);
bool RetourObjC(NSString*,NSString*);
void activeDelegate(void*nHandleChampWM) {
UIView*ChampWM= (UIView*)nHandleChampWM;
UIWebView*myView= (UIWebView*)[ChampWM subviews][0];
[myView setDelegate: [wdHTML new]]
NSLog(#"activé");
RetourObjC(#"JS",#"test");
}
...
bool RetourObjC(NSString* p0,NSString* p1){
IExternalCall* call = AllocExternalCall(0x136a26740038d376ll,2);
call->Push(0,&p0,16);
call->Push(1,&p1,16);
bool r = *(bool*)call->Call();
call->Release();
return r;
}
...
'RetourObjC' is a function that i have created in WM, this function execute a code in WLanguage.
When i call RetourObjC here, there isn't problem.
But i have created a class :
#interface wdHTML : UIWebView <UIWebViewDelegate> { }
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType ;
#end
#implementation wdHTML
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
NSLog(#"Enter");
NSURL *URL = [request URL];
RetourObjC(#"JS",#"test");
return NO;
}
return YES;
}
#end
When i called the function RetourObjC in this class, i have one error : Use of undeclared identifier 'RetourObjC'.
SOS please, i don't find any solution on google (i'm new in the developpement for IOS)

The problem is that your function isn't visible from the wdHTML class. Move the prototype to a header file:
// WDObjectiveC.h
bool RetourObjC(NSString*,NSString*);
and then #import that file in your class:
// wdHTML.m
#import "WDObjectiveC.h"

Related

How to use delegate here? I can't get it to work

I know there is very simple question, but few hours I can not do this.
I got 2 classes:
1. LoginViewController : UIViewController
2. WebRequests : NSObject - it makes request and got response from server (singleton)
Then I got response I want to run MyMethod in LoginViewController from WebRequests.
I do it like here, but it not works:
WebRequests.h
#protocol WebRequestsDelagate <NSObject>
#required
- (void) MyMethod;
#end
#interface WebRequests : NSObject
...
#property (nonatomic, weak) id <WebRequestsDelagate> delegate;
WebRequests.m
#implementation WebRequests
//singleton
+ (WebRequests *)sharedInstance {
static dispatch_once_t p = 0;
__strong static id _sharedObject = nil;
dispatch_once(&p, ^{
_sharedObject = [[self alloc] init];
});
return _sharedObject;
}
- (id)init {
if (self = [super init]) {
LoginViewController * loginViewController = [[LoginViewController alloc] init];
self.delegate = loginViewController;
}
return self;
}
- (void) someMethod {
//here I got response
[self.delegate runThisMethod];
I do not move on in runThisMethod in LoginViewController.
Why does it not work?
UPDATE
#implementation LoginViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
// AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
return YES;
}
If that's your real code, then the loginViewController created in the [WebRequests init] method will be destroyed at the end of the if statement (i.e. pretty much straight away):
- (id)init {
if (self = [super init]) {
LoginViewController * loginViewController = [[LoginViewController alloc] init];
self.delegate = loginViewController;
}
return self;
}
I don't understand why you are creating view controllers in this method; it would be more normal to create the view controller outside of this class (through whatever method) and then register it as the delegate of the WebRequests object.
Okay, I'm a bit confused by your code but maybe you're looking for something like
WebRequests *webRequests = [WebRequests sharedInstance];
webRequests.delegate = self;
perhaps in LoginController's viewDidLoad.

Getting the value of a delegate upon clicking back?

I have two class files. ViewController and ChooseServerView. A user clicks a cell within the ViewController class which pushes to the ChooseServerView. When a user makes a selection in ChooseServerView the value of that cell gets passed to the delegate. Now, these two views are in front of a navigation controller, so in the ChooseServerView there is a back button. When the user clicks back I want to update the cell in the first view with the new value from the delegate, make sense?
ViewController.h
#import <UIKit/UIKit.h>
#import "ChooseServerView.h"
#interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, serverUserChoice>
{
NSString *testLocation;
}
#property (nonatomic, retain) NSString *testLocation;
#end
View Controller.m
#import "ViewController.h"
#import "ChooseServerView.h"
#import "AppDelegate.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize testLocation;
- (void)viewDidLoad
{
NSUserDefaults *sharedPref = [NSUserDefaults standardUserDefaults];
testLocation =[sharedPref stringForKey:#"defaultLocation"];
NSLog(#"Location Chosen: %#",testLocation);
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
#pragma mark - Table View Methods
- (void) userDidChoose:(NSString *) server {
testLocation = server;
NSLog(#"Test Location %#", server);
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; // Default is 1 if not implemented
{
return 2;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; // fixed font style. use custom view (UILabel) if you want something different
{
switch (section) {
case 0:
return #"Choose Test Location:";
break;
case 1:
return #"Choose Test Type:";
default:
return #"Unknown";
break;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
{
switch (section) {
case 0:
return 1;
break;
case 1:
return 1;
default:
return 0;
break;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
UITableViewCell *serverLocCell = [tableView dequeueReusableCellWithIdentifier:#"serverLocation"];
switch (indexPath.section) {
case 0:
serverLocCell.textLabel.text = testLocation;
serverLocCell.detailTextLabel.text = #"Change";
break;
case 1:
serverLocCell.textLabel.text = #"Speed Test";
serverLocCell.detailTextLabel.text = #"Change";
break;
default:
break;
}
return serverLocCell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
switch (indexPath.section) {
case 0:
[self performSegueWithIdentifier:#"toServerChoice" sender:self];
break;
case 1:
[self performSegueWithIdentifier:#"toTestType" sender:self];
break;
default:
break;
}
}
#end
ChooseServerView.h
#import <UIKit/UIKit.h>
#class ViewController;
#protocol serverUserChoice <NSObject>
#optional
- (void)userDidChoose:(NSString *) server;
#end
#interface ChooseServerView : UIViewController <UITableViewDataSource, UITableViewDelegate, serverUserChoice>
{
NSArray *serverSelection;
NSArray *tqServerSelection;
}
#property (nonatomic, retain) NSArray *serverSelection;
#property (nonatomic, retain) NSArray *qServerSelection;
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#property(retain) NSIndexPath* lastIndexPath;
#property (nonatomic, assign) id <serverUserChoice> serverDelegate;
#end
ChooseServerView.m
#import "ChooseServerView.h"
#import "ViewController.h"
#import "AppDelegate.h"
#define totalSections 2
#define standardSection 0
#define qualitySection 1
#interface ChooseServerView ()
#end
#implementation ChooseServerView;
#synthesize serverSelection;
#synthesize qServerSelection;
#synthesize lastIndexPath;
#synthesize serverDelegate;
- (void)viewDidLoad
{
serverSelection = [[NSArray alloc] initWithObjects:#"Chicgo, IL",#"London, UK",#"San Jose, CA",#"Washington, DC", nil];
qServerSelection = [[NSArray alloc] initWithObjects:#"Chicgo, IL (Q)",#"London, UK (Q)",#"San Jose, CA (Q)",#"Washington, DC (Q)", nil];
[super viewDidLoad];
}
#pragma mark - Table View Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; // Default is 1 if not implemented
{
return totalSections;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; // fixed font style. use custom view (UILabel) if you want something different
{
switch (section) {
case standardSection:
NSLog(#"Std Heading Set");
return #"Standard Test Locations:";
break;
case qualitySection:
NSLog(#"Qual Heading Set");
return #"Quality Test Locations:";
break;
default:
NSLog(#"Section Count Error");
return #"Section Count Error";
break;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
{
if (section == 0) {
NSLog(#"Std Loc Set");
return [serverSelection count];
}
else {
NSLog(#"Quality Loc Set");
return [qServerSelection count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
UITableViewCell *serverLoc = [tableView dequeueReusableCellWithIdentifier:#"serverSelection"];
switch (indexPath.section) {
case standardSection:
serverLoc.textLabel.text = [self.serverSelection objectAtIndex:indexPath.row];
break;
case qualitySection:
serverLoc.textLabel.text = [self.qServerSelection objectAtIndex:indexPath.row];
break;
default:
break;
}
return serverLoc;
}
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellvalue;
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
cellvalue = cell.textLabel.text;
[serverDelegate userDidChoose:cellvalue];
NSLog(#"Cell Selected is %#",cellvalue);
[cell setSelected:FALSE animated:TRUE];
}
#end
I can see the correct value gets passed to the delegate, I just don't know how to "call" that delegate/method when going back using the automatic back button implemented by the nav controller.
Any ideas would be great.
As per answer below:
Added to my ViewController.h
#property (nonatomic, weak) IBOutlet UITableView *tableView;
Added to my ViewController.m
-(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.tableView reloadData];
}
Still no joy at this stage. First cell fails to update upon pressing the back button as provided by the navigation controller.
Looks like you are almost there.
I think the issue is that your UITableView is not being reloaded to represent the updated value of testLocation. I don't see a reference to the UITableView that is being managed by your ViewController, first add an outlet to ViewController.m to point to this table view.
Then, add the following in your ViewController.m
-(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.tableView reloadData];
}
You also need to make sure you set your ViewController as the delegate of ChooseServerViewController. (You should rename ChooseServerView.m to ChooseServerViewController.m for clarity, as it's a view controller subclass- I've referred to it as such below)
You can set the delegate by adding a prepare for segue method in ViewController.m - something like:
(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
ChooseServerViewController *viewController = (ChooseServerViewController *)segue.destinationViewController;
viewController.serverDelegate = self;
}
I would also look into using UITableViewController for these two controller classes, since it appears that's the type of functionality you are looking for.

UILabel to control a UItextfield in another view controller

I am using Xcode 4.3 and I have a label in one view controller that I want to update the text in a text field in another view controller. How should I do this?
You should put the text in your model class (assuming that you have one; if you don't, you need to create it). When the end-user edits the text field, your code should change the string in your model; when the label displays, you should read its text from the model. The easiest way of sharing your model among multiple classes is to define a singleton.
Header:
#interface Model : NSObject
#property (NSString*) labelText;
+(Model*)instance;
#end
Implementation:
#implementation Model
#synthesize labelText;
+(Model*)instance{
static Model *inst;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
inst = [[Model alloc] init];
});
return inst;
}
-(id)init {
if (self = [super init]) {
labelText = #"Initial Text";
}
return self;
}
#end
Using the model:
// Setting the field in the model, presumably in textFieldDidEndEditing:
// of your UITextField delegate
[Model instance].labelText = textField.text;
// Getting the field from the model, presumably in viewWillAppear
myLabel.text = [Model instance].labelText;

NSMutableDictionary setObject:forKey: fails to add key

I'm sure I'm missing something in a small iPhone program I'm trying to write, but the code is simple and it compiles without any errors and so I fails to see where the error is.
I've set up a NSMutableDictionary to store students' attributes, each with a unique key. In the header file, I declare the NSMutableDictonary studentStore:
#interface School : NSObject
{
#private
NSMutableDictionary* studentStore;
}
#property (nonatomic, retain) NSMutableDictionary *studentStore;
And of course in the implementation file:
#implementation School
#synthesize studentStore;
And I want to add an object into the dictionary:
- (BOOL)addStudent:(Student *)newStudent
{
NSLog(#"adding new student");
[studentStore setObject:newStudent forKey:newStudent.adminNo];
return YES;
}
class Student has the attributes:
#interface Student : NSObject
{
#private
NSString* name; //attributes
NSString* gender;
int age;
NSString* adminNo;
}
where newStudent has the values:
Student *newStudent = [[Student alloc] initWithName:#"jane" gender:#"female" age:16 adminNo:#"123"];
But when I look up the dictionary:
- (void)printStudents
{
Student *student;
for (NSString* key in studentStore)
{
student = [studentStore objectForKey:key];
NSLog(#" Admin No: %#", student.adminNo);
NSLog(#" Name: %#", student.name);
NSLog(#"Gender: %#", student.gender);
}
NSLog(#"printStudents failed");
}
It fails to print the values in the table. Instead, it prints the line "printStudents failed".
I guess this's quite basic, but since I'm new to iOS programming I'm a bit stumped. Any help will be appreciated. Thanks.
Your studentStore instance variable is a pointer to an NSMutableDictionary. By default, it points to nil, meaning it doesn't point to any object. You need to set it to point to an instance of NSMutableDictionary.
- (BOOL)addStudent:(Student *)newStudent
{
NSLog(#"adding new student");
if (studentStore == nil) {
studentStore = [[NSMutableDictionary alloc] init];
}
[studentStore setObject:newStudent forKey:newStudent.adminNo];
return YES;
}

NSInvalidArgumentException exception for reason: +[GameScene onEnter]

I get this exception when i try to create a new layer. So , basically i have a standart cocos2d template , i just removed HelloWorldLayer class and created a new class called GameScene, were i defined +scene method , init and dealloc methods
GameScene.h
#import "cocos2d.h"
#interface GameScene : CCLayer {}
+(id) scene;
#end
GameScene.m
#import "GameScene.h"
#implementation GameScene
+(id) scene {
CCScene *scene = [CCScene node];
GameScene *layer = [GameScene node];
[scene addChild:layer];
return self;
}
-(id) init {
if ((self = [super init])) {
CCLOG(#"New GameScene");
}
return self;
}
-(void) dealloc {
[super dealloc];
}
#end
I my appDelegate , instead of old layer , create new one from GameScene
- (void) applicationDidFinishLaunching:(UIApplication*)application
{
…
// Run the intro Scene
[[CCDirector sharedDirector] runWithScene: [GameScene scene]];
}
Console output shows :
2012-02-06 20:37:04.284 Doodle[3908:10a03] +[GameScene onEnter]: unrecognized selector sent to class 0x1098c4
2012-02-06 20:37:04.288 Doodle[3908:10a03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[GameScene onEnter]: unrecognized selector sent to class 0x1098c4'
I figure it out. Instead of returning an id type for method +scene , it should be a CCScene value.
// in header also modify type of returned value
+(CCScene *) scene {
CCScene *scene = [CCScene node];
GameScene *layer = [GameScene node];
[scene addChild:layer];
return self;
}
I'm still confused of why id is not working cause it can be every type , even CCScene type.
Am uncertain what you are trying to accomplish here, but in your +(id) scene creator, you should not be returning self.
Try [scene autorelease]; (if thats what you really want).