iOS - Storing multiple values in one variable - ios

I am creating 5 integer variables to store 5 different values in Objective C. For ex: intA, intB etc
Below is just sample code:
For example:
for (Desframe *obj in [myval allValues])
{
if (obj.A>10.0) {
myLabel.text = #"A";
intA = intA++;
}
else if (obj.B>10.0) {
myLabel1.text = #"B";
intB = intB++;
}
else if (obj.C>10.0) {
myLabe2.text = #"C";
intC = intC++;
}
else if (obj.D>10.0) {
myLabe3.text = #"D";
intD = intD++;
}
else if (obj.E>10.0) {
myLabe4.text = #"E";
intE = intE++;
}
}
In future, I may need to add 2 more variables.
I would like to know how to avoid creating 5 different integer variables but have 5 different values stored in one variable. Should I use array?
(or) how to handle this code professionally?
But I want this variable to be accessed globally in the same class (.m) file.
Kindly share your suggestion and guidance.

Yes, you can use an NSMutableArray for this. However, Objective-C NSArrays are a little strange since they can only contain objects. You'll have to "box" the entries as NSNumber objects:
NSMutableArray *numbers = #[#(1), #(2), #(3), #(4), #(5)];
And then you can fetch an item from the array:
NSNumber *aNumber = numbers[0];
But NSNumber Objects are immutable.
You might want to use a C-style array:
UInt64 numbers[] = [1, 2, 3, 4, 5];
Then you could say
numbers[0]++;
But with a statically allocated C-style array you can't add elements to the array at runtime.

You could use NSMutableDictionary with keys being your A - E here and integers as values.
That way, for instance, to add values (5 now and potentially more in the future) you would write:
[dict setObject:#123 forKey:#"A"];
To retrieve them:
[dict objectForKey:#"A"];

You could define your own struct.
struct MyStruct {
int a;
int b;
int c;
int d;
}
And use this new type in your class
#implementation MyClass {
MyStruct example;
// In your function
for (Desframe *obj in [myval allValues])
{
if (obj.A>10.0) {
myLabel.text = #"A";
example.a += 1;
}
else if (obj.B>10.0) {
myLabel1.text = #"B";
example.b += 1;
}
// And so on ...
}
}
}

Related

NSMutableArray has 6 (some example) items. 3 IDs and 3 arrays (info about those 3 IDs). How to remove those numbers (IDs)

(
65,
61,
82,
{
FOMobilePhone = "";
FOName = "XXX";
FOTitle = "PRODUCTION DIRECTOR";
FOWorkEMail = "AAA#example.com";
FOWorkPhone = "+12345";
Id = 65;
},
{
FOMobilePhone = "";
FOName = "BBB";
FOTitle = "GSC EGYPT OPERATION LEAD";
FOWorkEMail = "BBB#example.com";
FOWorkPhone = "+12345";
Id = 61;
},
{
FOMobilePhone = "";
FOName = "CCC";
FOTitle = "PRODUCTION, DIRECTOR";
FOWorkEMail = "CCC#example.com";
FOWorkPhone = "+12345";
Id = 82;
}
}
First 3 items are IDs and remaining 3 arrays are their respective data. NSMutableArray has 6 (some example) items. 3 IDs and 3 arrays (info about those 3 IDs). How to remove those numbers (IDs)?
Let someArray = NSMUtableArray you are getting from server.
NSMutableIndexSet *discardedItems = [NSMutableIndexSet indexSet];
NSUInteger index = 0;
for (id someObject in someArray) {
if ([someObject isKindOfClass:[NSString class]]){
[discardedItems addIndex:index];
}
index++;
}
[someArray removeObjectsAtIndexes:discardedItems];
Finally , someArray will have only the data without IDs.
try this:
if NSMutableArray name is arr1 then you can do like this to remove three ID:
[arr1 removeObject:0];
[arr1 removeObject:1];
[arr1 removeObject:2];
You don't say what language you're using. If it's Swift, you could write a filter command that would get rid of the Int items.
If it's Objective-C you don't have that option, but you could do it various other ways. I'd suggest using filterUsingPredicate (if it's a mutable array) or filteredArrayUsingPredicate if it's an immutable array.

