Working with multiple objects in NSArray - ios

There's a table view that has a list of things. The user can select multiple rows in this table. I'm storing each in an array.
I then want to loop through that array to get each item in it's own string that I can set it up to a key.
Here's something I have tried:
for (NSString *str in self.myArray) {
if ([str isEqual:#"Blah"]) {
self.blahString = str;
} else {
self.blahString = #"";
}
if ([str isEqual:#"Blah Blah"]) {
self.blahblahString = str;
} else {
self.blahblahString = #"";
}
if ([str isEqual:#"Blah Blah Blah"]) {
self.blahblahblahString = str;
} else {
self.blahblahblahString = #"";
}
}
if (self.myArray.count == 0) {
[self.answersToPass setObject:#"" forKey:#"Blah"];
[self.answersToPass setObject:#"" forKey:#"Blah Blah"];
[self.answersToPass setObject:#"" forKey:#"Blah Blah Blah"];
} else {
[self.answersToPass setObject:self.blahString forKey:#"Blah"];
[self.answersToPass setObject:self.blahblahString forKey:#"Blah Blah"];
[self.answersToPass setObject:self.blahblahblahString forKey:#"Blah Blah Blah"];
}
The goal here is if the user doesn't select anything, then just set each objectForKey to an empty string, else pull out each string and match it to it's right key.
EDIT:
I believe I have solved my issue. I scratched the above code completely.
I found an 'order-of-operation' error on my end. Totally my fault. Should have looked through my code line-by-line more carefully.
If I encounter any issues with this again I'll update the post here.
I appreciate everyone's input and help. I apologize for not being thorough enough in my question.

Your question is not super lucidly worded, so I'll do my best but I'm not sure what precisely you want.
1) It sounds like you are checking all the time if the user selected something. Why? This is a terrible idea. Instead, add a responder to change stuff when the user actually does select something.
2) This manual setup is not great - what if someday you want to have 500 different items? Are you going to manually enter each if statement?
Try something more like this.
for (NSString *string in self.myArray)
{
if (self.answersToPass[string])
[self.answersToPass setObject: string forKey:string];
for (id key in self.answersToPass)
if (key isEqualToString:(string))
[self.answersToPass setObject: string forKey:key];
else [self.answersToPass setObject: "" forKey:key];
}
Please note that the above is not tested so you may have to fix some bug with my obj c notation or something but it should show the right idea.
I would note that this basic structure of a dict with strings equaling each other sounds very silly. Why store a key and value that either are equal or where the value is null and then check each time? Wouldn't it be easier to just hold an array of booleans? Or a map of strings to booleans?

You will better define a data structure (e.g. NSMutableArray or NSMutableDictionary) as a property, and store the str into it, so that you can access them at a later time.
#property (nonatomic, strong) NSMutableArray *array;
for (NSString *str in self.myArray) {
[array addObject str];
}

Related

Comaparing NSString in Objective C

Any one please help me to understand the String comparison technique in Objective-C
NSString *strNew1 = #"AA";
NSString *strNew2 = #"AA";
So to compare both the strings we could use,
Method 1. if (strNew1 == strNew2) {
NSLog(#"Equal");
}
or
Method 2: if ([strNew1 isEqualToString:strNew2]) {
NSLog(#"Equal");
}
In this condition both of them are success. But am aware that method 1 will get failed at certain other condition. And also I have tried the below conditions(All are success).
NSString *strNew = #"AA";
NSString *strNew1 = #"AA";
NSString *strNew11 = [[NSString alloc] initWithString:strNew1];
NSString *strNew3 = strNew;
NSArray *arr = #[#"AA"];
NSString *strNew4 = [arr objectAtIndex:0];
NSString *strNew5 = [arr objectAtIndex:0];
_test = strNew5;
_test1 = #"AA";
if ([strNew isEqualToString:strNew1]) {
NSLog(#"Equal");
}
if (strNew == strNew3) {
NSLog(#"Equal1");
}
if (strNew == [arr objectAtIndex:0]){
NSLog(#"Equal2");
}
if (strNew == strNew4){
NSLog(#"Equal3");
}
if (strNew5 == strNew4){
NSLog(#"Equal4");
}
if (strNew4 == [arr objectAtIndex:0]){
NSLog(#"Equal5");
}
if (strNew11 == [arr objectAtIndex:0]){
NSLog(#"Equal11");
}
if (self.test == strNew4){
NSLog(#"Equal3");
}
if (self.test == self.test1){
NSLog(#"Equal3");
}
TEST *test = [TEST new]; // Tried with a class with NSString property with value "AA" . (test.strTest value is #"AA")
if (strNew == test.strTest) {
NSLog(#"Equal"); //success
}
I knew most of them are redundant. Am not able to understand the basics behind this. Please anyone give clear explanation on the concept behind this. Thanks.
In the cases you defined the strings created are internally treated as string literals. The runtime will not allocate different memory space to such strings.
Essentially all the strings that contain the same string literal ("AA" in your case) will point to the same memory location. This is done as a part of memory optimization by Apple.
When you change the value of any string (say to "AB") a new address will be allocated to that NSString object and then == will fail.
You need to use below instance method of NSString class.
- (BOOL)isEqualToString:(NSString *)aString;
So, In your case simply follow below:
if ([strNew isEqualToString strNew4]){
NSLog(#"Equal3");
}
By doing (strNew == strNew4),
You are only comparing the addresses of the objects.
The first way compares pointers, while the second way compares objects.
That is, the first way compares if the pointers have the same value. In this case it is likely that they don't, in the second case the objects will be compared. Since they are initialized the same way they could be equal. (Note, it appears that with the UIButton's implementation of isEqual: the result is always false.)
In most cases using == is not what you want. However, what is appropriate depends on your objective.
if (strNew1 == strNew2) //This compared your pointers
{
}
and
if ([strNew1 isEqualToString:strNew2]) //Compares NSString object
{
}
Remember that isEqualToString: comes with a WARNING
[string1 isEqualToString: string2]
will effectively return false is both strings are nil.

Check if contain Null

When I print the following I get (null)
NSLog(#"%#", [[responseObject objectAtIndex:i] objectForKey:#"child"]);
Now I want to do a validation to check if it returns (null). How am I supposed to do this?
I tried the following but it doesn't work:
1.
if (![[[responseObject objectAtIndex:i] objectForKey:#"child"] isEqualToString:#"(null)"]) {
}
2.
if (![[[responseObject objectAtIndex:i] objectForKey:#"child"] isEqual:#"(null)"]) {
}
"null" isn't just a NSString. You should do some research into the concept of a null object.
What you're looking for can be written like this:
if (![[responseObject objectAtIndex:i] objectForKey:#"child"]) {
//key "child" not in dictionary
}
(null) is the representation of nil displayed by NSLog.
You can write the following:
if ([[responseObject objectAtIndex:i] objectForKey:#"child"] == nil) {
}
Or a shorter alternative:
if (![[responseObject objectAtIndex:i] objectForKey:#"child"]) {
}
Another way to check is to use string length. I know other answers are just as good, I am just giving OP and anyone else in future some more options.
NSString *childStr = [[responseObject objectAtIndex:i]objectForKey:#"child"];
if ([childStr length] < 1)
{
//no value specified - childStr is NULL
}
else
{
//there is something in the childStr - throw a party!
}
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"hello"]) {
NSLog(#"only if not null show %#",[defaults objectForKey:#"hello"]);
}
This is a way to check it from User Defaults. It will only print if the saved object does not equal null.

Objective C delete last NSString in NSMutableArray

I am trying to get the last NSString from a NSMutableArray, and delete it if it's empty.
Here is the code I am using:
- (void)viewWillAppear:(BOOL)animated {
if ([notes.data length]==0){
[storedText removeLastObject];
}
[self.tableView reloadData];
}
data is the NSString and storedText is the NSMutableArray. This code deletes the NSString even if it's not empty. I want it to keep the string if it contains text.
You should try something like this:
- (void)viewWillAppear:(BOOL)animated {
if ([[[storedText lastObject] data] length]==0){
[storedText removeLastObject];
}
[self.tableView reloadData];
}
BTW, it seems that your hypothesis that notes.data is the same string as the last object in storedText is not correct. This leads me to suspect that you have other kinds of errors in your code that you should also investigate. In other words, what you can expect is that your notes.data is not correct -- indeed, you should at least "update" it after you remove the last object from the array:
- (void)viewWillAppear:(BOOL)animated {
if ([[[storedText lastObject] data] length]==0){
[storedText removeLastObject];
notes = [storedText lastObject]; //-- this will be the *new* last object after removal
}
[self.tableView reloadData];
}
but I have no clue what you do with notes.data, so I do not know if this by itself is enough to bring it back to being consistent with your hypothesis.
Ideally before you add any item to storedText you would check that it wasn't nil or an empty string, then you wouldn't have the problem.
Otherwise, get the last item from storedText and check it (using isEqualToString: or a length check) and then remove it if it matches.
Follow what Wain said. Do this.
//total array size
int count = [storedText count];
int lastItemIndexInt = count - 1;
//get last object in array which is a string
NSString *str1 = [storedText objectAtIndex:lastItemIndexInt];
if ([str1 isEqualToString:#""] || [str1 length] < 1)
{
//string is null / blank, remove it
[storedText removeObjectAtIndex:lastItemIndexInt];
}

Load array and display based on state of uiswitch

Im trying to develop an app that displays a random truth or dare type question, however the user has the ability to turn off truths or dares in option. I have successfully managed to get the app to display a random quote from a plist file from either the truth or dare array also i have managed to program two switch buttons in the user options view controller.
My problem is how would i go about displaying only a truth or dare or both if the user has turned on of the uiswitchs off?
- (IBAction)button:(id)sender
{
if (!self.plistArray)
{
NSString *path = [[NSBundle mainBundle] pathForResource:
#"data" ofType:#"plist"];
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
if ([[defaults objectForKey:#"truthonoff"] isEqualToString:#"YES"])
{
NSDictionary *plistDict = [[NSDictionary alloc] initWithContentsOfFile:path];
NSArray *plistArray1 = plistDict[#"truth"];
}
if ([[defaults objectForKey:#"dareonoff"] isEqualToString:#"YES"])
{
NSDictionary *plistDict2 = [[NSDictionary alloc] initWithContentsOfFile:path];
NSArray *plistArray2 = plistDict2[#"dare"];
}
self.plistArray = [[plistArray1 arrayByAddingObjectsFromArray:plistArray2] mutableCopy];
}
NSLog(#"%#", plistArray);
//check to see if array is empty and display message
if ([plistArray count] == 0)
{
self.text.text = #"array empty";
}
else
{
//display random quote from array
int randV = arc4random() % self.plistArray.count;
self.text.text = self.plistArray[randV];
[self.plistArray removeObjectAtIndex:randV];
}
}
That is my attempt however it will not run and i have the feeling it wont ddo the job i need.
Basicly i need it to display only truth if the user has selected that to true or only dare if that is selected or both if both are set to true.
EDIT
sorry the problem with the above code is the plist isnt being loaded and it is scipping straight to if array ==0 {
How do i ensure it loads the array and then checks which arrays to load from the plist file?
Any help is greatly appreciated
This is the code before i tried to add if statements. Im so confussed how best to do this
- (IBAction)shownext:(id)sender {
//load array and check then cycle through this untill array is empty. Array will add two arrays from plist file.
if (!self.plistArray) {
NSString *path = [[NSBundle mainBundle] pathForResource:
#"data" ofType:#"plist"];
NSDictionary *plistDict = [[NSDictionary alloc] initWithContentsOfFile:path];
NSArray * plistArray1 = plistDict[#"truth"];
NSDictionary *plistDict2 = [[NSDictionary alloc] initWithContentsOfFile:path];
NSArray *plistArray2 = plistDict2[#"dare"];
self.plistArray = [[plistArray1 arrayByAddingObjectsFromArray:plistArray2] mutableCopy];
}
NSLog(#"%#", plistArray);
//check to see if array is empty and display message
if ([plistArray count] == 0) {
self.text.text = #"array empty";
}
else {
//display random quote from array
int randV = arc4random() % self.plistArray.count;
self.text.text = self.plistArray[randV];
[self.plistArray removeObjectAtIndex:randV];
}
}
First, if you have a switch for truth and one for dare I hope you have something in place to deal with when the user turns both switches off and doesn't understand why they get nothing (trust me it will happen).
For the rest I'm not sure exactly how you app works but I will take a guess. I'm thinking you have a utility style app with the main UI in one view and then an info button that flips to a second view where the switches are. I'm also guessing that there is a button in the main view that retrieves a truth or dare string. My final assumption, based on your code above, is that when the user changes the state of a switch that writes a user default that you've use a #define to keep out spelling mistakes.
When your view loads you should load both arrays in case the user changes their mind in the middle of using your app and turns on both options or changes from one to the other. Depending on how many entries you have in each of those arrays you might consider creating a combined array as well to simplify things.
When the button is pressed you should then look at the defaults and see if you need to look at both arrays or just one (the below is pseudo code)
if(truth && dare) {
// if you have a combined array pick a random element from it.
// otherwise first randomly pick one of the arrays to pick from.
}
else if (truth) {
// get a random element from the truth array
}
else {
// get a random element from the dare array
}
Also, your current checks of the switch values will always return no unless you are doing extra work in the switch view controller. You should be using [defaults setBool:<UISwitch.isOn> forKey:<#definedKeyHere>] and [defaults boolForKey:<#definedKeyHere>].
It would really help to know what part isn't working. For one thing, it might help to store your flags as NSNumber objects instead of strings (could your string comparison be failing?). Then you could do something like:
if ([[defaults objectForKey:#"truthonoff"] boolValue])
Use a literal to add the actual NSNumber - #YES or #NO.
Consider changing your logic to something like:
VERIFY CODE - doing this freehand:
if (!self.plistArray)
{
self.plistArray = [NSMutableArray array];
NSString *path = [[NSBundle mainBundle] pathForResource:
#"data" ofType:#"plist"];
// why are you loading this twice?
NSDictionary *plistDict = [[NSDictionary alloc] initWithContentsOfFile:path];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([[defaults valueForKey:#"truthonoff"] boolValue])
{
[self.plistArray addObject:plistDict[#"truth"]];
}
if ([[defaults valueForKey:#"dareonoff"] boolValue])
{
[self.plistArray addObject:plistDict[#"dare"]];
}
}
I am assuming that your code to load the Plists is working. Verify all your keys match what's in the Plist. Set a breakpoint and verify.
Calling a method on a nil object is a no-op in Objective C. So, it'll happily ignore calls to nil objects without telling you. Verify you have what you think you have.
Also, here:
//display random quote from array
int randV = arc4random() % self.plistArray.count;
self.text.text = self.plistArray[randV];
[self.plistArray removeObjectAtIndex:randV];
Consider using arc4random_uniform(self.plistArray.count) as it avoids modulo bias in the generator.
Now, this just gives you say 0 or 1 if you have two elements. Are you sure the two dictionary keys, "truth" and "dare" actually point to arrays?
Ok, everything working to this point. Now, you have an array of ARRAYS! So you need to randomly pick a question array, and THEN randomly pick a question.
Something like:
//get random array
int randArrayIndex = arc4random_uniform(self.plistArray.count);
NSArray* questionArray = self.plistArray[randArrayIndex];
//get random question
int randQuestionIndex = arc4random_uniform([questionArray count]);
NSString* randomQuestion = questionArray[randQuestionIndex];
self.text.text = randomQuestion;
// remove question
[questionArray removeObjectAtIndex:randQuestionIndex];
Something like that anyway. Of course, assuming you are storing NSStrings in those Plist arrays.

How can I access one value among some values

{
"id"=12
"genres_en" = "thriller,movies,action";
}
{
"id"=13
"genres_en" = "thriller,horror";
}
Hi everyone ,
I have one json like this..I mean i have one content and all movie has their genre ..And i need to do one categorization ..For example I need to check which genre of movie is horror..Or which one is thriller..I m getting all value like this:
--> "horror,movies"
But how can i do the controllation to check whether the genre of this movie includes horror or not..??what is your suggesstion?
Thank you
You could use componentsSeparatedByString
NSDictionary *dic = PARSE The JSON;
NSString *values = [dic objectForKey:"genres_en"];
NSString *firstValue = [[values componentsSeparatedByString:","] objectAtIndex:0];
I don't have Xcode nearby, so the following code may contain an error(or two :) ).
Try it like that:
NSDictionary *yourDict = //your parsed json
NSString *genres = [yourDict objectForKey:#"genres_en"];
if ([genres rangeOfString:#"horror"].location != NSNotFound) {
return YES;
} else {
return NO;
}
Hope it helps
for(int j=0;j< GenresArray.count; j++)
{
NSString *value=[[genre componentsSeparatedByString: #","]objectAtIndex:j];
if([value isEqualToString:#"movies"])
{
[genreMovies addObject:value];
}
}
Thank you for your help guys ..Now i have my result:)
You can try to check if the string contains the substring you want . Like this:
NSString *typesString = [dic objectForKey:"genres_en"];
NSRange range = [typesString rangeOfString:#"horror"];
if(range.location != NSNotFound)
{
//it contains the substring "horror"
}
Or , the better way would be to get the array of types.
NSArray *types = [[typesString componentsSeparatedByString:","];
Now you can store this array for each entry and whenever you want to check if it belongs to a certain gender , just loop through the types array ( of each entry ) and compare the strings.
Hope this helps.
Cheers!

Resources