How to add additions in a cocoa touch static library - iphone

I'm writing a simple static library for myself recently. It include some ui control, macro, and additions of cocoa touch class, but there's something wrong with my code, and I don't know how to solve it.
I did these steps:
create a cocoa touch static library project named Orange, just for test.
add a NSObject subclass named MyMath, implement code.
add 2 files for NSArray addition, implement code.
move the project directory to "/".
create a window based application named TestOrange.
drag the Orange.xcodeproj into TestOrange.
set header search paths to "/Orange/Orange"
set Build Phases like the image bellow showed.
when i run the TestOrange, it can print the result of MyMath, but crash immediately.
MyMath can work, but NSArrayAdditions can't work. I think there's something wrong with NSArrayAdditions.
anyone encountered this problem before? please help me.
thanks in advance.
all code have listed here.
MyMath
#interface MyMath : NSObject {
}
- (NSNumber*)AddA:(int)a B:(int)b;
#end
#implementation MyMath
- (NSNumber*)AddA:(int)a B:(int)b {
return [NSNumber numberWithInt:a+b];
}
#end
NSArrayAdditions
#interface NSArray (Additions)
- (NSNumber*)Double:(int)a;
#end
#implementation NSArray (Additions)
- (NSNumber*)Double:(int)a {
return [NSNumber numberWithInt:2*a];
}
#end
use libOrange
#import "TestOrangeAppDelegate.h"
#import "MyMath.h"
#import "NSArrayAdditions.h"
#implementation TestOrangeAppDelegate
#synthesize window=_window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
MyMath *mm = [[MyMath alloc] init];
NSLog(#"%#", [mm AddA:12 B:23]);
[mm release];
NSArray *ary = [[NSArray alloc] init];
NSLog(#"%#", [ary Double:13]);
[ary release];
[self.window makeKeyAndVisible];
return YES;
}
#end

Try adding -ObjC and -load_all to your "other linker flags" in your build settings.
Basically, categories on framework classes don't necessarily get linked in unless you specify this flag.
-load_all will force the loading of all compiled classes, which solves the problem.

Related

Cant call instance methods from other classes

I hope you can help me with the following problem in Objective-C. I´ve been sitting around for two hours now, but I have no idea what´s wrong.
Here´s my code:
BMICalc.h:
#import <UIKit/UIKit.h>
#interface BMICalc : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate>
#property (strong, nonatomic) NSMutableArray *bmiArray;
-(int)bmiRows;
#end
BMICalc.m:
#import "BMICalc.h"
#implementation BMICalc
#synthesize bmiArray;
- (int) bmiRows
{
if (!bmiArray)
{
bmiArray = [[NSMutableArray alloc] init];
}
return [bmiArray count];
}
#end
Now I want to create a object of BMICalc in another class called BMIDiaryController:
BMIDiaryController.m:
#import "BMIDiaryController.h"
#import "BMICalc.h"
#interface BMIDiaryController ()
#end
#implementation BMIDiaryController
- (void)viewDidLoad
{
[super viewDidLoad];
BMICalc *bmiSender = [[BMICalc alloc] init];
int bmiVariable = [bmiSender bmiRows];
}
#end
So when I start the programme i get the following error:
"No visible #interface for 'BMICalc' declares the selector 'bmiRows'
I can´t call the method "bmiRows" with the object "bmiSender" (both of Class "BMICalc"
I hope you can help me with this. I searched and searched...I think it´s just a small thing, but I won´t see it...
Thank you and regards,
Stefan
Try creating a new project. Then add the BMICalc.m and BMICalc.h files. Try to instantiate your BMICalc object and call the bmiRows method from the appDelegate just to test it. There could be any number of things wrong in your main project that may be interfering with the class. At least doing this will confirm that you aren't crazy and that this code isn't the problem :)

objective-c/iphone sdk newcomer question

At present I'm building a basic application to learn Objective-C and the iPhone SDK.
I'm creating NSObject with getters and setters to get to grips with how these works. I've successfully added a property and getters and setters to my main controller, currently I'm trying to create a separate class which I can create a new instance of within my controller but it crashes when I try and use the setter.
Thank you in advance for your time, sorry if this question is as stupid as I'm sure it is.
Here's the header for my class
QuizQuestion.h
#import <Foundation/Foundation.h>
#interface QuizQuestion : NSObject {
NSString *question;
}
#property (retain) NSString* question;
#end
QuizQuestion.m
#import "QuizQuestion.h"
#implementation QuizQuestion
#synthesize question;
- (void) dealloc
{
[question release];
[super dealloc];
}
#end
And here is my controller code (i've cut some out)
#implementation Quiz2ViewController
#class QuizQuestion; // Is this correct?
- (void)viewDidLoad {
QuizQuestion *aQuestion;
//gets here fine, but crashes (the app closes) when I set question.
[aQuestion setQuestion:#"hello world"];
[super viewDidLoad];
}
#end
As well as #class I tried import "QuizQuestion.h" and I get the same issue.
You're not actually allocating an instance of the QuizQuestion class—your aQuestion variable isn’t pointing to anything in particular, so trying to send it a message, like -setQuestion:, is sending that message to... well, there’s no telling where, and sending things messages that aren’t meant for them is a surefire way to crash your app. What you need to do is this:
QuizQuestion *aQuestion = [[QuizQuestion alloc] init];
[aQuestion setQuestion:#"hello world"];
You also need to call [aQuestion release] at some point, or you’ll leak the memory associated with it.
You need to allocate space and initialize the QuizQuestion.
QuizQuestion *aQuestion = [[QuizQuestion alloc] init];
before setting the question.
I think you need to read up on some documentation before you try any more coding. Apple has several intro programming guides that are very good. The problem you are having is addressed in this section:
http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocAllocInit.html
QuizQuestion *aQuestion = [[QuizQuestion alloc] init];
[aQuestion setQuestion:#"hello world"];
[aQuestion release];

NSMutableArray count keeps changing

I have too much code to know which i need to quote here, but in my app delegate I have an NSMutableArray. Then in another class, it creates a new entry to the NSMutableArray but upon passing back to another class which should use that to display something on screen, it doesn't display anything. Putting an NSLog for the NSMutableArray count at the end of the class creating it displays the number 1, and then putting the same NSLog code at the start of the class which is meant to use that returns 0.
Any ideas why this is?
EDIT: Ok, i'll try and include all related code..
app delegate.h:
#interface palettesAppDelegate : NSObject <UIApplicationDelegate> {
NSMutableArray *colourPalettesContainer;
}
#property (assign, readwrite) NSMutableArray *colourPalettesContainer;
#end
app delegate.m:
#import "palettesAppDelegate.h"
#implementation palettesAppDelegate
#synthesize colourPalettesContainer;
- (void)dealloc {
[colourPalettesContainer release];
[super dealloc];
}
#end
Homeview.h:
#import <UIKit/UIKit.h>
#import "HandlingPalettes.h"
#interface HomeView : UIViewController {
HandlingPalettes *handlingPalettes;
}
#end
Homeview.m:
#import "HomeView.h"
#import <QuartzCore/QuartzCore.h>
#implementation HomeView
- (void)viewDidLoad {
[super viewDidLoad];
handlingPalettes = [[HandlingPalettes alloc] init];
[handlingPalettes newPalette];
}
-(void)viewWillAppear:(BOOL)animated {
NSLog(#"view will appear: %i", [dataCenter.colourPalettesContainer count]);
int numberOfExisting = [dataCenter.colourPalettesContainer count];
}
- (void)dealloc {
[handlingPalettes release];
[super dealloc];
}
#end
HandlingPalettes.h:
#import <UIKit/UIKit.h>
#interface HandlingPalettes : UIViewController {
}
-(void)newPalette;
#end
HandlingPalettes.m:
#import "HandlingPalettes.h"
#import "HomeView.h"
#import "palettesAppDelegate.h"
#implementation HandlingPalettes
-(void)newPalette {
palettesAppDelegate *dataCenter = (palettesAppDelegate *)[[UIApplication sharedApplication] delegate];
//If this is the first palette
if (dataCenter.colourPalettesContainer == nil) {
dataCenter.colourPalettesContainer = [[NSMutableArray alloc] init];
}
//Add a new palette
[dataCenter.colourPalettesContainer addObject:#"Test1", #"Test2", nil];
NSLog(#"Handling: %i", [dataCenter.colourPalettesContainer count]);
}- (void)dealloc {
[super dealloc];
}
#end
Your main mutablearray is in your app delegate. So, see what happens if in EVERY METHOD that you want to access the array you have the line to set up the app delegate relationship
palettesAppDelegate *dataCenter = (palettesAppDelegate *)[[UIApplication sharedApplication] delegate];
Now, when you call the dataCenter object you will be referencing the App Delegate and your program will find the array.
You may also find that you will need to have an #import "palettesAppDelegate.h" in each object that is going to reference the App Delegate.
Note, just adding the app delegate code is not necessarily the proper way to deal with this issue from an architectural standpoint. But if it works you at least know the answer to your original question.
I suspect the problem is ultimately related to confused memory management of the colourPalettesContainer member. You release it in the app delegate's dealloc method, but that class never retains it! It would be much cleaner if you'd follow Apple's memory management guidelines: your classes should only release objects that they own (i.e., that they themselves retained earlier). For example, you can do this by declaring the array's property retain:
#property (retain) NSMutableArray *colourPalettesContainer;
(To prevent leaking the array, you'll also need to release or autorelease it in the newPalette method. Retain and release should always come in close pairs.)
But even better, why not simply create the array in the app delegate's init method, or in its accessor (if for some reason you want to continue creating it only on its first use)? Unless you want to replace all palettes at once, there is no reason to let the array be assigned to from outside the app delegate.
#interface PalettesAppDelegate : NSObject <UIApplicationDelegate> {
#private
NSMutableArray *colourPalettesContainer;
}
#property (readonly) NSMutableArray *colourPalettesContainer;
#end
#implementation PalettesAppDelegate
- (NSMutableArray *)colourPalettesContainer {
if (colourPalettesContainer == nil) {
colourPalettesContainer = [[NSMutableArray alloc] init];
return colourPalettesContainer;
}
- (void)dealloc {
[colourPalettesContainer release];
[super dealloc];
}
#end
To make the design even cleaner, change the type of the colourPalettesContainer property to NSArray * and add an -addPalette: method to the app delegate. (It is rarely a good idea to publicly expose a mutable array inside a class.) You can then simply get rid of -newPalette in HandlingPalettes. (If you want to have all your palette-handling methods in HandlingPalettes, then simply move the array there. If you need to access the palettes from random places in your app, then you can simply put a retained reference to your HandlingPalettes object in the app delegate.)
Once you clean up the object ownership mess, the count mismatch will either resolve itself "by magic" or the cause will likely become much more obvious. In the latter case, check that the HomeView's dataCenter is actually the same object as the one in HandlingPalettes. (You omitted how HomeView gets its reference — are you sure you aren't creating another instance of the app delegate by accident?)
(By the way, you probably meant to use -addObjects:, not -addObject: in newPalette. Note also that all class names should be capitalized, with no exceptions: i.e., always use PalettesAppDelegate, never palettesAppDelegate. If for some reason Xcode's project template created it like that, simply rename the class. Lowercase class names are much too easy to confuse with variable names. Also, try to find better names in general: e.g., instead of HandlingPalettes, I'd use PalettesViewController (to reflect the fact that it is a subclass of UIViewController); and instead of dataCenter, I'd rather just choose appDelegate.)
I would be inclined to get rid of the newPalette method, and instead create a getter method for colourPalettesContainer in your app delegate.
ie:
appdelegate.h
#interface PalettesAppDelegate : NSObject <UIApplicationDelegate> {
NSMutableArray *colourPalettesContainer;
}
#property (non-atomic, retain) NSMutableArray *colourPalettesContainer;
#end
#implementation palettesAppDelegate
appdelegate.m
#import "appdelegate.h"
#synthesize colourPalettesContainer;
- (NSMutableArray *) colourPalettesContainer{
if(colourPalettesContainer==nil){
colourPalettesContainer=[[NSMutableArray alloc] init];
}
return colourPalettesContainer;
}
- (void)dealloc {
[colourPalettesContainer release];
[super dealloc];
}
#end
you should then be able to add items by calling
[appDelegate.colourPalettesContainer addObject:object];

method not found

I'm working on an application with three tabs plus a small view in which I created a sort of TopBar that contains some info and some buttons.
In the main application delegate I define:
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
...
// Add the tab bar controller's current view as a subview of the window
[window addSubview:tabBarController.view];
//here we add the topBar:
topBarViewController = [TopBarViewController instance];
topBarViewController.appDelegate = self;
[window addSubview:topBarViewController.view];
...
}
- (void)showReplyView
{
self.tabBarController.selectedViewController =
[self.tabBarController.viewControllers objectAtIndex:2];
}
as you can see I set the .appDelegate in the topBar to make some call back in the code of the topBar (ie: when I want to change the tab currently visualized)
Now in my TopBarViewController.h I have:
#interface TopBarViewController : UIViewController {
MyAppDelegate *appDelegate;
...
}
#property (nonatomic,retain) MyAppDelegate *appDelegate;
-(void)testMethod;
and in the .m file:
#implementation TopBarViewController
#synthesize appDelegate;
...
-(void)testMethod{
[appDelegate showReplyView];
}
...
When I build the project the compiler tell me that the showReplyView method doesn't exist.
I tried everything and I'm sure that there are no typo errors...
Is it possible that I can't reference to the delegate?
Thanks to anyone would help me...
I found the problem:
in the TopBarViewController.h I was declaring #class MyAppDelegate; since I couldn't make an import (avoid the loop).
So the compiler was not able to find out which methods were declared.
To solve it I import the #import MyAppDelegate.h directly in the TopBarViewController.m!
Thanks anyway for the help!
Have you defined showReplyView in the #interface for MyAppDelegate?

How to display complex object in debugger?

I'd like to display the contents of the property myarray, from the following singleton:
[Session sharedManager].myarray
I've tried these:
po [Session sharedManager]. myarray
po [[Session sharedManager] myarray]
but always get this error:
A syntax error near end of expression.
Any suggestions?
--- EDIT ---
I'm working with SDK 3.0.
I've discovered the problem, which is I had three open brackets rather than two. You can't see that here because I mistyped the number of brackets. It is working now. Thanks.
If you use XCode Debugger and you set a breakpoint in the some place that the variable is already initialized and can be seen, you can click to the variable and choosing Print Description.
You can do it in simple way like NSLog(). What is the problem with this approach? Usually, I see that it will print out all the description() method of all objects in the array?
And I am not sure, but you lack a semicolon at the end of the statement. ";", can you recheck for that one?
What you are describing is very strange. I set up a test application and was able to print the object from the singleton just fine.
#import "testAppDelegate.h"
//A Session Singleton
#interface Session : NSObject {
NSArray *myArray;
}
#property (nonatomic, retain) NSArray *myArray;
#end
#implementation Session
#synthesize myArray;
static Session *sharedSession;
+(Session *)sharedSession {
if (!sharedSession) {
sharedSession = [[Session alloc] init];
sharedSession.myArray = [NSArray arrayWithObjects:#"A",#"B",#"C",nil];
}
return sharedSession;
}
#end
//App Delegate
#implementation testAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(#"%#",#"Breakpoint Here"); //Here is where I set My breakpoint
return YES;
}
- (void)dealloc {
[super dealloc];
}
#end
In GDB:
(gdb) po [[Session sharedSession] myArray]
<NSCFArray 0x4710630>(
A,
B,
C
)
I did this using the 3.2 iPhone SDK, using a default project template, in the debug mode without changing any build settings. I suspect you may have issues in your build settings. I have noticed that debugging is wonky on the 4.0 beta sdks. If you are using 4.0, remember that it is still beta, and your problems may really be someone else's problems.