Objective C Message Argument Array Parsing (AJNMessageArgument)

I'm working with AllJoyn on iOS using objective C. I'm having trouble parsing an ALLJOYN_ARRAY type in objective C. The problem is that the MsgArg type (C++) is abstracted through the AJNMessagArgument type (objective c). The sample code for parsing an array signature of "a{iv}" in c++ is as follows:
MsgArg *entries;
size_t num;
arg.Get("a{iv}", &num, &entries);
for (size_t i = 0; i > num; ++i) {
char *str1;
char *str2;
uint32_t key;
status = entries[i].Get("{is}", &key, &str1);
if (status == ER_BUS_SIGNATURE_MISMATCH) {
status = entries[i].Get("{i(ss)}", &key, &str1, &str2);
}
}
Now in objective c, the msgarg is the handle of the AJNMessageArgument type. I've tried the following to try getting this to work with no avail:
AJNMessageArgument *strings = [AJNMessageArgument new];
size_t numVals;
QStatus status = [supportedLangsArg value: #"as", &numVals, strings.handle];
if(status != ER_OK){
NSLog(#"ERROR: Could not supported languages from the message argument");
}
This returns ER_OK, but I can't see any data in the handle via the debugger like I can with valid AJNMessageArguments.
Passing in &strings.handle throws a compile error "Address of property expression required".
I've tried quite a few other things, but none make much sense compared to the one above.
Please help me! I need an example of how to parse an "as" signature in objc. I haven't been able to find any docs for this.
Thanks for any help!
Ok, short story is this can't be done without adding custom code to the AJNMessageArgument Class. This is because in this scenario, the "value" method will return a pointer to an array of MsgArg types. Objective C cannot interact with MsgArg - Which is the whole reason they created the AJNMessageArgument wrapper for Objective C.
Here is how it is done:
Add this static method to your AJNMessageArgument.mm class:
+ (NSArray*)getAJNMessageArgumentArrayFromMsgArgArray:(void*)arg : (int)size
{
NSMutableArray * toReturn = [NSMutableArray new];
MsgArg *msgArray = (MsgArg*) arg;
for (int i = 0; i < size; ++i)
{
void * msarg = malloc(sizeof(MsgArg));
MsgArg arg = msgArray[i];
memcpy(msarg, &msgArray[i], sizeof(MsgArg));
AJNMessageArgument *toAdd = [[AJNMessageArgument alloc] initWithHandle:msarg];
[toReturn addObject:toAdd];
}
return [toReturn copy];
}
Don't forget to add the method definition to the AJNMessageArgument.h file:
+ (NSMutableArray*)getAJNMessageArgumentArrayFromMsgArgArray:(void*)arg : (int)size
So now, in our objective C code, we can parse the AJNMessageArgument with signature "as" - but we can't cast it to the MsgArg type yet because we can't access that structure outside of objc++ - so we will use a (void *).
+ (NSArray*)getSupportedLangsFromMessageArgument:(AJNMessageArgument*)supportedLangsArg
{
void *strings; //void * to keep track of MsgArg array data.
size_t numVals;
QStatus status = [supportedLangsArg value: #"as", &numVals, &strings];
if(status != ER_OK){
NSLog(#"ERROR: Could not supported languages from the message argument");
}
NSMutableArray *arrayOfMsgArgs = [AJNMessageArgument getAJNMessageArgumentArrayFromMsgArgArray:strings :numVals];
//Now loop through the resulting AJNMessageArguments of type ALLJOYN_STRING - and parse out the string.
NSMutableArray *arrayOfStrings = [NSMutableArray new];
for (AJNMessageArgument *arg in arrayOfMsgArgs) {
NSString* msgArgValue = [AboutUtil getStringFromMessageArgument:arg];
[arrayOfStrings addObject:msgArgValue];
}
return [arrayOfStrings copy];
}
Now we have an NSArray of NSStrings. Whew.
In case you were wanting to see the code to get the NSString out of the AJNMessageArguments that are in the array, here is that method:
+ (NSString*)getStringFromMessageArgument:(AJNMessageArgument*)msgarg
{
char *charStr;
QStatus status = [msgarg value:#"s", &charStr];
if (status != ER_OK) {
NSLog(#"Error");
}
NSString *str = [NSString stringWithFormat:#"%s", charStr];
return str;
}
Happy AllJoyn-ing.

It is possible to use array reduce concept from swift in objective c?

I have this lines of code in Swift:
let graphPoints:[Int] = [4, 2, 6, 4, 5, 8, 3]
let average = graphPoints.reduce(0, combine: +) / graphPoints.count
It is possible to "translate" this lines of code in objective c code?
It's not very clear for me how reduce combine concept works. I read about it but still is unclear.
I took the code from this tutorial: http://www.raywenderlich.com/90693/modern-core-graphics-with-swift-part-2
Please help. Thanks.
let's say you have some NSNumbers stored in an NSArray you can use this KVC collection operator:
NSArray *someNumbers = #[#0, #1.1, #2, #3.4, #5, #6.7];
NSNumber *average = [someNumbers valueForKeyPath:#"#avg.self"];
For Objective-C, I would add the Higher-Order-Functions to this list of answers: https://github.com/fanpyi/Higher-Order-Functions
#import <Foundation/Foundation.h>
typedef id (^ReduceBlock)(id accumulator,id item);
#interface NSArray (HigherOrderFunctions)
-(id)reduce:(id)initial combine:(ReduceBlock)combine;
#end
#import "NSArray+HigherOrderFunctions.h"
#implementation NSArray (HigherOrderFunctions)
-(id)reduce:(id)initial combine:(ReduceBlock)combine{
id accumulator = initial;
for (id item in self) {
accumulator = combine(accumulator, item);
}
return accumulator;
}
#end
example:
NSArray *numbers = #[#5,#7,#3,#8];
NSNumber *sum = [numbers reduce:#0 combine:^id(id accumulator, id item) {
return #([item intValue] + [accumulator intValue]);
}];
NSNumber *multiplier = [numbers reduce:#1 combine:^id(id accumulator, id item) {
return #([item intValue] * [accumulator intValue]);
}];
NSLog(#"sum=%#,multiplier=%#",sum,multiplier);
The reduce function is not standard in Objective-C. You can implement it as an extension of NSArray though.
In your case, you have an array of Int in Swift. You cannot have that in Objective-C, you need an array of NSNumber.
Here is an implementation of reduce that should work in your case:
#implementation NSArray (Helpers)
- (NSInteger)reduceInt:(NSInteger)initial combine:(NSInteger (^)(NSInteger acum, NSInteger element))block {
if (!self) {
return initial;
}
NSInteger acum = initial;
for (id element in self) {
if ([element isKindOfClass:[NSNumber class]]) {
acum = block(acum, [(NSNumber *)element integerValue]);
}
}
return acum;
}
#end
You can use it then with your array, something like this:
NSArray *a = #[#1, #2, #3];
NSInteger result = [a reduceInt:0 combine:^NSInteger(NSInteger acum, NSInteger element) {
return acum + element;
}];
how to translate reduce to ObjC (or better to say how to solve your "average problem" in Objective C) was perfectly answered by André Slotta. the swift reduce is much more than that. I will try to answer the second part of your question, how the concept works in swift
func reduce<T>(initial: T, #noescape combine: (T, Self.Generator.Element) throws -> T) rethrows -> T
Return the result
of repeatedly calling combine with an accumulated value initialized to
initial and each element of self, in turn, i.e. return
combine(combine(...combine(combine(initial, self[0]),
self[1]),...self[count-2]), self[count-1]).
let arr: Array<Int> = [1,2,3,4,5]
let sum = arr.reduce(0) { (sum, i) -> Int in
return sum + i
}
print(sum) // 15
// this is an quasi equivalent of
var sum1 = 0 // ..... reduce(0)....
arr.forEach { (elementValue) -> Void in
sum1 = sum1 + elementValue // ...{ return sum + i }
}
print(sum1) // 15 reduce function will return accumulated inital value
// reduce is part of SequenceType protocol, that is why
let arr1 = ["H","e","l","l","o"," ","w","o","r","l","d"]
let str = arr1.reduce("") { (str, s) -> String in
str + s
}
// works the same way
print(str) // "Hello world"
// let have a litle bit more complex example, to see how powerful, useful and easy to use reduce can be
let dict = arr1.reduce([:]) { (var dict, s) -> Dictionary<Int,String> in
let i = dict.count
dict.updateValue(s, forKey: i+1)
return dict
}
print(dict) // [11: "d", 10: "l", 2: "e", 4: "l", 9: "r", 5: "o", 6: " ", 7: "w", 3: "l", 1: "H", 8: "o"]
Write an NSArray extension
- (NSInteger)reduceStart:(NSInteger)start combine:(NSInteger(^)(NSInteger x, NSInteger y))combine {
for (NSNumber* n in self) {
if ([n isKindOfClass:[NSNumber class]]) {
start = combine (start, n.integerValue);
}
}
return start;
}
fix all mistakes that I made, and that's it. Just less flexible than Swift.

CGRectFromString() for general structs

#"{0, 1.0, 0, 1.0}"
I wish to convert the above string to a struct like this:
struct MyVector4 {
CGFloat one;
CGFloat two;
CGFloat three;
CGFloat four;
};
typedef struct MyVector4 MyVector4;
CGRectFromString() does the same thing, only for CGRect. How can I do it for my own structs?
If there is a function for rect it means that it is not working by default.
You have to create your own function something like MyVector4FromString.
You may like to to know that you can init struct object like this also.
MyVector4 v1 = {1.1, 2.2, 3.3, 4.4};
This is a very easy C syntax. so I don't think you require to init from string.
See here : 4.7 — Structs
But if you are getting string from server or from other function than yes you have to create your function to do this. You can parse string and init 4 float value.
This link will help you to divide string in multiple part : Split a String into an Array
All the best.
It can be done in the following way:
-(MyVector4)myVector4FromString:(NSString*)string
{
NSString *str = nil;
str = [string substringWithRange:NSMakeRange(1, string.length - 1)];
NSArray *strs = [str componentsSeparatedByString:#","];
MyVector4 myVec4 = {0,0,0,0};
for (int i=0; i<4; i++)
{
CGFloat value = ((NSString*)[strs objectAtIndex:i]).floatValue;
if (i==0) { myVec4.one = value; } else
if (i==1) { myVec4.two = value; } else
if (i==2) { myVec4.three = value; } else
if (i==3) { myVec4.four = value; }
}
return myVec4;
}
This function can parse strings in format shown in your question like #"{12.0,24.034,0.98,100}"

iOS filter array of dictionary base on value and not the key

I have array with dictionaries like this:
Array: (
{
customerUS= {
DisplayName = "level";
InternalName = "Number 2";
NumberValue = 1;
},
customerCAN= {
DisplayName = "PurchaseAmount";
InternalName = "Number 1";
NumberValue = 3500;
};
}
)
I want to filter the dictionaries base on particular value and not the key. For example I want all the dictionaries with values on any key of 3500. Does any body knows how can I do this?
I'll really appreciate your help.
Try a predicate format like:
#"%# IN SELF", testValue
When you filter the array each will be run against the IN. When you pass IN a dictionary it uses the values of the dictionary.
you can also use
-keysOfEntriesPassingTest:
of NSDictionary. Just pass in a block like so:
for(NSDictionary *myDictionary in myArray){
NSSet *resultSet = [myDictionary keysOfEntriesPassingTest:^(id key, id object, BOOL *stop) {
//assuming that 3500 is an int, otherwise use appropriate condition.
if([[NSNumber numberWithInt:object] isEqual:[NSNumber numberWithInt:3500]]){
return YES;
}else{
return NO;
}
}];
if (resultSet.count>0){
//do whatever to myDictionary
}
}

Resources