My iPhone game has a lot of recurring code (move pictures, add score), that makes it too big when repeating the same code on each button click.
this is ViewController.m
interface and implementation between Viewcontroller.h and ViewController.m is correct - workes well
- (IBAction)button_xx_pressed:(id)sender
{
//trying to call the outsourced code
[self this_is_a_test];
}
so I tried to make outsourced recurring code. I don't need method or functions that gives a result back or something. Just do some action like NSLog output...(just a test). Or in the original version - move pictures, add score and other stuff.
this is Outsourcing.h
#import "Outsourcing.m"
#end
this is Outsourcing.m
#import "Outsourcing.h"
- (void)this_is_a_test {
int test_variable = 999;
NSLog(#"Give me a test output: = %i", test_variable);
}
#end
this would shrink the size of my game more than 80% (very important). I have thousands of recurring programming lines and at the moment, I don't know how to handle it.
actual error messages:
Outsourcing.h => missing context for method declaration
Outsourcing.m => missing context for method declaration
=> #end must appear in Objective-C context
Anyone any hints for me? Thank you very much... The rest of my game is ok... everything would run without issues. I'm very glad that I got it running (but the game size is a problem).
1 or 2 months ago, I never used xcode before. I just had some experience in VBA. And what I want is similar to.
=> Call this_is_a_test
=> Private Sub this_is_a_test()
But it seems I'm too stupid :-(
thanks
#interface Outsourcing : NSObject
- (void)this_is_a_test;
#end
#import "Outsourcing.h"
#implementation
- (void)this_is_a_test {
int test_variable = 999;
NSLog(#"Give me a test output: = %d", test_variable);
}
#end
and you call it like this in your ViewController:
#import "Outsourcing.h"
...
- (IBAction)button_xx_pressed:(id)sender
{
Outsourcing *outsourcing = [[[Outsourcing alloc] init] autorelease];
//trying to call the outsourced code
[outsourcing this_is_a_test];
}
You are missing
#interface Outsourcing : NSObject
in your header file (Outsourcing.h). Remove:
#import "Outsourcing.m"
You import header files, not source files....You are also missing:
#implementation Outsourcing
In your .m file, just after the import declaration.
Related
Following problem: I receive an Object from a framework (which is not instantiable) and I want to extend it. When I make a category, the problem is, that it doesn't have an effect on the existing object.
I thought of isa swizzling. So let the isa field point to the extended "list of selectors". But that doesn't seem to be possible? (Syntax for it?)
Does anyone know a better approach to do it ?
That is the code:
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray<CBATTRequest *> *)requests {
//want to do something that uses the extension
}
And I want to extend CBATTRequest. I think the problem lies in CoreBluetooth?
This is how I make my category:
BLERequestable.h
#protocol BLERequestable <NSObject>
- (nonnull NSString *)getCentralUUID;
- (nonnull NSString *)getCharacteristicUUID;
- (nullable NSData*)getData;
- (void)setData:(nullable NSData *) data;
#end
CBATTRequest+Requestable.h
#import <CoreBluetooth/CoreBluetooth.h>
#import "BLERequestable.h"
#interface CBATTRequest (Requestable) <BLERequestable>
#end
CBATTRequest+Requestable.m
#import "CBATTRequest+Requestable.h"
#implementation CBATTRequest (Requestable)
- (NSString *)getCentralUUID {
return self.central.identifier.UUIDString;
}
- (NSString *)getCharacteristicUUID {
return self.characteristic.UUID.UUIDString;
}
- (NSData*)getData {
return self.value;
}
- (void)setData:(NSData *) data {
self.value = data;
}
#end
And I import the Category everywhere I want to use it.
After long researching and testing (thanks to Rob Napier), I found the source of error.
My project consists of a library and and executable target. In the library I defined my category and used it inside. The problem is, that when it comes to linking due to the executable, the o-file with my category isn't linked. See this stack post for further details on problems with categories in static libraries.
One possible solution would be setting the linker flag from the exe target to -Objc.
But I don't like this solution, because the library's ability to work properly would depend on the exe.
So I included the implementation of the category in the m-file where I use it.
If somebody has another (better) solution, I would be glad to see it. Otherwise I would close this question.
My first shot at creating a method with multiple parameters. Still trying to wrap my head around how Objective C does things. Been banging my head for a couple days on this now. Finally ready to ask for help. Searched and tried many posts here on stack overflow. Below is various code chunks I'm working with ... this is a cocos2d v3 project FYI.
// MainPlayScene.h
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#include <sys/sysctl.h>
#interface MainPlayScene : CCScene <CCPhysicsCollisionDelegate>
+ (MainPlayScene *)scene;
- (id)init;
- (void)evaluateTileAttack:(CCNode*)tileTouchedCCNode : (CCNode*)tileTouchedCCNode2;
#end
// MainPlayScene.m
#import "cocos2d.h"
#import "MainPlayScene.h"
#implementation MainPlayScene
{
CCNode *tileTouchedCCNode;
CCNode *tileTouchedCCNode2;
}
+ (instancetype)scene
{
return [[self alloc] init];
}
- (id)init
{
return self;
}
- (void)evaluateTileAttack: (CCNode*)ccnode1 : (CCNode*)ccnode2
{
NSLog(#"ccnode1: %#", ccnode1.physicsBody.collisionType);
NSLog(#"ccnode2: %#", ccnode2.physicsBody.collisionType);
}
- (void)actionMenuAttackHandler: (id)sender
{
[self evaluateTileAttack: tileTouchedCCNode, tileTouchedCCNode2];
^^^^^^^^^^^^^^^^^^^^^
error at this line
}
#end
ERROR: No visible #interface for 'MainPlayScene' declares the selector 'evaluateTileAttack:'
Not sure why I am getting this error because I think I am declaring in MainPlayScene.h properly ...
The method declaration, though technically valid I think, is at least unusual for ObjC. Best seen when you wrap and align (as is customary for long method calls/declarations) on the colon:
- (void)evaluateTileAttack:(CCNode*)tileTouchedCCNode
:(CCNode*)tileTouchedCCNode2;
Normally a method has a name for all parameters:
- (void)evaluateTileAttack:(CCNode*)tileTouchedCCNode
otherNode:(CCNode*)tileTouchedCCNode2;
The call is definitely invalid, ObjC methods do not take a comma-separated list of parameters (unless specifically declared to do so, which is rare). So this is illegal:
[self evaluateTileAttack: tileTouchedCCNode, tileTouchedCCNode2];
Instead it should be (not sure about this unnamed format though):
[self evaluateTileAttack:tileTouchedCCNode
:tileTouchedCCNode2];
This definitely works and is the expected/recommended approach:
[self evaluateTileAttack:tileTouchedCCNode
otherNode:tileTouchedCCNode2];
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have a problem that I hope you can help me with. I have an app with several storyboard views, each with a separate viewcontroller. I want to be able to use my own class in all views in the storyboard. This will make the code in each viewcontroller much cleaner and the whole app easier to debug etc. The class will contain variables and methods.
The overall aim for me is to collect data from the user via buttons and then store these in a database. It will be possible to view and amend data, as well as generating statistics.
As most variables and methods will be used in different views and at different times, I would like to separate all these in separate files.
I can also tell you that this is not a lazy short-cut attempt from me, I have surfed the internet for many, many hours reading hundreds of posts etc and I am still nowhere nearer a solution.
Any input is very much appreciated!
Thank you for taking your time to read this...
SomeClass.h has the following code:
#import <Foundation/Foundation.h>
#interface SomeClass : NSObject
{
NSString *dataOne;
NSString *dataTwo;
NSString *dataThree;
}
- (void) SetDataOne: (NSString*) dataOneReceived;
- (void) SetDataTwo: (NSString*) dataTwoReceived;
- (void) SetDataThree: (NSString*) dataThreeReceived;
- (void) saveSomeData;
#end
SomeClass.m has the following code:
#import "SomeClass.h"
#implementation SomeClass
- (void) SetDataOne: (NSString*) dataOneReceived {
dataOne = dataOneReceived;
}
- (void) SetDataTwo: (NSString*) dataTwoReceived {
dataTwo = dataTwoReceived;
}
- (void) SetDataThree: (NSString*) dataThreeReceived {
dataThree = dataThreeReceived;
}
- (void) saveSomeData {
// Here I do stuff with dataOne etc…
}
#end
SomeView.h has the following code:
#import <UIKit/UIKit.h>
#import "HeadViewController.h"
#import "SomeClass.h"
#interface SomeView : UIViewController
// contains stuff not needed to show here
- (IBAction)Done:(id)sender;
#end
SomeView.m has the following code:
#import "SomeView.h"
#import "SomeClass.h"
#interface SomeView ()
#end
#implementation SomeView
- (void)viewDidLoad
{
[super viewDidLoad];
SomeClass *someClassObject = [[SomeClass alloc] init];
// Do any additional setup after loading the view.
}
// Other standard methods omitted
- (IBAction)Done:(id)sender {
[someClassObject SetDataOne: #”whatever text”];
[someClassObject SetDataTwo: #”whatever text”];
[someClassObject SetDataThree: #”whatever text”];
[someClassObject SaveSomeData];
Error Msg for all the above: ”Use of Undeclared Identifier ’someClassObject’
}
#end
Comment: You can see the error message I get at the end of the code above. I have no clue what I am doing wrong. I have looked at a lot of examples on how to create and call classes, but cannot seem anything that solves my problem. Also, I see that some of the put the ”SomeClass *someClassObject = [[SomeClass alloc] init];” in the ”main.m file”. If I understand correctly, that file is the first one to load when app starts. If so, then I cannot place it there as I will have to create instances of my class in several different views and other times than when the app starts. That is why I have placed it in the viewDidLoad-method.
A couple of thoughts:
You've made someClassObject a local variable of the viewDidLoad method. Looks like you meant to make it a class instance variable (or, better, a private class property, which will have the instance variable synthesized for you). Thus:
#interface SomeView ()
#property (nonatomic, strong) SomeClass *someClassObject;
#end
#implementation SomeView
- (void)viewDidLoad
{
[super viewDidLoad];
self.someClassObject = [[SomeClass alloc] init];
}
- (IBAction)done:(id)sender {
[self.someClassObject setDataOne: #"whatever text"];
[self.someClassObject setDataTwo: #"whatever text"];
[self.someClassObject setDataThree: #"whatever text"];
[self.someClassObject saveSomeData];
// should resolve the Error Msg for all the above: ”Use of Undeclared Identifier ’someClassObject’
}
BTW, as a matter of convention, your method names should start with a lowercase letter (e.g. setDataOne not SetDataOne, done rather than Done, etc.), as illustrated above.
If you're going to write your own setters, setDataOne, setDataTwo, etc., you might as well remove those three instance variables, remove your three setData___ methods, and replace the three instance variables with class properties (and let the compiler synthesize not only the instance variables, but the setters, too).
someClassObject is set inside viewDidLoad and because it is not stored anywhere inside the view will be deleted at the end of that very same method
You should add your object inside each header file's interface section like this:
SomeView.h
#import <UIKit/UIKit.h>
#import "HeadViewController.h"
#import "SomeClass.h"
#interface SomeView : UIViewController
{
SomeClass *someClassObject;
}
// contains stuff not needed to show here
- (IBAction)Done:(id)sender;
#end
Then when you instantiate someClassObject inside ViewDidLoad it will persist throughout that view.
First of all, sorry if the title is misleading. This is literally my first ever creation with Xcode, so I may be a bit off with what everything is called and such.
So, I have a class with a few IBAction's, something like this:
// AppController.h
#import <Foundation/Foundation.h>
#interface AppController : NSObject {
}
+ (void)addItem;
- (IBAction)addButton:(id)sender;
#end
And:
// AppController.m
#import "AppController.h"
#implementation AppController
+ (void)addItem {
NSLog("Action");
}
- (IBAction)addButton:(id)sender {
[[self class] addItem];
}
When I run the app and click the button that fires the IBAction, the app hangs and the Xcode-window becomes selected, with a green "breakpoint" on the line NSLog(...).
I have no idea what this reaction is called, nor what I am supposed to do about it. Any help is appreciated!
NSLog("Action");
The first argument of NSLog() must be an NSString, not a C string (char *). You missed the # character:
NSLog(#"Action");
is the correct approach.
Edit: if it's just a typo, and after fixing it, the problem still persists: then you most likely set a breakpoint on that particular line. Delete or disable the breakpoint to enable the program to continue.
I'm currently trying to develop an iPhone application.
Most things are working as I would expect and prefer.
Right now the issue I'm having is that when adding methods to one of my ViewControllers the methods are not visible from other parts of my applications.
When I add the same methods, with the same signature to my other view controllers they will be visible.
I've googled, browsed stackoverflow, reread, copy/pasted, and prayed to the spaghetti monster for divine insight, but to no avail.
There must be some minor detail, that I in my folly am overlooking. I hope you will be able to help me!
InfoPageViewController.h
#import <UIKit/UIKit.h>
#import "DB.h"
#interface InfoPageViewController : UIViewController
{
IBOutlet UIWebView* wv;
DB* db;
}
#property (retain, nonatomic) IBOutlet UIWebView* wv;
-(void) reloadInfoPage;
#end
InfoPageViewController.m
#import "InfoPageViewController.h"
#interface InfoPageViewController ()
#end
#implementation InfoPageViewController
#synthesize wv;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"Information", #"Information");
self.tabBarItem.image = [UIImage imageNamed:#"TabIcon-Settings"];
db = [[DB alloc] init];
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
DBInfoPage* dbip = [db getInfopage];
[wv loadHTMLString:dbip.html baseURL:nil];
//NSLog(#"word%#", dbip.html);
[self reloadInfoPage];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
-(void)reloadInfoPage
{
DBInfoPage* dbip = [db getInfopage];
[wv loadHTMLString:dbip.html baseURL:nil];
NSLog(#"reloading infopage%#", #"");
}
#end
infoviewtest.h
#import <UIKit/UIKit.h>
#import "InfoPageViewController.h"
#interface infoviewtest : NSObject
#end
infoviewtest.m
#import "infoviewtest.h"
#implementation infoviewtest
-(void)test
{
InfoPageViewController* ivc = [[InfoPageViewController alloc] init];
[ivc reloadInfoPage];
}
#end
This yields an error of "No visible #interface for 'InfoPageViewController' declares the selector 'reloadInfoPage'.
I have also tried to use autocomplete to show me the available methods of the 'InfoPageViewController', this yields a list not containing 'reloadInfoPage', similarly the instance variable 'wv' is not visible from outside of the scope of the class.
I have tried closing and reopening xcode, as well as restart the computer.
I have also tried to 'clean' the project.
Any help will be greatly appreciated by the parts of my hair, not yet pulled in frustration.
If I have been lacking in providing information, please request and I'll do my best to respond.
Johan Abildskov
Actually your code look correct - all you have to do is probably clean the project and possibly restart XCode.
But you could optimize the linking/compiling by making some modifications like:
infoviewtest.h
#import <UIKit/UIKit.h>
//#class InfoPageViewController; //add this if you'll be adding ivar or property of this type
#interface infoviewtest : NSObject
#end
infoviewtest.m
#import "infoviewtest.h"
#import "InfoPageViewController.h" //here's the place to import other headers
#implementation infoviewtest
-(void)test
{
InfoPageViewController* ivc = [[InfoPageViewController alloc] init];
[ivc reloadInfoPage];
}
#end
EDIT: Make sure that your implementation of DB class is correct. XCode error might lead you to wrong assumptions. Again: the code you've posted seems correct, just not optimized for compilation.
I've noticed an odd issue with test targets, when you don't include a class in the test target it still compiles, this could could be whats happening here so:
Have you included InfoPageViewController in your test target?
Your code is perfect it seems. Even DB.h having the same method name, it will not affect the declaration of the same method in your controller class. Its quite strange error. Probably your XCode might get corrupted. Try to update Xcode and try the same code. If you are updating Xcode, update the iTunes too. This may fix your problem I think.
Just in case anyone else is suffering from this weird problem as I just did - the cause in my case was due to my ending up with 2 copies of the same class .m & .h files in different directories of my project after my Xcode newbie fumbling attempt to move them from one disk directory to another while keeping them in the same Xcode group. Xcode ended up allowing me to edit one set of files but used the other for compilation so the method that I added really didn't exist as far as the compiler was concerned, hence the above error message.