Reading data from a file in Objective-C, how to? [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'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.

Related

localizable.strings not working with Arabic string

I created a Localizable.strings file in XCode and then 2 languages in it.(english + Arabic )
I filled up these files with the language translations, but the just show translation in english, when I start with Arabic the key appear!
in my code :
NSLocalizedString("title", comment: "")
Localizable.strings(english)
"title" = "Error" ;
Localizable.strings(Arabic)
"title" = "خطأ" ;
I careated sample one and tried in Objective C.I got it.
I set "title" = "خطأ" in Arabic Localization files
"title" = "عنوان";
Now I have to change English to Arabic.
First I set the design in storyboard
Then Click Project.Choose Localization in Info
If you click the +(Below Localization) it shows the pop up view
Now choose Arabic.When click Arabic it shows window.You should click finish.
We need to create the string file for the localization now.I set string file name as LocalizationArabic
Once you create the String file it looks like below.
Then click File Inspector when pressing LocalizationArabic string file.Now click the Localization.It shows Empty Check box Arabic and English like below.
Here we must check the check box.Also when we check the check box the LocalizationArabic folder creates with three string files like below
Then I entered the language which I want to translate from English to Arabic in string file.
Finally I created the Header file for the Localization Language
The Header file name is LanguageHeader.It looks like below.
Now the code part starts here
First the Localization class of NSObject class
Localization.h
#import <Foundation/Foundation.h>
#import "LanguageHeader.h"
#interface Localization : NSObject
+(Localization *)sharedInstance;
+(NSString*) strSelectLanguage:(int)curLang;
+(NSString*) languageSelectedStringForKey:(NSString*) key;
#end
Localization.m
#import "Localization.h"
int currentLanguage,selectedrow;
#implementation Localization
+(Localization *)sharedInstance
{
static Localization *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[Localization alloc] init];
});
return sharedInstance;
}
+(NSString*) strSelectLanguage:(int)curLang{
if(curLang==ARABIC){
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:#"ar", nil]forKey:#"AppleLanguages"];
}
else{
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:#"en", nil]forKey:#"AppleLanguages"];
}
[[NSUserDefaults standardUserDefaults] synchronize];
currentLanguage=curLang;
NSString *strLangSelect = [[[NSUserDefaults standardUserDefaults]objectForKey:#"AppleLanguages"] objectAtIndex:0];
return strLangSelect;
}
+(NSString*) languageSelectedStringForKey:(NSString*) key
{
NSString *path;
NSString *strSelectedLanguage = [[[NSUserDefaults standardUserDefaults]objectForKey:#"AppleLanguages"] objectAtIndex:0];
//When we check with iPhone,iPad device it shows "en-US".So we need to change it to "en"
strSelectedLanguage = [strSelectedLanguage stringByReplacingOccurrencesOfString:#"en-US" withString:#"en"];
if([strSelectedLanguage isEqualToString:[NSString stringWithFormat: #"en"]]){
currentLanguage=ENGLISH;
selectedrow=ENGLISH;
path = [[NSBundle mainBundle] pathForResource:#"en" ofType:#"lproj"];
}
else{
currentLanguage=ARABIC;
selectedrow=ARABIC;
path = [[NSBundle mainBundle] pathForResource:#"ar" ofType:#"lproj"];
}
NSBundle* languageBundle = [NSBundle bundleWithPath:path];
NSString* str=[languageBundle localizedStringForKey:key value:#"" table:#"LocalizationArabic"];
return str;
}
#end
Then ViewController.h
#import <UIKit/UIKit.h>
#import "Localization.h"
#interface ViewController : UIViewController{
Localization *localization;
}
#property (strong, nonatomic) IBOutlet UILabel *lblTitle;
- (IBAction)actionChangeLanguageToArabic:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize lblTitle;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
localization = [Localization sharedInstance];
lblTitle.text = [Localization languageSelectedStringForKey:#"title"];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)actionChangeLanguageToArabic:(id)sender {
[Localization strSelectLanguage:ARABIC];
lblTitle.text = [Localization languageSelectedStringForKey:#"title"];
}
#end
Above code works perfectly.
Output Screen shot are below
When run the app first
After clicking the button

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.

Reading and writing data to a property list

I know this question has been asked a hundred times here because I have been reading most of the questions about reading and writing to plists in this forum, in fact this is the main reason why I'm posting this question. I'm tired of trying outdated tutorials about this topic. I have tried a few tutorials but most of them are using .xib files or are not using ARC and I usually end up with a bunch of errors.
Does anyone know about a tutorial about reading/writing to a plist that uses storyboards and ARC? In other words an updated tutorial.
All I need is a tutorial that I can reference to have a better understanding on how to persist data using plists.
Thanks a lot
Here is a very simple piece of code that shows how to read and write to a plist. Code is based on this tutorial.
What I have here is basically two labels and two buttons on screen, one button to write the data and the other one is to read the data when clicked, the two labels are to show the first two items from an array (plist), item 0 will be shown in the first label and item 1 will be shown in the the second label.
.m file
-(NSString *)getFilePath
{
NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [[pathArray objectAtIndex:0] stringByAppendingPathComponent:#"fruitList.plist"];
}
-(void)saveData
{
NSArray *value = [[NSArray alloc] initWithObjects: #"Orange", #"Apple", nil];
[value writeToFile:[self getFilePath] atomically:YES];
}
-(void)loadData
{
NSString *myPath = [self getFilePath];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:myPath];
if(fileExists)
{
NSArray *values = [[NSArray alloc]initWithContentsOfFile:myPath];
self.labelOne.text = [values objectAtIndex:0];
self.labelTwo.text = [values objectAtIndex:1];
}
}
- (IBAction)writeData:(id)sender
{
[self saveData];
}
- (IBAction)readData:(id)sender
{
[self loadData];
}
.h file
#property (weak, nonatomic) IBOutlet UILabel *labelOne;
#property (weak, nonatomic) IBOutlet UILabel *labelTwo;
-(NSString*) getFilePath;
-(void) saveData;
-(void) loadData;
- (IBAction)writeData:(id)sender;
- (IBAction)readData:(id)sender;

How to access dictionaries within other methods?

Below is the code I am using to try and access the initialised dictionary with another method:
#import "UserFoodData.h"
#implementation UserFoodData
-(void)loadUserFoodData{
NSString *appDataPath = [[NSBundle mainBundle] pathForResource:#"UserFoodData" ofType:#"plist"];
NSMutableDictionary *userFoodDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:appDataPath];
for (userFoodDictionary in userFoodDictionary){
NSLog(#"%#", userFoodDictionary);
}
}
-(void)setName:(NSString *)foodName andCarbs:(NSNumber *)carbAmount{
[userFoodDictionary setObject:foodName forKey:foodName];
}
#end
The error messages I seem to be getting is:
Use of undeclared identifier 'userFoodDictionary'
Now what I believe is wrong is that the compiler believes that there is a possibility that the setName:andCarbs method could but executed before the loadUserFoodData Which is called when the apps main screen has been initialised. Could someone please help me with a work around?
The error messages I seem to be getting is:
Use of undeclared identifier 'userFoodDictionary'
Compiler says:
1. I didn't see any variable like userFoodDictionary locally or instance variable in -(void)setName:(NSString *)foodName andCarbs:(NSNumber *)carbAmount.
2. But you are trying to access it.
and also your for loop has mistakes. please verify my answer
Compiler is trying to look for userFoodDictionary in "UserFoodData" class. Because you are accessing userFoodDictionary outside of loadUserFoodData method. So in order to access outside of local method you must keep that reference in header file then you can access it any where in class.
#interface UserFoodData : NSObject
#property(nonatomic,retain)NSMutableDictionary *userFoodDictionary;
#end
#import "UserFoodData.h"
#implementation UserFoodData
//#synthesize userFoodDictionary; synthesise is automatically entered by compiler
-(void)loadUserFoodData{
NSString *appDataPath = [[NSBundle mainBundle] pathForResource:#"UserFoodData" ofType:#"plist"];
self.userFoodDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:appDataPath];
//Please not down this
for (id aFood in userFoodDictionary){
NSLog(#"%#", aFood);
}
}
-(void)setName:(NSString *)foodName andCarbs:(NSNumber *)carbAmount{
[self.userFoodDictionary setObject:foodName forKey:foodName];
}
#end
I'm assuming you get the error in the second method that you posted.
- (void)setName:(NSString *)foodName andCarbs:(NSNumber *)carbAmount{
[userFoodDictionary setObject:foodName forKey:foodName];
}
userFoodDicitionary is not defined in that method. If you want the dictionary to persist between method calls, store it in a #property.
You should really read some introductory material to Objective-C, you could start with this Apple document
There are multiple issues here...
For one, your for loop has a syntax error...not only that, but you're trying to iterate through a dictionary named userFoodDictionary with an iterator variable also named userFoodDictionary. Change that to something like:
for (id dictKey in userFoodDictionary) {
NSLog(#"%#", dictKey);
}
You're also trying to access a variable out of scope. userFoodDictionary is declared within the scope of loadUserFoodData. After that method completes, the variable is deallocated, so of course you can't access it in setName:andCarbs:. To do that, you need to define it in a wider scope -- make a property, a static variable, an iVar, etc.
There are many lacking OOP concepts here...if you are new to programming, Objective-C is a difficult place to start, and it may throw you for many loops (pun intended).
Try this...
#import "UserFoodData.h"
#implementation UserFoodData
-(void)loadUserFoodData{
NSString *appDataPath = [[NSBundle mainBundle] pathForResource:#"UserFoodData" ofType:#"plist"];
NSMutableDictionary *userFoodDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:appDataPath];
for (userFoodDictionary in userFoodDictionary){
NSLog(#"%#", userFoodDictionary);
}
}
-(void)setName:(NSString *)foodName andCarbs:(NSNumber *)carbAmount{
NSString *appDataPath = [[NSBundle mainBundle] pathForResource:#"UserFoodData" ofType:#"plist"];
NSMutableDictionary *userFoodDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:appDataPath];
[userFoodDictionary setObject:foodName forKey:foodName];
}
#end
Let me know if that helps... :)
I think the issue is your NSMutableDictionary should be ivar that is declare NSMutableDictionary in .h as follow
NSMutableDictionary *userFoodDictionary
in .m
-(void)loadUserFoodData{
NSString *appDataPath = [[NSBundle mainBundle] pathForResource:#"UserFoodData" ofType:#"plist"];
userFoodDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:appDataPath];
for (userFoodDictionary in userFoodDictionary){
NSLog(#"%#", userFoodDictionary);
}
}
-(void)setName:(NSString *)foodName andCarbs:(NSNumber *)carbAmount{
[userFoodDictionary setObject:foodName forKey:foodName];
}
So the issue is in the below line
for (userFoodDictionary in userFoodDictionary){
NSLog(#"%#", userFoodDictionary);
}
replace it with
for (NSMutableDictionary *userFoodDic in userFoodDictionary){
NSLog(#"%#", userFoodDic);
}
May this will solve your issue
ok Got the other issue too
Please declare the userFoodDictionary as one of the property too
as described by #Sebastian in his answer :)

Calling method from another file [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 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...

Resources