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.
Related
What I want to have happen:
Items in array show up in a label. Each item in the array will have it's own label.
I eventually want to add more items.
And make it so that index 0 of thisArray can be added to index 0 of that array; display in a label;
object at index 1 in thisArray can be added to object at index 1 in thatArray and then the result can be displayed in a separate label,
and so on
To appear on a button click.
I'm having a lot of trouble implementing this and I feel like it is a lot simpler than I am making it. Any insight would be appreicated!!
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.steakArray = [[NSArray alloc] initWithObjects: #"800", #"50", nil];
//NSString *name;
NSString *calories = [_steakArray objectAtIndex:0];
NSString *fat = [_steakArray objectAtIndex:1];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//this doesn't work, this is what I want to have happen though.
//click button, show this in label.
- (IBAction)steak:(id)sender {
self.infoLabel.text = calories, fat;
}
#end
You need to look at this documentation https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Strings/Articles/FormatStrings.html
You can use String with Format:
NSString *string1 = [NSString stringWithFormat:#"A string: %#, a float: %1.2f",
#"string", 31415.9265];
// string1 is "A string: string, a float: 31415.93"
NSNumber *number = #1234;
NSDictionary *dictionary = #{#"date": [NSDate date]};
NSString *baseString = #"Base string.";
NSString *string2 = [baseString stringByAppendingFormat:
#" A number: %#, a dictionary: %#", number, dictionary];
// string2 is "Base string. A number: 1234, a dictionary: {date = 2005-10-17 09:02:01 -0700; }"
Even if you are getting calories in string, you can use the following code to add and display in the label
NSString *calories1 = [_steakArray objectAtIndex:0];
NSString *calories2 = [_steakArray2 objectAtIndex:0];
int sum = [calories1 intValue] + [calories2 intValue];
self.infoLabel.text = [NSString stringWithFormat:#"%d",sum];
I guess its a very basic memory concept. But couldn't figure it out what happens with below case. Any insight would be helpful.
This could be similar to Problems with NSString inside viewWillDisappear
But I wanted to know why there requires a #property. How can we do it without taking #property. Please provide some inside view.
in .h I have NSString *someString
in .mm (this is my non-ARC cocos2d+box2d game scene)
-(id)initWithString:(NSString *)tempString
{
if(self = [super init])
{
someString = [[NSString allo]init];
someString = tempString;
}
return self;
}
-(void)onEnterTransitionDidfinish
{
[super onEnterTransitionDidfinish];
NSLog("The String is %#",someString);//Becomes nil here
}
-(void)printString
{
NSLog(#"The String is %#",someString);//This works fine
}
If you are not using ARC then you need to learn a lot more about memory management.
The following two lines:
someString = [[NSString allo]init];
someString = tempString;
should be:
someString = [tempString copy]; // or [tempString retain];
And be sure you call [someString release] in your dealloc method.
BTW - you are not using a property. someString is declared as an instance variable, not a property.
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(#"----------------------------");
}
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...
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.