I have declared array in SomeClass.h It's a global variable isn't it?
#property (nonnull, nonatomic, retain) NSMutableArray *additional_tabs;
Below I declared 2 function where I use this array.
- (id _Nullable)initFromJSON:(NSDictionary *_Nullable)dictionary;
- (void)moreTabs:(NSMutableArray *_Nullable)a;
Below is if-statement I used inside initFromJSON function.
if ([Tools isNonullValueForKey:[dictionary valueForKey:#"additional_tabs"]]) {
_additional_tabs = [NSMutableArray new]; //really I need them?
_additional_tabs = [dictionary valueForKey:#"additional_tabs"];
NSLog(#"additionalTabCount (initJSON) = %lu", [_additional_tabs count]);
for (int i = 0; i < [_additional_tabs count]; i++) {
if ([Tools isNonullValueForKey:[_additional_tabs valueForKey:#"_id"]]) {
_additional_tab_id = [[_additional_tabs valueForKey:#"_id"] objectAtIndex:i];
}
if ([Tools isNonullValueForKey:[_additional_tabs valueForKey:#"names"]]) {
NSDictionary *dic = [[_additional_tabs valueForKey:#"names"] objectAtIndex:i];
_en_additional_tab_name = [dic valueForKey:#"en"];
_pl_additional_tab_name = [dic valueForKey:#"pl"];
}
if ([Tools isNonullValueForKey:[_additional_tabs valueForKey:#"url"]]) {
_additional_tab_url = [[_additional_tabs valueForKey:#"url"] objectAtIndex:i];
}
NSLog(#"%# %d %# %# %# %#", #"pos", i, #"id: ", _additional_tab_id, #"url: ", _additional_tab_url);
}
}
And this [_additional_tabs count] have 17.
But in function moreTabs:
NSLog(#"additional tabs count: %lu",[_additional_tabs count]);
for (int i = 1; i < [_additional_tabs count]; i++) {
[a addObject:[[VCTab alloc] initWithIdAndTypeAndUrl:[[_additional_tabs valueForKey:#"_id"] objectAtIndex:i] :VCTabAdditional :[[_additional_tabs valueForKey:#"url"] objectAtIndex:i]]];
}
}
return [_additional_tabs count] with nil... look like is different array or cleared?
I would be very grateful for your help :)
All the best
Related
How would you count this array?
NSArray *sortThisArray = #[#{#"numbers":#[#"One",#"Two"]},
#{#"numbers":#[#"Two",#"One"]},
#{#"numbers":#[#"One",#"Two",#"Three"]},
#{#"numbers":#[#"One",#"Two",#"Three"]},
#{#"numbers":#[#"One",#"Two",#"Three",#"Four"]},
];
The desired result would then be:
NSArray *sortedArray = #[#{#"numbers":#[#"One",#"Two"],
#"occures":#(2)},
#{#"numbers":#[#"One",#"Two",#"Three"],
#"occures":#(2)},
#{#"numbers":#[#"One",#"Two",#"Three",#"Four"],
#"occures":#(1)},
];
I've tried using NSCountedSet and countForObject, but the results are inaccurate. It seems to only count the arrays that are exactly the same. In other words, the array with #[#"Two",#"One"] gets ignored because its not 100% equal to #[#"One",#"Two"], even though they have the same objects and same count.
This should work. You have to have a consistent way to compare your arrays (either sorting like in this example or by moving the NSArray to NSSet).
NSMutableDictionary<NSArray<NSString *> *, NSNumber *> *valueCount = [NSMutableDictionary dictionary];
for (NSDictionary<NSString *, NSArray<NSString *> *> *value in sortThisArray) {
NSArray<NSString *> *numberStrings = [value[#"numbers"] sortedArrayUsingSelector:#selector(compare:)];
valueCount[numberStrings] = #(valueCount[numberStrings].integerValue + 1);
}
NSMutableArray *sortedArray = [NSMutableArray arrayWithCapacity:valueCount.count];
for (NSArray<NSString *> *key in valueCount) {
[sortedArray addObject:#{#"numbers": key, #"occures": valueCount[key]}];
}
May be something like this:
NSMutableArray *mArray = [NSMutableArray arrayWithArray:sortThisArray];
NSMutableArray *result = [[NSMutableArray alloc] init];
while ([mArray count]) {
NSDictionary *obj = [mArray firstObject];
int count = 1;
for (int i=1; i<[mArray count]; i++) {
NSDictionary *sObj = [mArray objectAtIndex:i];
if ([[sObj objectForKey:#"numbers"] count] == [[obj objectForKey:#"numbers"] count]) {
BOOL increase = YES;
for (int j=0; j<[[obj objectForKey:#"numbers"] count]; j++) {
if (![[sObj objectForKey:#"numbers"] containsObject:[[obj objectForKey:#"numbers"] objectAtIndex:j]]) {
increase = NO;
}
}
if (increase) {
count++;
[mArray removeObjectAtIndex:i];
}
}
}
[mArray removeObjectAtIndex:0];
[result addObject:#{#"numbers":obj, #"occurrs":[NSNumber numberWithInteger:count]}];
}
*Code is not tested
I am sorting an array.
There are three types of elements in the array.
1. featured
2. organic and
3. claimed.
Among them, I want to sort only organic elements and keep the featured and claimed elements at their own index.
Below is my code in which, I am extracting the claimed and featured indices in a dictionary as key being the index and value is the array element.
//Initialization
NSMutableArray *sortedArray = nil;
NSMutableDictionary *tempFeaturedDictionary = [[NSMutableDictionary alloc]init];
NSMutableDictionary *tempClaimedDictionary = [[NSMutableDictionary alloc]init];
NSMutableArray *tempOrganicArray = [[NSMutableArray alloc]init];
for (int i = 0; i < array.count; i++) {
DRListing *isFeaturedObj = (DRListing*)[array objectAtIndex:i];
if (isFeaturedObj.featured) {
[tempFeaturedDictionary setObject:isFeaturedObj forKey:[#(i)stringValue]];
}else if (isFeaturedObj.claimed)
{
[tempClaimedDictionary setObject:isFeaturedObj forKey:[#(i)stringValue]];
}else
[tempOrganicArray addObject:isFeaturedObj];
}
Again I am adding the claimed and featured back to their original indices after sorting as:
sortedArray = [NSMutableArray arrayWithArray:[tempOrganicArray sortedArrayUsingDescriptors:sortDescriptorsArray]];
for (int i = 0; i<sortedArray.count; i++) {
for (NSString *key in tempFeaturedDictionary) {
if ( [[#(i)stringValue] isEqualToString: key] ) {
[sortedArray insertObject:[tempFeaturedDictionary objectForKey:[#(i)stringValue]] atIndex:i];
}}
for (NSString *key in tempClaimedDictionary) {
if ([[#(i)stringValue]isEqualToString:key ]) {
[sortedArray insertObject:[tempClaimedDictionary objectForKey:[#(i)stringValue]] atIndex:i];
}
}
}
The code works good. Except there is claimed/(and)featured elements at the last index of the 'array'. Because the 'sortedArray' index remains less than the 'array.count' in this scenario.
Thanks in advance.
Update -
I receive response array of type:
[{featured1 featured2}, {organic1, organic2..}, {claimed1}, {featured11, featured12}, {organic11, organic12..}, {claimed2}, ..]
and I am allowed to sort only organic elements within this array. Featured and claimed should not loose their original index position.
I would iterate through the array, extracting the organics to sort. Then sort your organic array. Then iterate through the original array taking either the element from the original array or an element from the sorted organics array as appropriate.
NSMutableArray *organicsArray = [NSMutableArray new];
for (int i = 0; i < array.count; i++) {
DRListing *isFeaturedObj = (DRListing*)array[i];
if ((!isFeaturedObj.featured) && (!isFeaturedObj.claimed)) {
[organicsArray addObject:isFeaturedObj];
}
}
NSMutableArray *sortedOrganicsArray = [[organicsArray sortedArrayUsingDescriptors:sortDescriptorsArray] mutableCopy];
NSMutableArray *outputArray = [NSMutableArray new];
for (int i = 0; i < array.count; i++) {
DRListing *isFeaturedObj = (DRListing*)array[i];
if ((!isFeaturedObj.featured) && (!isFeaturedObj.claimed)) {
[outputArray addObject:sortedOrganicsArray[0]];
[sortedOrganicsArray removeObjectAtIndex:0];
} else {
[outputArray addObject:isFeaturedObject];
}
}
You could possibly make it a little more efficient if you reversed your sort order for the organics array since then you could say
[outputArray addObject:[sortedOrganicsArray lastObject]];
[sortedOrganicsArray removeLastObject];
But if your array isn't particularly large then the performance improvement will probably be negligible.
Maybe this is an alternative:
NSMutableArray *organics = [NSMutableArray new];
NSMutableArray *others = [NSMutableArray new];
for (DRListing *isFeaturedObj in array) {
if (isFeaturedObj.organic) {
[organics addObject:isFeaturedObj];
} else {
[others addObject:isFeaturedObj];
}
}
NSMutableArray *sorted = [NSMutableArray alloc]initWithObjects:organics,others, nil];
You can take the first 2 functions. The others are what I used for testing.
- (DRListing *)getNextObjectFromArray:(NSArray *)array WithStartingIndex:(int)index
{
for (int i=index; i<array.count; i++) {
DRListing *obj = (DRListing*)[array objectAtIndex:i];
if (!obj.featured && !obj.claimed)
{
return obj;
}
}
return nil;
}
- (void)sortArray:(NSMutableArray *)array
{
for (int pass = 0; pass<array.count-1; pass++) {
for (int i=0; i<array.count-1; i++) {
DRListing *obj = [self getNextObjectFromArray:array WithStartingIndex:i];
int foundIndex = (int)[array indexOfObject:obj];
DRListing *obj2 = [self getNextObjectFromArray:array WithStartingIndex:foundIndex+1];
int foundIndex2 = (int)[array indexOfObject:obj2];
if (obj!=nil && obj2 !=nil) {
if (obj.value >= obj2.value) {
[array exchangeObjectAtIndex:foundIndex withObjectAtIndex:foundIndex2];
}
i = foundIndex;
}
}
}
NSLog(#"Sorted Data: %#",array);
}
- (NSMutableArray *)testData
{
NSMutableArray *array = [NSMutableArray new];
for (int i=0; i<20; i++) {
DRListing *obj = [DRListing new];
obj.featured = i*i%2;
obj.claimed = i%2;
obj.value = i*3%10;
[array addObject:obj];
}
NSLog(#"Test Data: %#",array);
return array;
}
#interface DRListing : NSObject
#property (nonatomic) BOOL featured;
#property (nonatomic) BOOL claimed;
#property (nonatomic) int value;
#end
I am using REST API to fetch data. I have two methods, one for ResponceSucces and other for responceFailure. In responce failure I simply dismiss the activity indicator. Sometimes it happens that data is not retrieved but still activity indicator keeps spinning infinitely. And ResponceFailure method is not Called.
My question is can I set timeout interval to my web service, to check if response did not come, then activity indicator must be dismissed after some time for example 20/30 seconds.
Below is my code:
-(void)messagesGetSuccess:(FBListingsWebHandler*)handler response:(NSDictionary*)response
{
[MBProgressHUD hideHUDForView:self.view animated:YES];
[[FBModelManager sharedModelManager].messages removeAllObjects];
NSArray *messagesArray = [response objectForKey:#"message"];
if([[FBUserManager sharedUserManager] userType] == kUserShipper){
//extract usernames of transporters who placed bid on selected listing
NSArray *userNames;
NSMutableArray *transporterNames;
NSDictionary *biddingsDic = [[FBModelManager sharedModelManager] getModelDictionary:kModelBiddings];
if ([biddingsDic count] > 0){
userNames = [[biddingsDic allValues] valueForKey:#"userName"];
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:userNames];
NSSet *uniqueNames = [orderedSet set];
transporterNames = [[NSMutableArray alloc] initWithArray:[uniqueNames allObjects]];
}
//add transporter records in messages dictionary who have messages for selected listing
for (int i = 1; i < [messagesArray count]; i++) {
NSMutableArray *modelArray = [[NSMutableArray alloc] init];
NSDictionary *groupedMsgDic = [messagesArray objectAtIndex:i];
int count = (int)[[[groupedMsgDic allValues] objectAtIndex:0] count];
for (int j = 0; j < count; j++) {
FBMessagesModel *model = [[FBMessagesModel alloc] initWithMessageItems:[[[groupedMsgDic allValues] objectAtIndex:0] objectAtIndex:j]];
[modelArray addObject:model];
model = nil;
}
[[FBModelManager sharedModelManager].messages setObject:modelArray forKey:[[groupedMsgDic allKeys] objectAtIndex:0]];
//remove transporter usernames from array who have messages besides bid for selected listing
if([transporterNames containsObject:[[groupedMsgDic allKeys] objectAtIndex:0]]){
[transporterNames removeObject:[[groupedMsgDic allKeys] objectAtIndex:0]];
}
modelArray = nil;
}
//add transporter records in messages dictionary who placed bid but have no message for selected listing
for (int i = 0; i < [transporterNames count]; i++) {
NSString *path = [[[biddingsDic allValues] objectAtIndex:[userNames indexOfObject:[transporterNames objectAtIndex:i]]] photoPath];
int transporterId = [[[biddingsDic allValues] objectAtIndex:[userNames indexOfObject:[transporterNames objectAtIndex:i]]] userId];
NSString *objectForZeroMsgs = [NSString stringWithFormat:#"%#-%d",path,transporterId];
[[FBModelManager sharedModelManager].messages setObject:objectForZeroMsgs forKey:[transporterNames objectAtIndex:i]];
}
transporterNames = nil;
// [self tableView:self.shipperGroupedMessagesTableView_ numberOfRowsInSection:0];
[self.shipperGroupedMessagesTableView_ reloadData];
}else if([[FBUserManager sharedUserManager] userType] == kUserTransporter){
for (int i = 1; i < [messagesArray count]; i++) {
FBMessagesModel *model = [[FBMessagesModel alloc] initWithMessageItems:[messagesArray objectAtIndex:i]];
[[FBModelManager sharedModelManager].messages setObject:model forKey:[NSString stringWithFormat:#"%d",model.mailId]];
if(model.mailMessage && ![model.mailMessage isEqualToString:#""]){
[self createMessageBubble:model];
}
model = nil;
}
[self.bubbleTableView_ reloadData];
}
}
-(void)messagesGetFailure:(FBListingsWebHandler*)handler
{
[MBProgressHUD hideHUDForView:self.view animated:YES];
[[FBModelManager sharedModelManager].messages removeAllObjects];
if([[FBUserManager sharedUserManager] userType] == kUserTransporter){
[self.bubbleTableView_ reloadData];
}
else if([[FBUserManager sharedUserManager] userType] == kUserShipper){
if([[FBModelManager sharedModelManager].messages count] == 0){
NSDictionary *biddingsDic = [[FBModelManager sharedModelManager] getModelDictionary:kModelBiddings];
if ([biddingsDic count] > 0){
NSArray *userNames = [[biddingsDic allValues] valueForKey:#"userName"];
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:userNames];
NSSet *uniqueNames = [orderedSet set];
NSArray *transporterNames = [uniqueNames allObjects];
[[FBModelManager sharedModelManager].messages removeAllObjects];
for (int i = 0; i < [transporterNames count]; i++) {
NSString *path = [[[biddingsDic allValues] objectAtIndex:[userNames indexOfObject:[transporterNames objectAtIndex:i]]] photoPath];
int transporterId = [[[biddingsDic allValues] objectAtIndex:[userNames indexOfObject:[transporterNames objectAtIndex:i]]] userId];
NSString *objectForZeroMsgs = [NSString stringWithFormat:#"%#-%d",path,transporterId];
[[FBModelManager sharedModelManager].messages setObject:objectForZeroMsgs forKey:[transporterNames objectAtIndex:i]];
}
[self.shipperGroupedMessagesTableView_ reloadData];
}else{
[self addNoMessagesLabel];
}
}
[self.shipperGroupedMessagesTableView_ reloadData];
}
}
I am adding a screenshot.
I want to make 1 array that will hold all of the other arrays objects and will look like this
("052-6224754","03-6475075","02-6753231")
my code is:
-(NSMutableArray*) getRecepientsPhones
{
NSMutableArray* phones = [[NSMutableArray alloc]init];
//scroll all choosed contacts and retrieve phones to nsstring
if([recepientsFromContacts count]>0)
for (int i=0; i<[recepientsFromContacts count]; i++)
{
NSMutableArray* tempArray = [[NSMutableArray alloc]init];
if(![[[recepientsFromContacts objectAtIndex:i]objectForKey:#"CPhones"]isKindOfClass:[NSNull class]])
{
[tempArray addObject:[[recepientsFromContacts objectAtIndex:i]objectForKey:#"CPhones"]];
for(int j = 0; j<[tempArray count];j++)
{
[phones addObject:[tempArray objectAtIndex:j]];
}
}
}
//lets fetch from that contact
if([personRecepient count]>0)
{
if(![[personRecepient objectForKey:#"CellPhone"]isKindOfClass:[NSNull class]])
[phones addObject:[personRecepient objectForKey:#"CellPhone"]];
}
NSLog(#"%#",phones);
return phones;
}
[[recepientsFromContacts objectAtIndex:i]objectForKey:#"CPhones"]
is 1 or more dimension array (it is array of phone numbers per person , person can have more than 1 number)
example: ("052-6224754","03-6475075")
but my function returns
("052-6224754","03-6475075"),("02-6753231")
which is not good , what should I do to make it 1 array
("052-6224754","03-6475075","02-6753231")
You should change the line
[phones addObject:[tempArray objectAtIndex:j]];
to
[phones addObjectsFromArray:[tempArray objectAtIndex:j]];
This should result in a flattened array of phone numbers.
Then you should head over to codereview.stackexchange.com because there are several issues with your code fragment.
Edit: Here's a cleaned up version of the method:
- (NSArray *)recepientsPhoneNumbers
{
NSMutableArray* phoneNumbers = [NSMutableArray array];
for (NSDictionary *dict in _recepientsFromContacts)
{
id recipientPhoneNumbers = dict[#"CPhones"];
if (recipientPhoneNumbers != [NSNull null])
[phoneNumbers addObjectsFromArray:recipientPhoneNumbers];
}
id recipientPhoneNumbers = _personRecepient[#"CellPhone"];
if (recipientPhoneNumbers != [NSNull null])
[phoneNumbers addObjectsFromArray:recipientPhoneNumbers];
NSLog(#"%#", phoneNumbers);
return phoneNumbers;
}
I applied Cocoa coding conventions, so ivars are now prefixed with underscores.
I have an NSArray some thing like in the following format.
The group array is :
(
"Q-1-A1",
"Q-1-A9",
"Q-2-A1",
"Q-2-A5",
"Q-3-A1",
"Q-3-A8",
"Q-4-A1",
"Q-4-A4",
"Q-10-A2",
"Q-8-A2",
"Q-9-A2",
"Q-7-A1",
"Q-5-A2"
)
Now what i have to do is group the array elements some thing like this.
1 = ( "Q-1-A1","Q-1-A9")
2 = ("Q-2-A1","Q-2-A5",) ...
10 =("Q-10-A2")
can any one please help me how can i achieve this.
Thanks in advance.
Try
NSArray *array = #[#"Q-1-A1",
#"Q-1-A9",
#"Q-2-A1",
#"Q-2-A5",
#"Q-3-A1",
#"Q-3-A8",
#"Q-4-A1",
#"Q-4-A4",
#"Q-10-A2",
#"Q-8-A2",
#"Q-9-A2",
#"Q-7-A1",
#"Q-5-A2"];
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
for (NSString *string in array) {
NSArray *components = [string componentsSeparatedByString:#"-"];
NSString *key = components[1];
NSMutableArray *tempArray = dictionary[key];
if (!tempArray) {
tempArray = [NSMutableArray array];
}
[tempArray addObject:string];
dictionary[key] = tempArray;
}
Create an NSMutableDictionary, then iterate through your 'group array'.
For each NSString object:
get the NSArray of componentsSeparatedByString:#"-"
use the second component to create a key and retrieve the object for that key from your mutable dictionary. If its nil then set it to an empty NSMutableArray.
add the original NSString to the mutable array.
Try this
NSArray *arrData =[[NSArray alloc]initWithObjects:#"Q-1-A1",#"Q-1-A9",#"Q-2-A1",#"Q-2-A5",#"Q-3-A1",#"Q-3-A8",#"Q-4-A1",#"Q-4-A4",#"Q-10-A2",#"Q-8-A2",#"Q-9-A2",#"Q-7-A1",#"Q-5-A2", nil ];
NSMutableDictionary *dictList = [[NSMutableDictionary alloc]init];
for (int i=0; i<[arrData count];i++) {
NSArray *arrItem = [[arrData objectAtIndex:i] componentsSeparatedByString:#"-"];
NSMutableArray *arrSplitedItems = [dictList valueForKey:[arrItem objectAtIndex:1]];
if (!arrSplitedItems) {
arrSplitedItems = [NSMutableArray array];
}
[arrSplitedItems addObject:[arrData objectAtIndex:i]];
[dictList setValue:arrSplitedItems forKey:[arrItem objectAtIndex:1]];
}
NSArray *sortedKeys =[dictList allKeys];
NSArray *sortedArray = [sortedKeys sortedArrayUsingComparator:^(id str1, id str2) {
return [((NSString *)str1) compare:((NSString *)str2) options:NSNumericSearch];
}];
for (int i=0; i<[sortedArray count]; i++) {
NSLog(#"%#",[dictList objectForKey:[sortedArray objectAtIndex:i]]);
}
listOfYourMainArray/// Its YOur main Array;
temArray = (NSArray *)listOfYourMainArray; // Add Your main array to `temArray`.
NSMutableDictionary *lastDic = [[NSMutableDictionary alloc] init]; /// YOu need to creat Dictionary for arrange your values.
for (int i = 0; i< listOfYourMainArray.count; i++)
{
for (int j = 0 ; j < temArray.count; j ++)
{
if (([[temArray objectAtIndex:j] rangeOfString:[NSString stringWithFormat:#"Q-%d", i] options:NSCaseInsensitiveSearch].location != NSNotFound))
{
[lastDic setValue:[temArray objectAtIndex:j] forKey:[NSString stringWithFormat:#"%d", i]];
}
}
}
NSLog(#"%#", lastDic)