I am using SudzC to get webservices, that webservice give me data, I tried to save the data in a property, but when I use to fill a tableview the property don't have any data. I use the debugger to view the property.
This es my handler
- (void) ConsultarUnidadesOrganizacionalesPorEmpresaHandler: (id) value {
// Handle errors
if([value isKindOfClass:[NSError class]]) {
NSLog(#"%#", value);
return;
}
// Handle faults
if([value isKindOfClass:[SoapFault class]]) {
NSLog(#"%#", value);
return;
}
// Do something with the NSMutableArray* result
NSMutableArray *result = (NSMutableArray*)value;
NSMutableArray *unidadOrganizacional = [[NSMutableArray alloc] init];
self.myData = [NSMutableArray array];
for (int i = 0; i < [result count]; i++)
{
EWSUnidadNegocio *empresa = [[EWSUnidadNegocio alloc] init];
empresa = [result objectAtIndex:i];
[unidadOrganizacional addObject:[empresa Descripcion]];
}
self.myData = unidadOrganizacional;
}
And this is the part where I use the web service
- (void)viewDidLoad
{
// Do any additional setup after loading the view from its nib.
EWSEmpresaWebServiceSvc *service = [[EWSEmpresaWebServiceSvc alloc]init];
[service ConsultarUnidadesOrganizacionalesPorEmpresa:self action:#selector(ConsultarUnidadesOrganizacionalesPorEmpresaHandler:) EmpresaId:self.empresaID];
[super viewDidLoad];
}
And the tableview is empty. Why does this happen? How can I use the data and fill my tableview?
Try to change your code this way :
self.myData = [[NSMutableArray alloc] init]autorelease];
// your loop
[sel setMyData:unidadOrganizacional];
try loading it in a dictionary:
dict = [resp objectForKey:#"YourKey"];
if( ( dict == nil ) || ![dict isKindOfClass:[NSDictionary class]] ) {
NSLog( #"WARNING: %#", [dict description]);
return;
}
empID = [[dict objectForKey:#"empresaID"]copy];
NSLog(#"Your Value: %#", empID);
I found the answer, I just have to put
[_myTableView reloadData]
at the end of the method.
Related
I receive the following error: [__NSArrayM addObject:], NIL object. but not crash ,I want to know why display this remind.
here is my code
NSMutableArray *picturesCounts = [NSMutableArray array];
NSMutableArray *bigUrlArray = [NSMutableArray array];
NSMutableArray *pitcturesArray = [NSMutableArray array];
NSInteger i = 1;
for (TNHotelPictures *picture in pictures) {
NSString *pictureCounts = [NSString stringWithFormat:#"%ld",(long)picture.images.count];
[picturesCounts addObject:pictureCounts];
[pitcturesArray addObject:picture.images];
for (TNHotelDetailPhotoImages *photoImage in picture.images) {
[bigUrlArray addObject:photoImage.bigUrl];
}
i++;
}
NSInteger imageInAllIndex = imageIndex;
NSMutableArray *imagesCount = [NSMutableArray array];
for (NSInteger m = 0; m<i; m++) {
imagesCount = pitcturesArray[(typeIndex-(m+1))] ;
imageInAllIndex += imagesCount.count;
}
NSMutableArray *array = [NSMutableArray array];
for (NSString *url in bigUrlArray)
{
if (![url isKindOfClass:[NSString class]])
{
return;
}
TNHotelPhoto *photo = [[TNHotelPhoto alloc] initWithImageURL:[NSURL URLWithString:url]];
[array addObject:photo];
}
TNHotelPhotoSource *source = [[TNHotelPhotoSource alloc] initWithPhotos:array];
TNHotelDetailPhotoBrowserViewController *browserVC = [[TNHotelDetailPhotoBrowserViewController alloc] initWithPhotoSource:source WithImageIndex:imageInAllIndex>=0?imageInAllIndex:0 andImageArray:pictures andTypeIndex:typeIndex];
[UIManager showViewController:browserVC];
}
It means that the object has been initialized and holding a reference in memory. Its not a NIL.
See your code:
for (TNHotelPictures *picture in pictures) {
NSString *pictureCounts = [NSString stringWithFormat:#"%ld",(long)picture.images.count];
[picturesCounts addObject:pictureCounts];
[pitcturesArray addObject:picture.images];
for (TNHotelDetailPhotoImages *photoImage in picture.images) {
[bigUrlArray addObject:photoImage.bigUrl];
}
i++;
}
I think you should check the picture whether its properties pictureCounts,images,bigUrl are not nil.
Here is my requirement :
forSaleSingleProperties array should contain dictionaries with no same attribute PARCELID
forSaleMultipleProperties array should contain an array of those dictionaries with same attribute PARCELID
forSalePropertiesArray is the base array containing all dict.
Note: Dictionaries contain various other attributes. I want all those with same PARCELID attribute
I don't understand what is wrong with this logic...
if (_forSaleSinglePropertiesArray==nil) {
_forSaleSinglePropertiesArray = [[NSMutableArray alloc]initWithObjects: nil];
}
if (_forSaleMultiplePropertiesArray==nil) {
_forSaleMultiplePropertiesArray = [[NSMutableArray alloc]initWithObjects: nil];
}
if (_forSalePropertiesArray!=nil) {
if (_forSalePropertiesArray.count>1) {
BOOL propertyObject1IsMultiple = NO;
NSDictionary *propertyObject1;
NSMutableArray *multiplePinArray = [[NSMutableArray alloc]initWithObjects: nil];
for (int i=0; i<_forSalePropertiesArray.count; i++) {
propertyObject1 = [_forSalePropertiesArray objectAtIndex:i];
multiplePinArray = nil;
multiplePinArray = [[NSMutableArray alloc]initWithObjects: nil];
for (int j=i+1; j<_forSalePropertiesArray.count; j++) {
NSDictionary *propertyObject2 = [_forSalePropertiesArray objectAtIndex:j];
if ([propertyObject1 valueForKey:PARCEL_ID]==[propertyObject2 valueForKey:PARCEL_ID]) {
if (_forSaleMultiplePropertiesArray.count==0) {
[multiplePinArray addObject:propertyObject2];
propertyObject1IsMultiple = YES;
[_forSaleMultiplePropertiesArray addObject:multiplePinArray];
}else{
BOOL propFound = NO;
NSMutableArray *propArr;
NSInteger index = -1;
for(NSMutableArray *arr in _forSaleMultiplePropertiesArray){
if (![arr containsObject:propertyObject2]&&!propFound) {
[arr addObject:propertyObject2];
propertyObject1IsMultiple = YES;
propFound = YES;
index = [_forSaleMultiplePropertiesArray indexOfObject:arr];
propArr = [[NSMutableArray alloc]initWithArray:arr];
}
}
if (propArr!=nil) {
[_forSaleMultiplePropertiesArray replaceObjectAtIndex:index withObject:propArr];
}
}
}
}
if (!propertyObject1IsMultiple) {
[_forSaleSinglePropertiesArray addObject:propertyObject1];
}
}
}
}
OK so...
I'm leaving this as a placeholder.
Sort the parent array by PARCELID.
Iterate array.
Sort into two piles.
... or something. Will write it later.
I would have done it more like this:
- (void)solution {
self.forSaleSinglePropertiesArray = [[NSMutableArray alloc] init];
self.forSaleMultiplePropertiesArray = [[NSMutableArray alloc] init];
NSDictionary *partitionedProperties = partitionPropertiesByParcelID(self.forSalePropertiesArray);
[self dividePropertiesIntoSingleAndMultiple:partitionedProperties];
}
NSDictionary *partitionPropertiesByParcelID(NSArray *properties) {
NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
for (NSDictionary *property in properties) {
id parcelID = property[PARCEL_ID];
NSMutableArray *parcels = result[parcelID];
if (parcels == nil) {
parcels = [[NSMutableArray alloc] init];
[result setObject:parcels forKey:parcelID];
}
[parcels addObject:property];
}
return result;
}
- (void)dividePropertiesIntoSingleAndMultiple:(NSDictionary *)partitionedProperties {
for (NSArray *properties in partitionedProperties.allValues) {
if (properties.count == 1) {
[self.forSaleSinglePropertiesArray addObject:properties[0]];
}
else {
assert(properties.count > 1);
[self.forSaleMultiplePropertiesArray addObject:properties];
}
}
}
First the code creates a Dictionary where the keys are parcel IDs and the values are arrays of properties with that parcle ID. Then it goes through that dictionary and puts a representative of each parcel ID into either the single or multiple array.
I feel that this code is easier to understand, and I strongly suspect that if you do performance metrics on the above code and your answer, that this code will have better performance over large data sets. I believe this is true because your answer seems to have O(n^2) performance while mine is O(n). (Read up on "Big-O notation" if you aren't sure what this means.)
Also, are you sure that your answer actually works for all data sets? Removing objects out of an array while iterating over it throws up a huge red flag in my book.
I liked #Fogmeister's sort idea so much, I implemented it:
- (void)sortSolultion {
self.forSaleSinglePropertiesArray = [[NSMutableArray alloc] init];
self.forSaleMultiplePropertiesArray = [[NSMutableArray alloc] init];
NSArray *forSaleArray = [self.forSalePropertiesArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1[PARCEL_ID] compare:obj2[PARCEL_ID]];
}];
id currentParcelID = nil;
self.propertiesWithCurrentParcelID = [[NSMutableArray alloc] init];
for (NSDictionary *property in forSaleArray) {
if (self.propertiesWithCurrentParcelID.count == 0) {
currentParcelID = property[PARCEL_ID];
}
else if (![property[PARCEL_ID] isEqual: currentParcelID]) {
[self placeCurrentPropertiesInCorrectArray];
currentParcelID = property[PARCEL_ID];
}
[self.propertiesWithCurrentParcelID addObject:property];
}
[self placeCurrentPropertiesInCorrectArray];
}
- (void)placeCurrentPropertiesInCorrectArray {
if (self.propertiesWithCurrentParcelID.count > 1) {
[self.forSaleMultiplePropertiesArray addObject:self.propertiesWithCurrentParcelID];
}
else if (self.propertiesWithCurrentParcelID.count == 1) {
[self.forSaleSinglePropertiesArray addObject:self.propertiesWithCurrentParcelID[0]];
}
[self.propertiesWithCurrentParcelID removeAllObjects];
}
This solution has a slightly higher cyclomatic complexity than my previous solution, and indeed it was harder to get it error free than my first one. But this solution has a smaller allocation footprint. Both seem to have the same big-O complexity.
Alright I got it right myself.
Updated Code to a much simpler and fast mechanism below:
if (_forSaleSinglePropertiesArray==nil) {
_forSaleSinglePropertiesArray = [[NSMutableArray alloc]initWithObjects: nil];
}
if (_forSaleMultiplePropertiesArray==nil) {
_forSaleMultiplePropertiesArray = [[NSMutableArray alloc]initWithObjects: nil];
}
if (_forSalePropertiesArray!=nil) {
NSMutableDictionary *samePropsDict = [[NSMutableDictionary alloc]init];
for (NSDictionary* dict in _forSalePropertiesArray) {
NSMutableArray *samePropsArray = [samePropsDict objectForKey:[dict valueForKey:PARCEL_ID]];
if (samePropsArray==nil) {
samePropsArray = [[NSMutableArray alloc]init];
}
[samePropsArray addObject:dict];
[samePropsDict setObject:samePropsArray forKey:[dict valueForKey:PARCEL_ID]];
}
for (NSString *key in [samePropsDict allKeys]) {
NSArray *arr = [samePropsDict objectForKey:key];
if (arr.count>1) {
[_forSaleMultiplePropertiesArray addObject:arr];
}else{
[_forSaleSinglePropertiesArray addObject:[arr firstObject]];
}
}
}
-(void) objectParsed_ListAllMedia:(NSDictionary *)dictionary
{
#try {
self.viewLoading.hidden=1;
[self.arrGaalleryMediaName removeAllObjects];
[self.arrMediaNames removeAllObjects];
if(self.arrOnlyServerImages == nil){
self.arrOnlyServerImages = [[NSMutableArray alloc] init];
}
if([self.arrOnlyServerImages count] >0){
[self.arrOnlyServerImages removeAllObjects];
}
if (dictionary==nil) {
[self.gridCollectionView reloadData];
return;
}
// Filter Array for Audio file
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"type != 'audio' "];
self.arrOnlyServerImages = [NSMutableArray arrayWithArray:[[dictionary objectForKey:#"objects"] filteredArrayUsingPredicate:predicate]];
// Remove duplicate Start //Read Meta Data and Duplicate from Download, Duplicate from upload START
dispatch_queue_t backgroundQueue = dispatch_queue_create("com.memreas.myqueue", 0);
dispatch_async(backgroundQueue, ^{
NSMutableArray *arr = [NSMutableArray array];
NSMutableIndexSet * indexSet = [NSMutableIndexSet indexSet];
for (int i=0; self.assetAry.count>i; i++) {
ALAsset *result =self.assetAry[i];
ALAssetRepresentation *imageRep = [result defaultRepresentation];
NSDictionary * customMetaDic = [imageRep metadata][(NSString*)kCGImagePropertyIPTCDictionary];
if (customMetaDic) {
[self.arrMediaNames addObject:customMetaDic[(NSString*)kCGImagePropertyIPTCObjectName]?customMetaDic[(NSString*)kCGImagePropertyIPTCObjectName]:#""];
}else{
[self.arrMediaNames addObject:#""];
}
[self.arrGaalleryMediaName addObject:[self getFileNameWithExtensionFromPath:imageRep.url]];
}
for (int i=0; self.arrOnlyServerImages.count>i; i++) {
NSMutableDictionary* obj = self.arrOnlyServerImages[i];
NSMutableDictionary * dic2 = [NSMutableDictionary dictionaryWithDictionary:obj];
BOOL isArrMedia =[self.arrMediaNames containsObject:dic2[#"media_name"]];
BOOL isGallery =[self.arrGaalleryMediaName containsObject:dic2[#"media_name"]];
if (isArrMedia||isGallery) {
dic2[#"isDownloaded"] = [NSNumber numberWithBool:YES];
[indexSet addIndex: isArrMedia?[self.arrMediaNames indexOfObject:dic2[#"media_name"]] :[self.arrGaalleryMediaName indexOfObject:dic2[#"media_name"]]];
}else{
dic2[#"isDownloaded"] = [NSNumber numberWithBool:NO];
}
[arr addObject:dic2];
}
dispatch_async(dispatch_get_main_queue(), ^{
#try {
self.arrOnlyServerImages = arr;
[self.assetAry removeObjectsAtIndexes:indexSet];
[self.gridCollectionView reloadData];
}
#catch (NSException *exception) {
NSLog(#"%#",exception);
[self.gridCollectionView reloadData];
}
});
});
// Remove duplicate END //Read Meta Data and Duplicate from Download, Duplicate from upload END
[self.gridCollectionView reloadData];
[self.gridView.collectionView reloadData];
[self.location performSelector:#selector(stopActivity) withObject:nil afterDelay:2];
}
#catch (NSException *exception) {
NSLog(#"%#",exception);
}
}
I have issue with my code, While I run this code it generates memory pressure issue and crash the app.
Functionality is:
I load all the images from server and local assets and match each other with file name and remove duplicate images from list, So it will visible only once.
Any one have solution so please help.
thanks in advance.
You're accessing memory-intensive things (ALAssetRepresentations) in a tight loop. In these cases a local autoreleasepool can help ARC to keep your memory use down.
Inside the loop where you pass through self.assetAry, wrap everything in an autoreleasepool like so:
#autoreleasepool {
AlAsset *asset = ...
...
// Rest of your code
}
The following code is in my implementation file:
NSMutableArray *courseArray;
- (IBAction)btnClick:(id)sender
{
NSDictionary *courseNames;
if(![_txtBox.text isEqual:#""]) //if not empty
{
courseNames = [self retrieveCourseNamesForSemester:_txtBox.text];
for (NSString *key in courseNames)
{
NSString *val = [NSString stringWithFormat:#"%#-%#",key,[courseNames objectForKey:key]];
_txtView.text = val;
#try
{
[courseArray addObject:val];
}
#catch(NSException *e)
{
NSLog(#"Exception: %# for value = %#", e, val);
}
}
}
[_coursePicker reloadAllComponents];
_coursePicker.hidden=false;
[_txtBox resignFirstResponder];
}
Where you see the call to NSLog(), I get the following error message:
2014-03-29 00:02:25.830 WebServiceTest[44646:60b] Exception: -[__NSArrayI addObject:]: unrecognized selector sent to instance 0x8d82c30 for value = 73-522-Course Name
EDIT: Also, courseArray is populated with sample data in viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
courseArray = #[#"Australia (AUD)", #"China (CNY)",
#"France (EUR)", #"Great Britain (GBP)", #"Japan (JPY)"];
}
Is there somewhere I should be defining that courseArray will take NSString objects?
The code in viewDidLoad creates an immutable array. You need to make a mutable copy, like this
(void)viewDidLoad
{
[super viewDidLoad];
courseArray = [#[#"(AUD)", #"(CNY)", #"(EUR)"] mutableCopy];
}
Try this code,
for (NSString *key in courseNames)
{
NSString *val = [NSString stringWithFormat:#"%#-%#",key,[courseNames objectForKey:key]];
_txtView.text = val;
if ([CourseArray count]==0)
{
CourseArray= [NSMutableArray arrayWithObject:val];
}
else
{
[CourseArray addObject:val];
}
}
I'm trying to get the metadata from the box api and so I need to traverse the entire directory structure. Here is the code:
- (IBAction)ls {
// INITIALIZE folderID (will be nil only for the root folder)
if (self.folderID == nil)
{
self.folderID = BoxAPIFolderIDRoot;
self.folderName = #"Root";
}
// START TRAVERSING DIRECTORY TREE
[self traverseItemsWithFolderID:self.folderID name:self.folderName];
}
- (void)traverseItemsWithFolderID:(NSString *)folder name:(NSString *)namefolder
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self fetchFolderItemsWithFolderID:folder name:namefolder]; // <- List Files/dirs in directory namefolder
dispatch_async(dispatch_get_main_queue(), ^{
// Create box object "item" to traverse folderItemsArray
BoxItem * item = (BoxItem *)[self.folderItemsArray objectEnumerator];
for (item in self.folderItemsArray)
{
if([item.type isEqualToString:BoxAPIItemTypeFolder])
{
NSLog(#"SubFolder id %#", item.modelID);
NSLog(#"SubFolder name %#", item.name);
[self traverseItemsWithFolderID:item.modelID name:item.name];
}
}
});
});
}
and this last method:
- (void)fetchFolderItemsWithFolderID:(NSString *)innerFolder name:(NSString *)innerFolderName
{
BoxFoldersResourceManager *mgr = [BoxSDK sharedSDK].foldersManager;
BoxFoldersRequestBuilder *bldr = [[BoxFoldersRequestBuilder alloc] initWithQueryStringParameters:#{ #"fields" : #"name,type,id,etag,size,modified_at,hash" }];
[mgr folderItemsWithID:innerFolder requestBuilder:bldr success: ^(BoxCollection *collection)
{
self.folderItemsArray = [NSMutableArray array];
for (NSUInteger i = 0; i < collection.numberOfEntries; i++)
{
[self.folderItemsArray addObject:[collection modelAtIndex:i]];
NSLog(#"FOLDER NAME %#", innerFolderName);
BoxItem *item = (BoxItem *)[self.folderItemsArray objectAtIndex:i];
NSLog(#"Here The list of Files/Directories:");
NSLog(#"TypE %#", item.type); // [file/directory]
NSLog(#"NAME %#", item.name); // filename
NSLog(#"ID %#", item.ETag); // directory level [0 = root]
NSLog(#"ID %#", item.modelID); // metadata unique identifier [FolderID !]
NSLog(#"SIZE %#", item.size); // in bytes
NSLog(#"Modified Time %#", item.modifiedAt); // in UTC format
NSLog(#"HASH %lu", (unsigned long)item.hash); // hash
}
self.totalCount = [collection.totalCount integerValue];
NSLog(#" Number of files/dirs in Level %ld", (long)self.totalCount);
}
The final result is that the code start an infinite loop of requests and don't understand why, as it should stop when there are no more directories. Any help on identifying the issue is much appreciated.
Thanks !
You should avoid using the property self.folderItemsArray since you have a recursive method, try this:
- (NSArray*)fetchFolderItemsWithFolderID:(NSString *)innerFolder name:(NSString *)innerFolderName
{
...
// This is a new line.
NSMutableArray* folderItemsArray = [NSMutableArray array];
[mgr folderItemsWithID:innerFolder requestBuilder:bldr success: ^(BoxCollection *collection)
{
//self.folderItemsArray = [NSMutableArray array]; remove this line.
for (NSUInteger i = 0; i < collection.numberOfEntries; i++)
{
[folderItemsArray addObject:[collection modelAtIndex:i]]; // remove the self here.
...
}
return folderItemsArray;
}
And update this method like this:
- (void)traverseItemsWithFolderID:(NSString *)folder name:(NSString *)namefolder
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSArray* items = [self fetchFolderItemsWithFolderID:folder name:namefolder]; // <- List Files/dirs in directory namefolder
dispatch_async(dispatch_get_main_queue(), ^{
// Create box object "item" to traverse folderItemsArray
//BoxItem * item = (BoxItem *)[self.folderItemsArray objectEnumerator]; why do you need this line.
for (BoxItem *item in items)
{
if([item.type isEqualToString:BoxAPIItemTypeFolder])
{
NSLog(#"SubFolder id %#", item.modelID);
NSLog(#"SubFolder name %#", item.name);
[self traverseItemsWithFolderID:item.modelID name:item.name];
}
}
});
});
}