Set bool property of all objects in the array - ios

I've a model class called PhotoItem. In which I have a BOOL property isSelected
#interface PhotoItem : NSObject
/*!
* Indicates whether the photo is selected or not
*/
#property (nonatomic, assign) BOOL isSelected;
#end
I've an NSMutableArray which holds the object of this particular model. What I want to do is, in a particular event I want to set the bool value of all objects in the array to true or false. I can do that by iterating over the array and set the value.
Instead of that I tried using:
[_photoItemArray makeObjectsPerformSelector:#selector(setIsSelected:) withObject:[NSNumber numberWithBool:true]];
But I know it won't work and it didn't. Also I can't pass true or false as the param in that (since those are not object type). So for fixing this issue, I implemented a custom public method like:
/*!
* Used for setting the photo selection status
* #param selection : Indicates the selection status
*/
- (void)setItemSelection:(NSNumber *)selection
{
_isSelected = [selection boolValue];
}
And calling it like:
[_photoItemArray makeObjectsPerformSelector:#selector(setItemSelection:) withObject:[NSNumber numberWithBool:true]];
It worked perfectly. But my question is, Is there any better way to achieve this without implementing a custom public method ?

Is there any better way to achieve this without implementing a custom public method?
This sounds like you are asking for opinion, so here is mine: Keep it simple.
for (PhotoItem *item in _photoItemArray)
item.isSelected = YES;
Why obfuscate a simple thing with detours through obscure methods when you can write code that anybody will immediately understand?
Another way of doing the same thing would be:
[_photoItemArray setValue:#YES forKey:#"isSelected"];
This does not need the custom additional setter method because KVC does the unboxing for you.
But again I would vote against using such constructs. I think they are distracting from the simple meaning and confusing developers that come after you.

Related

containsObject is returning NO after the app is restarted

I have a UITabelView displaying a list of items(returned from the server), users will be able to select any item and add it to his own section.
Upon selecting an item, I am retrieving the selected item details and saving it to a pList file, the list will then be displaying a small icon informing the user that the item is added to his section. User will be able to remove it from his section by tapping the icon again.
To know if the item is already in his section, i am using
[self.myItemsArray containsObject:item]
Everything is working perfect if the user don't exit the application. The issue is occurring once the app is restarted. When I retrieve the tableview list from the database or from server, all the items will not be shown as on my list and [self.myItemsArray containsObject:item] will return NO for the previous added items.
I was searching for an alternative way, by creating an NSArray of my items id's and will then check if the new array will contains the item id to display the icon.
the new issue is that the id is returned as double from the server and stored as it is. The application is crashing when creating the array:
[self.myItemsArray valueForKey:#"Id"]
myItemsArray is an array of items(item is an NSDictionary containing all the details)
So i am desperate now,could anyone help me by resolving any of the above issues?
I prefer the first one, since containsObject will be more simple, but I don't mind to solve it with the second choice if the first will not work.
You'll need to make sure you have a good isEqual: method defined for your custom class, since that's what NSArray uses to determine containment: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/#//apple_ref/occ/instm/NSArray/containsObject:
Let's say this class has something like a 'key' or 'id' value that is unique for each instance of the class (which in your case is a double type). This will not always be the case, of course; it's often an aggregate of individual properties/ivars that constitutes a unique 'key', but for the purposes of this discussion let's say that such a field exists. Your code might look something like this (all in the .m):
static double const EPSILON = .000000001; // You'll need to be the judge of how "close" values can be to each other but still be distinct
#interface MyObjectClass: NSObject
#property (nonatomic, readonly) double uniqueKey;
#end
#implementation MyObjectClass
// ...
- (BOOL)isEqual:(id)object
{
if (self == object) { return YES; }
if (!object isKindOfClass:[MyObjectClass class]]) { return NO; }
MyObjectClass *myObject = (MyObjectClass *)object;
if (abs(self.uniqueKey - myObject.uniqueKey) < EPSILON) { return YES; }
return NO;
}
//...
#end
Note that you should NOT check for direct equality between two float or double values; see How dangerous is it to compare floating point values? for a good discussion about the pitfalls of working with floating point and double precision values.

Check for NSString

I am looking for robust, iron clad code to check if an NSString property has a valid string in it as opposed to being empty, null, nil etc.
The property is:
#property (nonatomic, retain) NSString * name;
I have been using the following?
if (self.item.name==nil) {
//do something
}
else {
//do something else
}
However, not sure this is working right. (Full logic is far more complicated so not trivial to trace if logic working right every time.)
I have also tried self.item.length>0, however, it says length is not a valid property.
Thanks for any suggestions.
EDIT:
Item is an instance of an object such as a shirt. It corresponds to an entity in core data. name is a property of the object. I have changed it from text to name to avoid confusion with text as a defined term.
I suppose self.item is a UILabel or UITextField. The property that you have defined is named text. So you are working with the wrong variable. You can either check self.item.text.length > 0 or self.text.length > 0. Whichever is your actual property.

Logic/iOS - Override certain values depending on if user entered or not

I am looking for a way to properly perform the following.
I have multiple values in an object that are given default values (some a physical number, other calculated). The user selects a few parameters and the rest are populated for them.
After the values are populated the user can then overwrite any value of their choosing which then may cause values to be re-calculated. If the value is a calculated value that the user has entered I don't want it to change.
Take for example the following:
Class values {
NSString *userSelected:
double value1;
double value2;
double value3;
double calc1;
double calc2;
double calc3;
}
The user then selects (From a picker) values.userSelected. Upon selection, values 1 - 3 and calc 1 - 3 are assigned/calculated to their "default values".
The user can then go in and edit say value1. Once changed calc1-3 will re-calculate if they use value1. Now the user can also overwrite the calc values. So if the user overrides calc1 and then changes value1 I DO NOT want calc1 to change again since it was changed by the user.
One way I thought to do this was duplicate each value with a default and if the non-default is set return that instead:
ie
Class values {
double value1;
double defaultValue1; ... etc.
}
Hence if the non-default value is set then use that, else use the default value. This just seems like an inefficient way of doing it. Does anyone have a better thought process on how to do this. My class is around 20 properties so I'd rather not require 2 properties per variable. I am programming in iOS but this is more a methodology question vs a specific piece of code. If anything is unclear please feel free to ask.
Thanks,
DMan
One thing that could do what you're looking for: accessor overrides. Basically, you declare in your class a bunch of values using #property syntax, then do some stuff under the hood in the implementation, including overriding the getter/setters. For example:
//in MyClass.h
#interface MyClass : NSObject
#property (nonatomic, assign) double value1;
#property (nonatomic, assign) double calc1;
#end
//in MyClass.m
#implementation MyClass {
BOOL _calc1Changed;
}
//you should default that flag to NO, so...
- (id)init {
_calc1Changed = NO;
}
- (void)setValue1:(double)newValue1 {
if (!_calc1Changed) [self calculateCalc1]; //define this calculation also in this file
value1 = newValue1; //value1 is the synthesized ivar for the property you declared
}
And of course, somewhere you'll need to call _calc1Changed = YES; whenever the user sets calc1 manually, possibly in a similarly constructed override. Basically, the result is that every time you call myClassInstance.value1 = something or [myClassInstance setValue1:something] these checks will be performed and extra functionality can be performed to validate/respond to inputs.

Non-Object Attribute in Core Data, transient properties

Feel lost after reading this section: A Non-Object Attribute
According to the Basic-Approach also contained in above link, I should have 2 attributes in my custom-code when handling "transient properties":
1st attribute, for the actually-wanted (un-supported) custom type => transient attribute
2nd attribute, for shadow-representation (concrete supported) type => persistent attribute
......
My reading was very enjoyable, until reached "A Non-Object Attribute" section, which puzzle me deeply, as quoted below:
...When you implement the entity’s custom class, you typically add an instance variable for the attribute. ...
《 OK, I can follow this...make an iVar is no big deal》
If you use an instance variable to hold an attribute, you must also implement primitive get and set accessors
《 OK, I know how to do primitive-accessor. why need them? because internal-optimized-storage inside MO can be efficiently used, I guess.》
#interface MyManagedObject : NSManagedObject
{
 NSRect myBounds; // I assume this suppose to be the **transient attribute**
}
#property (nonatomic, assign) NSRect bounds; // I assume this is the **persistent attribute**
#property (nonatomic, assign) NSRect primitiveBounds; // because complier forces me to implement below primitive-accessors ?
#end
- (NSRect)primitiveBounds
{
return myBounds; // accessing iVAR storage for **transient attribute**? I hope so
}
- (void)setPrimitiveBounds:(NSRect)aRect
myBounds = aRect; // accessing iVAR storage for **transient attribute**? I hope so
}
From here down below, I have... too many ???????????? unsolved
- (NSRect)bounds
{
[self willAccessValueForKey:#"bounds"]; //KVO notice of access **persistent attribute**, I guess
NSRect aRect = bounds; //will this invoke primitive-Getter ???
[self didAccessValueForKey:#"bounds"];
if (aRect.size.width == 0) //bounds has not yet been unarchived, Apple explained
 {
NSString *boundsAsString = [self boundsAsString]; // unarchiving pseudo method, I guess
if (boundsAsString != nil) //if that value is not nil, transform it into the appropriate type and cache it...Apple explained.
{
bounds = NSRectFromString(boundsAsString); //will this invoke primitive-Setter???
}
}
return bounds;
}
I put my final question list here:
1, do I STILL need to have 2 attributes to handle NON-Object-Attribute, transient attribute and persistent attribute?
2, how can iVar "myBounds" be represented/connected with "#property bounds"? Is this "#property bounds" the modeled-property in a MOM?
3, what is the purpose of implementation of primitive-accessor here? for enforcing me write KVO (will...did...) methods pair? for transferring values (in and out) between iVar "myBounds"and "#property bounds"?
4, in this line of code
bounds = NSRectFromString(boundsAsString); //will this invoke primitive-Setter???
is primitive-Setter called OR public/standard-Setter gets called? Why?
In iOS, there are the very convenient NSStringFromCGRect and CGRectFromNSString functions. Why not just use those and store a string?
Your questions:
Yes, you need the 2 attributes, as explained in the documentation.
Yes, this is based on the managed object model. The primitiveX name for x is generated / interpreted automatically.
You need the primitive accessor methods here to make it KVC - which is not the case with primitives.

I need to build a HashMap like, Map<Set, Set>. Is it possible?

My usecase here is, I need to search for a string within a set of strings(say synonyms). If I find the relevant search-word within the set of strings, then I will display the set of values associated with that set of strings. I am currently thinking of implementing it as a Map, but not sure, if that's even possible.
I am confused about the best data-structure that can be used in this scenario?
Thanks for the help.
EDIT
Replaced Array with Set as it made more sense
Scenario:
Set-1 = {jug,jar,bottle,cup}
Set-2 = {"Store water", "Store Juice", "Store Coffee"}
For any input I receive from either jug,jar,bottle,cup, I should return the properties associated with it from Set-2. In simple words, I need to return whole of Set-2 when any word from Set-1 matches. Hopefully, this will make my question clear.
you can subclass NSObject for that kind of behaviour.
#interface Synonyms : NSObject
#property NSArray *strings;
#property NSArray *values;
-(NSArray *)searchForWord:(NSString *)searchWord;
#end
#implementation Synonyms
-(NSArray *)searchForWord:(NSString *)searchWord{
BOOL found=NO;
//add code to search for that search term in strings array
if(found)
return self.values;
else
return nil;
}
#end
so, first create all these synonyms instances and store them in NSArray.
Assign strings and values array to each instance.
When user enters search-word, call searchForWord function for each element of array.
If found ,it returns not nil object.else no synonym.
PART 2:
If you are looking for below kind of behaviour, example below
Dictionary myDic;
myDic.Add("car", "automobile");
myDic.Add("car", "autovehicle");
myDic.Add("car", "vehicle");
myDic.Add("bike", "vehicle");
myDic.ListOSyns("car") // should return {"automobile","autovehicle","vehicle" ± "car"}
// but "bike" should NOT be among the words returned
Then you can use NSDictionary,
NSDictionary *dictionary =#{#"car":#[#"automobile",#"autovehicle",#"vehicle"],#"bike":#[#"vehicle"]};
NSArray *values =[dictionary objectForKey:#"search-term"];
if(values==nil)
//no result
else
return values;

Resources