Calling method from another file [closed] - ios

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I am a beginner in Objective-C. I would like to call the method two in file you.m from file me.m. Could you please teach me with simple example showing below to understand. Thank you!
you.h
#import <Foundation/Foundation.h>
#interface you : NSObject {
}
- (NSString *)one;
- (NSString *)two;
#end
you.m
#import "you.m"
#implementation you
- (NSString *)one {
NSString *a = #"this is a test.";
return a;
}
-(NSString *)two {
NSString *b = [self one];
return b;
}
#end
me.h
#import <Foundation/Foundation.h>
#interface me : NSObject {
}
#end
me.m
#import "you.h"
#import "me.h"
#implementation me
-(void)awakeFromNib{
//NSString *obj = [[[NSString alloc] init] autorelease];
//NSString *str = [obj two]; // dont work
//NSString *str = [self two]; // dont work
// I'd like to call method *two* from here.
NSLog(#"%#", str);
}
#end

In me class, create an instance of you.
you *objectYou=[you new];
As two returns a string, you need to store it :
NSString *string=[objectYou two];
In your code:
-(void)awakeFromNib{
you *objectYou=[you new];
NSString *str = [objectYou two];
NSLog(#"%#", str);
}
NOTE: Follow naming conventions. Class names must start with Capital letter like Me, You.
EDIT:
As you are learning, I would like to add one more thing, as you are calling one from two. If one is not meant to be called outside you class. You can define it in .m and remove the declaration from .h.

Simple, create an instance of You class in Me class and call that member function. Like so -
you *youInstance = [[you alloc] init];
NSString *retStr = [youInstance two];
Btw, its a good practice to CamelCase class names.
Also note this -
#interface you
- (NSString *) twoInstanceMethod;
+ (NSString *) twoClassMethod;
#end
NSString *retStr = [you twoClassMethod]; // This is ok
NSString *retStr = [you twoInstanceMethod]; // this doenst't work, you need an instance:
//so we create instance.
you *youInstance = [[you alloc] init];
NSString *retStr = [youInstance two];
Hope this clears some concepts...

Related

NSString : leak when assigning value to a property

Assuming we don't use ARC.
Suppose we have a very simple class in which we declare 2 NSString properties, like this :
#interface Foo : UIView {}
-(id)initWithArguments:(NSString*)mess title:(NSString*)tit;
#property(nonatomic, retain) NSString *message;
#property(nonatomic, retain) NSString *title;
#end
and in implementation :
#implementation Foo
#synthesize message, title;
-(id)initWithArguments:(NSString*)mess title:(NSString*)tit{
if((self = [super init])){
message = mess; // (1)
self.title = tit; // (2)
(...)
}
return self;
}
-(void)dealloc{
message = nil;
title = nil;
[super dealloc];
}
#end
Now if I call a method from another class, in which I create 2 NSString and an instance of Foo , like this :
-(void)someMethod{
NSString *string1 = [NSString stringWithFormat:#"some text with %d things", 5];
NSString *string2 = [NSString stringWithFormat:#"other text with %d things", 5];
Foo *foo = [[Foo alloc] initWithArguments:string1 title:string2];
}
The whole code works fine and doesn't crash, but, if I profile it with instruments,
it doesn't cause a leak when calling (1)("message = mess;")
it cause a leak when calling (2)("self.title = tit;")
It's very confusing, because stringWithFormat is an autoreleased object, isn't it ?
So, how an autoreleased object can cause a leak when assigning to a property ???
I read somewhere that it's almost always better to use the "self.text = value;" form instead of the "text = value;" form, because the second one may cause a leak.
Actually, in this code it's the contrary.
And... If I use a constant NSString like #"some text", instead of the values returned by [NSString stringWithFormat], there is no leak, of course.
Any idea ?
You have forgotten to invoke the (compiler-generated) setter methods in a few cases:
self.message = mess; // in init method
self.message = nil; // in dealloc method
self.title = nil; // ditto
It's crucial that you use the setter/getter methods in non-ARC code.

xCode won't allow addObject

absolute beginner here. I'm trying to teach myself Xcode using several different sources. My current lesson, I'm just trying to capitalize each word in a string. For some reason, I'm not given the option of using addObject, even though I've resorted to copying line for line what's in the book! Here's the code I'm using, I'm just typing it into the ViewController.m. I haven't touched the header file.
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *myString = #"How much wood could a woodchuck chuck";
NSArray *wordsInSentence = [myString componentsSeparatedByString:#" "];
NSLog(#"%#", wordsInSentence);
NSMutableArray *capitalizedWords = [[NSMutableArray alloc] init];
for (int word =0; word < [wordsInSentence count]; word++)
{
NSString *uncapitalizedWords = [wordsInSentence objectAtIndex:word];
NSString *capitalizedWords = [uncapitalizedWords capitalizedString];
[capitalizedWords addObject:capitalizedWords];
}
NSLog(#"%#", capitalizedWords);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
My problem is with
[capitalizedWords addObject:capitalizedWords];
When I begin typing, it doesn't even show addObject in the drop down box as an option, the only option I have is addObserver.
Any and all help would be much appreciated, Thanks
The problem is that you have two variables with the same name, capitalizedWords. One is the mutable array, the other is the string. And, thus, when you use capitalizedWords inside that for loop, it's using the string rendition. I would suggest renaming the string variable, e.g., replace:
NSString *uncapitalizedWords = [wordsInSentence objectAtIndex:word];
NSString *capitalizedWords = [uncapitalizedWords capitalizedString];
[capitalizedWords addObject:capitalizedWords];
with
NSString *uncapitalizedWord = [wordsInSentence objectAtIndex:word]; // renaming this isn't critical, but using singular case makes it more clear
NSString *capitalizedWord = [uncapitalizedWord capitalizedString]; // renaming this fixes the problem
[capitalizedWords addObject:capitalizedWord];
The problem is that you are naming the string the same as the array.
Try changing
NSString *capitalizedWords = [uncapitalizedWords capitalizedString];
[capitalizedWords addObject:capitalizedWords];
to:
NSString *capitalizedWordsString = [uncapitalizedWords capitalizedString];
[capitalizedWords addObject:capitalizedWordsString];
When you're declaring the string with the same name as the array you're shadowing the array and Xcode will see capitalizedWords as a string, not an array. That's why it doesn't present you with the addObject method.

Using NSMutableArray to keep Objects

I think that I'm missing some fundamental knowledge on Xcode Objective C programming standards. Unfortunately I couldn't find the appropriate solution to my problem.
The problem is that when I try to keep data in an array of objects it becomes impossible to keep them separately. Adding new objects overwrites the previous objects in array. Here is some code about that:
CustomObject.m file:
#import "CustomObject.h"
NSString * title;
NSString * detail;
#implementation CustomObject
- (void) initCustomObjectWithValues : (NSString *) iTitle : (NSString *) iDetail {
title = [NSString stringWithString:iTitle];
detail = [NSString stringWithString:iDetail];
}
- (NSString *) getTitle {
return title;
}
- (NSString *) getDetail {
return detail;
}
#end
viewDidLoad function in ViewController.m file:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
myMutableArray = [[NSMutableArray alloc] init];
for (int i=0; i<10; i++) {
NSString * tempTitle = [#"title " stringByAppendingString:[NSString stringWithFormat:#"%d",i]];
CustomObject * myCustomObject = [[CustomObject alloc] init];
[myCustomObject initCustomObjectWithValues :[NSString stringWithFormat:#"%#",tempTitle]
:[#"detail " stringByAppendingString:[NSString stringWithFormat:#"%d",i]]];
[myMutableArray addObject:myCustomObject];
}
for (int i=0; i<10; i++) {
NSLog(#"%#",[[myMutableArray objectAtIndex:i] getTitle]);
NSLog(#"%#",[[myMutableArray objectAtIndex:i] getDetail]);
NSLog(#"----------------------------");
}
}
Here, myMutableArray is defined at the top of the ViewController.m file. (To make it global and can be used in other functions in future)
Here what I've got in the logs:
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
As far as I understand each new added object overwrites the olds. First I thought that they are referring to same allocated memory but in debug tool myMutableArray seems like this:
Printing description of myMutableArray:
<__NSArrayM 0x8d8cb60>(
<CustomObject: 0x8d8e990>,
<CustomObject: 0x8d8dd40>,
<CustomObject: 0x8d8d2e0>,
<CustomObject: 0x8d8d470>,
<CustomObject: 0x8d8d350>,
<CustomObject: 0x8d8ddf0>,
<CustomObject: 0x8d8df00>,
<CustomObject: 0x8d8df40>,
<CustomObject: 0x8d8dff0>,
<CustomObject: 0x8d8e0c0>
)
Does anyone have an idea about the solution. It should be something very basic but I can't catch the problem.
Thank you all in advance
using
NSString * title;
NSString * detail;
outside of the #interface part creates global variables. When you assign a variable to title or detail you don't set an instance variable of your object, you change those global variables. And since they are global, they are the same for all objects that reference them.
Turn those global variables into instance variables, or even better use #property.
Your code is bad objective-c overall.
You should not use get in getters that return variables. You should not have methods that start with init and don't return self. You should only call init in [[Foo alloc] init...] situations. You should avoid unnamed parameters in your methods.
And there is no need to create strings from strings from strings.
Here is how I would write it:
// CustomObject.h
#interface CustomObject : NSObject
#property (copy, nonatomic) NSString * title;
#property (copy, nonatomic) NSString * detail;
- (id)initWithTitle:(NSString *)title detail:(NSString *)detail
#end
// CustomObject.m
#import "CustomObject.h"
#implementation CustomObject
- (id)initWithTitle:(NSString *)title detail:(NSString *)detail {
self = [super init];
if (self) {
// use stringWithString: to create #"" strings when title is nil
// if nil is a valid value for those variables you should use
// _title = [title copy];
_title = [NSString stringWithString:title];
_detail = [NSString stringWithString:detail];
}
return self;
}
#end
for (int i=0; i<10; i++) {
NSString *tempTitle = [NSString stringWithFormat:#"title %d",i];
NSString *tempDetail = [NSString stringWithFormat:#"detail %d",i];
CustomObject * myCustomObject = [[CustomObject alloc] initWithTitle:tempTitle detail:tempDetail];
[myMutableArray addObject:myCustomObject];
}
for (int i=0; i<10; i++) {
CustomObject *object = myMutableArray[i];
NSLog(#"%#", object.title);
// or NSLog(#"%#", [object title]); if you don't like dot-notation.
NSLog(#"%#", object.detail);
NSLog(#"----------------------------");
}

Reading data from a file in Objective-C, how to? [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I'm trying to develop an iOS app , that allow the user to enter a word then press the button to get the definition of the word
Actually I have a file which contains the words and their definitions such that
Apple , the definition
orange , the definition
I wrote the code but I don't know why it's not working
#import "ViewController.h"
NSString *readLineAsNSString(FILE *file);
#interface ViewController ()
#end
#implementation ViewController
#synthesize text;
#synthesize lab;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)butt:(id)sender {
FILE *file = fopen("1.txt", "r");
NSString *a = text.text ;
bool found =FALSE;
while(!feof(file)|| !found )
{
NSString *line = readLineAsNSString(file);
if ((a= [[line componentsSeparatedByString:#","] objectAtIndex:1])) {
lab.text = [[line componentsSeparatedByString:#","] objectAtIndex:0];
}
fclose(file);
}
}
#end
Can anyone help me to figure out what is wrong?
IMHO, a simple way to achieve this is through plist.
Here, a small example to achieve what you want.
1) Create your plist file.
In your project, go and "Add New File". In the left column, under iOS (for example), select "Resource". In the main panel select a "Property List" file. Save with a name like "Defs".
Your plist should look like the following.
2) Read the plist file (comments in the code)
- (void)readDefinitionsFile
{
// grab the path where the plist is located, this plist ships with the main app bundle
NSString* plistPath = [[NSBundle mainBundle] pathForResource:#"Defs" ofType:#"plist"];
// create a dictionary starting from the plist you retrieved
NSDictionary* definitions = [NSDictionary dictionaryWithContentsOfFile:plistPath];
// JUST FOR TEST PURPOSES, read the keys and the values associated with that dictionary
for (NSString* key in [definitions allKeys]) {
NSLog(#"definition for key \"%#\" is \"%#\"", key, [definitions objectForKey:key]);
}
}
Some notes
Above a simple example on how to use plist. It does not provide a complete example to achieve what you want. Based on that you will be able to reach your goal.
You should need a property to reference the dictionary you retrieved. So, for example, in your .m.
#interface ViewController ()
#property (nonatomic, strong) NSDictionary* definitions;
#end
#implementation ViewController
// other code here
// within readDefinitionsFile method
self.definitions = [NSDictionary dictionaryWithContentsOfFile:plistPath];
Use definitions to retrieve the definition you are interested in.
NSString* definition = [self.definitions objectForKey:#"aKeyYouWillRetrieveFromSomewhere"];
if(definition) {
NSLog(#"definition is %# for key %#", definition, #"aKeyYouWillRetrieveFromSomewhere");
} else {
NSLog(#"no definition for key %#", #"aKeyYouWillRetrieveFromSomewhere");
}
Hope that helps.

iOS parser alloc breakpoint

.h
#class HtmlParser
#interface ClassName : NSObject <UITableViewDataSource>
{
NSString *img;
HtmlParser *htmlParser;
}
: )
.M
- (NSString*)img
{
if (img!=nil) return img;
if (_description!=nil)
{
// NSString* description = [NSString stringWithString:_description];
htmlParser = [[HtmlParser alloc] loadHtmlByString:(NSString*) _description];
}
return img;
}
I am trying to initialize HtmlParser with the contents of description. "description" is RSS html loaded asynchronously, started in the tableViewController.
I get a breakpoint with or without the NSString* description. '-[HtmlParser loadHtmlbyString:]: unrecognized selector sent to instance 0x75aa9b0'... That's all the debugging I know how to do. Breakpoints are enabled for all exceptions.
-the method in .m is called in the viewController's cellForRowAtIndexPath:
ClassName *object = _objects[indexPath.row];
NSString *i = object.img;
UIImage* iG = [UIImage imageWithData:
[NSData dataWithContentsOfURL:[NSURL URLWithString:i]]];
cell.imageView.image = iG;
Its messy so let me know if further clarification is needed.
.h
#interface HtmlParser: NSObject <NSXMLParserDelegate>
{
ET Cetera
}
- (id) loadHtmlByString:(NSString *)string;
When you call the method in question:
htmlParser = [[HtmlParser alloc] loadHtmlbyString:(NSString*) _description];
It shouldn't have the (NSString *) in there. It should be:
htmlParser = [[HtmlParser alloc] loadHtmlbyString: _description];
But, is loadHtmlbyString an init method? If so, then you should start the name with init, and you should also adhere to the naming conventions by capitalizing all the words in the name (including By).
The 'loadHtmlbyStringmethod is not a method of theHtmlParserclass, it is a method of yourClassName` class.
Don't you get a compiler warning on this line:
htmlParser = [[HtmlParser alloc] loadHtmlbyString:(NSString*) _description];
Look at the .h for the HtmlParser class and see what methods are defined for that class.

Resources