Encapsulating data and CPTScatterPlot object with delegates into one class - core-plot

I am trying to find a way to encapsulate the data for a plot and the delegate functions in one class. This will make it much simpler to create multiple plots dynamically based on the number of data sets that I acquire.
To do so, I created a class that includes the x, y data points and CPTScatterPlot object, as well as the standard delegate functions, which are now class methods that access the internal data.
When the object is instantiated, the idea is to pass it the data and the graph object, and the constructor makes "self" the data source.
Here is the code:
// DataScatterPlot.h
#import <Foundation/Foundation.h>
#import "CorePlot-CocoaTouch.h"
#interface DataScatterPlot : NSObject <CPTScatterPlotDataSource>
#property (nonatomic, strong) CPTScatterPlot *CPTScatterPlotObj;
#property (nonatomic, strong) NSMutableArray *x;
#property (nonatomic, strong) NSMutableArray *y;
- (id) initWithGraph: (CPTXYGraph*) graph DataX: (NSMutableArray*) x andDataY: (NSMutableArray*) y;
#end
// DataScatterPlot.m
#import "DataScatterPlot.h"
#implementation DataScatterPlot
-(id) initWithGraph: (CPTXYGraph *)graph DataX:(NSMutableArray *)dataX andDataY:(NSMutableArray *)dataY {
self = [super init];
if ( self != nil ) {
self.CPTScatterPlotObj = [[CPTScatterPlot alloc] init];
self.x = dataX;
self.y = dataY;
self.CPTScatterPlotObj.dataSource = (id<CPTScatterPlotDataSource>) self;
[graph addPlot:self.CPTScatterPlotObj];
}
return self;
}
// Delegate method that returns the number of points on the plot
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
NSLog(#"The count is %lu", (unsigned long)[self.x count]);
return [self.x count];
}
// Delegate method that returns a single X or Y value for a given plot.
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
// For Sigmoid
NSNumber *dataX = [self.x objectAtIndex:index];
NSNumber *dataY = [self.y objectAtIndex:index];
// FieldEnum determines if we return an X or Y value.
switch (fieldEnum) {
case CPTScatterPlotFieldX:
{
return dataX;
}
case CPTScatterPlotFieldY: // Y-Axis
{
return dataY;
}
default:
return [NSNumber numberWithFloat:0];
}
}
#end
When I run the code, I get an "unrecognized selector sent to instance" error, which seems it indicate it is looking for a method that does not exist within the object.
Is there something that I'm doing incorrectly?
Here is the error message:
2015-10-09 12:02:09.743 SigmoidWithCustomDataClass[1192:10285] -[__NSDictionaryI numberOfRecordsForPlot:]: unrecognized selector sent to instance 0x7f9a2bda7fb0
2015-10-09 12:02:10.550 SigmoidWithCustomDataClass[1192:10285] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDictionaryI numberOfRecordsForPlot:]: unrecognized selector sent to instance 0x7f9a2bda7fb0'
*** First throw call stack:
(
0 CoreFoundation 0x000000010f697c65 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010f330bb7 objc_exception_throw + 45
2 CoreFoundation 0x000000010f69f0ad -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x000000010f5f513c ___forwarding___ + 988
4 CoreFoundation 0x000000010f5f4cd8 _CF_forwarding_prep_0 + 120
5 SigmoidWithCustomDataClass 0x000000010eaae44b -[CPTPlot reloadData] + 94
6 SigmoidWithCustomDataClass 0x000000010eaae289 -[CPTPlot drawInContext:] + 36
7 QuartzCore 0x000000010ec1b92b CABackingStoreUpdate_ + 2793
8 QuartzCore 0x000000010ed21933 ___ZN2CA5Layer8display_Ev_block_invoke + 59
9 QuartzCore 0x000000010ed217be _ZN2CA5Layer8display_Ev + 1478
10 QuartzCore 0x000000010ed164d9 _ZN2CA5Layer17display_if_neededEPNS_11TransactionE + 301
11 QuartzCore 0x000000010ed16561 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 35
12 QuartzCore 0x000000010ec8286e _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 242
13 QuartzCore 0x000000010ec83a22 _ZN2CA11Transaction6commitEv + 462
14 UIKit 0x000000010fcd09ed -[UIApplication _reportMainSceneUpdateFinished:] + 44
15 UIKit 0x000000010fcd16b1 -[UIApplication _runWithMainScene:transitionContext:completion:] + 2648
16 UIKit 0x000000010fcd0095 -[UIApplication workspaceDidEndTransaction:] + 179
17 FrontBoardServices 0x0000000114bb75e5 __31-[FBSSerialQueue performAsync:]_block_invoke_2 + 21
18 CoreFoundation 0x000000010f5cb41c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
19 CoreFoundation 0x000000010f5c1165 __CFRunLoopDoBlocks + 341
20 CoreFoundation 0x000000010f5c0f25 __CFRunLoopRun + 2389
21 CoreFoundation 0x000000010f5c0366 CFRunLoopRunSpecific + 470
22 UIKit 0x000000010fccfb02 -[UIApplication _run] + 413
23 UIKit 0x000000010fcd28c0 UIApplicationMain + 1282
24 SigmoidWithCustomDataClass 0x000000010eaad71f main + 111
25 libdyld.dylib 0x0000000112474145 start + 1
26 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)

The plot's datasource is a dictionary. Check the rest of your code and make sure you're not reassigning the datasource anywhere.

Related

Can't access object's properties after encoding it (crashes)

I have a custom class oject that I want to save using NSUserDefaults, this is how I saving it:
Shift.m
-(void)encodeWithCoder:(NSCoder*)encoder
{
[encoder encodeObject:self.date forKey:#"date"];
[encoder encodeObject:self.startTime forKey:#"startTime"];
[encoder encodeObject:self.endTime forKey:#"endTime"];
}
- (id)initWithCoder:(NSCoder *)decoder {
if(self = [super init]) {
self.date = [decoder decodeObjectForKey:#"date"];
self.startTime = [decoder decodeObjectForKey:#"startTime"];
self.endTime = [decoder decodeObjectForKey:#"endTime"];
}
return self;
}
MyTableViewController.m:
-(void)saveCustomObject:(id)object forKey:(NSString*)key
{
NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:object];
[[NSUserDefaults standardUserDefaults] setObject:encodedObject forKey:key];
}
-(NSArray*)getCustomObjectForKey:(NSString*)key
{
NSData *encodedObject = [[NSUserDefaults standardUserDefaults] objectForKey:key];
NSArray *shifts=[NSArray arrayWithObjects:[NSKeyedUnarchiver unarchiveObjectWithData:encodedObject], nil];
return shifts;
}
It seems it works fine when debugging, but when I try to access one of the object properties, for example on tableView: cellForRowAtIndexPath: like that:
Shift *currentShift=[self.shifts objectForIndex:indexPath.row];
NSLog(#"%#",currentShift.startTime.description);
It crashes with that crash message:
2016-03-19 09:04:05.913 MyApp[9654:4249448] -[__NSArrayM startTime]: unrecognized selector sent to instance 0x7ff81b449c10
2016-03-19 09:04:05.924 MyApp[9654:4249448] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM startTime]: unrecognized selector sent to instance 0x7ff81b449c10'
*** First throw call stack:
(
0 CoreFoundation 0x000000010e3e9e65 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010de62deb objc_exception_throw + 48
2 CoreFoundation 0x000000010e3f248d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x000000010e33f90a ___forwarding___ + 970
4 CoreFoundation 0x000000010e33f4b8 _CF_forwarding_prep_0 + 120
5 Mehuyavut count 0x000000010d95a8e8 -[shiftsTableViewViewController tableView:cellForRowAtIndexPath:] + 600
6 UIKit 0x000000010e8efe43 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 766
7 UIKit 0x000000010e8eff7b -[UITableView _createPreparedCellForGlobalRow:willDisplay:] + 74
8 UIKit 0x000000010e8c4a39 -[UITableView _updateVisibleCellsNow:isRecursive:] + 2996
9 UIKit 0x000000010e8f901c -[UITableView _performWithCachedTraitCollection:] + 92
10 UIKit 0x000000010e8dfedc -[UITableView layoutSubviews] + 224
11 UIKit 0x000000010e84d4a3 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 703
12 QuartzCore 0x000000011231959a -[CALayer layoutSublayers] + 146
13 QuartzCore 0x000000011230de70 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 366
14 QuartzCore 0x000000011230dcee _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
15 QuartzCore 0x0000000112302475 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 277
16 QuartzCore 0x000000011232fc0a _ZN2CA11Transaction6commitEv + 486
17 QuartzCore 0x000000011233037c _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 92
18 CoreFoundation 0x000000010e315367 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
19 CoreFoundation 0x000000010e3152d7 __CFRunLoopDoObservers + 391
20 CoreFoundation 0x000000010e30af2b __CFRunLoopRun + 1147
21 CoreFoundation 0x000000010e30a828 CFRunLoopRunSpecific + 488
22 GraphicsServices 0x0000000111ba6ad2 GSEventRunModal + 161
23 UIKit 0x000000010e796610 UIApplicationMain + 171
24 Mehuyavut count 0x000000010d95b5af main + 111
25 libdyld.dylib 0x0000000110b2592d start + 1
26 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Any one knows why?
Thank you!
It seems like you want Shift *currentShift=[self.shifts objectForIndex:indexPath.row] to give you 1 Shift object, but what it really does is returning a NSArray. You basically call a startTime method in NSArray, and since it doesn't exist, your program fails.
It seems like NSLog(#"%#",currentShift.startTime.description) is the line doing that. Confirm by commenting out the NSLog. It shouldn't give you a crash.
If this hypothesis is fine, check if [currentShift isKindOfClass:[NSArray class]] is true.
If it is, a bug you have in this line:
NSArray *shifts=[NSArray arrayWithObjects:[NSKeyedUnarchiver unarchiveObjectWithData:encodedObject], nil];
You also don't really show how your - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section looks like. You must return proper number of entries there.
You're making self.shifts be an NSArray, but you use objectForKey, which is available for dictionaries. It's not available for arrays. I think you wanted objectAtIndex instead.

How to map local NSDictionary into a custom Object using RKMappingOperation?

RJobObject * jobObj = [RJobObject new];
RKMappingOperation *mappingOperation = [[RKMappingOperation alloc] initWithSourceObject:jobDictionary destinationObject:jobObj mapping:[RJobObject mapping]];
mappingOperation.dataSource = (id)jobObj;
[mappingOperation start];
jobDictionary structure:
NSDictionary *msg1 = #{
#"id" : #"dfcd",
#"message" : #"ndjfcdfcd"
};
NSDictionary *msg2 = #{
#"id" : #"fjvdfv",
#"message" : #"kjndcdovc"
};
NSDictionary *msg3 = #{
#"id" : #"fce",
#"message" : #"dfcdf"
};
NSArray *msgsArray = [NSArray arrayWithObjects:msg1, msg2,msg3, nil];
NSMutableDictionary * jobDictionary = [NSMutableDictionary dictionaryWithDictionary:#{#"id" : #"Sourabh pant",
#"title": #"http://www.google.com"
}];
[jobDictionary setObject:msgsArray forKey:#"messages"];
/......................................................./
RJobObject is the custom object:
#property (nonatomic) NSString * id;
#property (nonatomic) long long duration;
#property (nonatomic) NSString * title;
#property (nonatomic) NSString * image;
#property (nonatomic) NSString * secret;
#property (nonatomic) NSInteger unreadCount;
#property (nonatomic) NSArray * messages;
This creates a crash inside RRestkit, if the jobDictionary contains messages.If the messages array inside jobDictionary is empty,then the code runs fine.
So to sum up the message array is not being mapped.
Stack trace
2015-11-28 15:59:22.808 Checking Rest Kit[35951:3402596] -
[RJobObject mappingOperation:targetObjectForRepresentation:withMapping:inRelationship:]: unrecognized selector sent to instance 0x79f96270
2015-11-28 16:00:48.987 Checking Rest Kit[35951:3402596] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[RJobObject mappingOperation:targetObjectForRepresentation:withMapping:inRelationship:]: unrecognized selector sent to instance 0x79f96270'
*** First throw call stack:
(
0 CoreFoundation 0x018e3a14 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x013a2e02 objc_exception_throw + 50
2 CoreFoundation 0x018ecd63 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
3 CoreFoundation 0x0182a6bd ___forwarding___ + 1037
4 CoreFoundation 0x0182a28e _CF_forwarding_prep_0 + 14
5 Checking Rest Kit 0x00142f48 -[RKMappingOperation destinationObjectForMappingRepresentation:parentRepresentation:withMapping:inRelationship:] + 1704
6 Checking Rest Kit 0x00149885 __64-[RKMappingOperation mapOneToManyRelationshipWithValue:mapping:]_block_invoke + 149
7 CoreFoundation 0x018152e9 __53-[__NSArrayI enumerateObjectsWithOptions:usingBlock:]_block_invoke + 73
8 CoreFoundation 0x01815182 -[__NSArrayI enumerateObjectsWithOptions:usingBlock:] + 162
9 CoreFoundation 0x017ff835 -[NSArray enumerateObjectsUsingBlock:] + 53
10 Checking Rest Kit 0x0014920b -[RKMappingOperation mapOneToManyRelationshipWithValue:mapping:] + 2763
11 Checking Rest Kit 0x0014b4fb -[RKMappingOperation applyRelationshipMappings] + 6283
12 Checking Rest Kit 0x0014d7db -[RKMappingOperation main] + 4075
13 Checking Rest Kit 0x0014c7dd -[RKMappingOperation start] + 45
14 Checking Rest Kit 0x000ab866 -[ViewController jobObjectFromJobDictionary:] + 310
15 Checking Rest Kit 0x000ab6d5 -[ViewController fetchJobFromDbForId:] + 85
16 Checking Rest Kit 0x000ab566 -[ViewController viewDidLoad] + 918
17 UIKit 0x01e3b2ae -[UIViewController _sendViewDidLoadWithAppearanceProxyObjectTaggingEnabled] + 44
18 UIKit 0x01e3fdce -[UIViewController loadViewIfRequired] + 1384
19 UIKit 0x01e401ed -[UIViewController view] + 35
20 UIKit 0x01cedf94 -[UIWindow addRootViewControllerViewIfPossible] + 69
21 UIKit 0x01cee6b1 -[UIWindow _setHidden:forced:] + 304
22 UIKit 0x01ceea67 -[UIWindow _orderFrontWithoutMakingKey] + 49
23 UIKit 0x01d02118 -[UIWindow makeKeyAndVisible] + 80
24 UIKit 0x01c6a6e7 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4190
25 UIKit 0x01c71cd6 -[UIApplication _runWithMainScene:transitionContext:completion:] + 1989
26 UIKit 0x01c96ee5 __84-[UIApplication _handleApplicationActivationWithScene:transitionContext:completion:]_block_invoke3218 + 68
27 UIKit 0x01c6e966 -[UIApplication workspaceDidEndTransaction:] + 163
28 FrontBoardServices 0x04c4dc76 __37-[FBSWorkspace clientEndTransaction:]_block_invoke_2 + 71
29 FrontBoardServices 0x04c4d74d __40-[FBSWorkspace _performDelegateCallOut:]_block_invoke + 54
30 FrontBoardServices 0x04c6b173 -[FBSSerialQueue _performNext] + 184
31 FrontBoardServices 0x04c6b5aa -[FBSSerialQueue _performNextFromRunLoopSource] + 52
32 FrontBoardServices 0x04c6a8a6 FBSSerialQueueRunLoopSourceHandler + 33
33 CoreFoundation 0x017fd6ff __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
34 CoreFoundation 0x017f338b __CFRunLoopDoSources0 + 523
35 CoreFoundation 0x017f27a8 __CFRunLoopRun + 1032
36 CoreFoundation 0x017f20e6 CFRunLoopRunSpecific + 470
37 CoreFoundation 0x017f1efb CFRunLoopRunInMode + 123
38 UIKit 0x01c6e206 -[UIApplication _run] + 540
39 UIKit 0x01c73bfa UIApplicationMain + 160
40 Checking Rest Kit 0x000af02a main + 138
41 libdyld.dylib 0x03911a21 start + 1
42 ??? 0x00000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
In Rconnection.m
- (id)destinationObjectForMappingRepresentation:(id)representation parentRepresentation:(id)parentRepresentation withMapping:(RKMapping *)mapping inRelationship:(RKRelationshipMapping *)relationshipMapping {
/* Some Code */
............
if (destinationObject == nil)
{
NSDictionary *dictionaryRepresentation = [representation isKindOfClass:[NSDictionary class]] ? representation : #{ [NSNull null] : representation };
RKMappingMetadata *parentMetadata = [RKMappingMetadata new];
parentMetadata.parentObject = self.destinationObject ?: [NSNull null];
NSArray *metadata = RKInsertInMetadataList(self.metadataList, parentMetadata, nil);
RKMappingSourceObject *sourceObject = [[RKMappingSourceObject alloc] initWithObject:dictionaryRepresentation parentObject:parentRepresentation rootObject:self.rootSourceObject metadata:metadata];
// Crashing Breakpoint below:
destinationObject = [dataSource mappingOperation:self targetObjectForRepresentation:(NSDictionary *)sourceObject withMapping:concreteMapping inRelationship:relationshipMapping];
}
.......
/* Some code */
}
#import <Foundation/Foundation.h>
#import <RestKit/RestKit.h>
#interface RJobObject : NSObject
#property (nonatomic) NSString * id;
#property (nonatomic) long long duration;
#property (nonatomic) NSString * title;
#property (nonatomic) NSString * image;
#property (nonatomic) NSString * secret;
#property (nonatomic) NSInteger unreadCount;
#property (nonatomic) NSArray * messages;
+(RKObjectMapping *)mapping;
#end
This line is incorrect:
mappingOperation.dataSource = (id)jobObj;
because you are giving the operation a plain data model object as a data source (and telling the compiler to like it by casting to id).
When the operation runs it needs some new instances to be created so it can map the content from the JSON dict into them, this is a job the data source is supposed to do. When the operation asks the data source you get a crash because the object you provided as the data source, jobObj, doesn't understand the request.
You need to create and set an appropriate data source that can handle this requirement.

objective-c -[__NSCFNumber length]: unrecognized selector sent to instance

I'm working on an iOS app with collectionView in objective-c and I have an error.
Below code is for feeding each cell with data(image in this case).
I pick up an image name from two dimensional array in Model class, and display it.
I made up a new array to prevent from duplication of image display by changing value in the array from '0' to '1' so next time can avoid display '1' marked image.
I succeeded initial setting all arrays with NSInteger 0, with replaceObjectAtIndex:withObject: method in a 'ViewDidLaod' method, however, I have an error when I want to change the value into '1' in the array with replaceObjectAtIndex:withObject:, the same method I used in the 'ViewDidLaod' method.
I already searched google and stack but people who got the same problem used immutable array, that's why they had an issue, but I have mutable array in my code. Please help me.
The error message is below:
2015-04-13 03:55:25.824 InfanTree[4474:166010] -[__NSCFNumber length]: unrecognized selector sent to instance 0xb000000000000002
2015-04-13 03:55:25.846 InfanTree[4474:166010] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber length]: unrecognized selector sent to instance 0xb000000000000002'
*** First throw call stack:
(
0 CoreFoundation 0x000000010826fa75 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x0000000107f08bb7 objc_exception_throw + 45
2 CoreFoundation 0x0000000108276d1d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x00000001081ce9dc ___forwarding___ + 988
4 CoreFoundation 0x00000001081ce578 _CF_forwarding_prep_0 + 120
5 UIKit 0x0000000108f13f06 +[_UIAssetManager createAssetNamed:fromBundle:] + 67
6 UIKit 0x00000001088d4f60 +[UIImage imageNamed:inBundle:compatibleWithTraitCollection:] + 221
7 InfanTree 0x00000001079c92d0 -[ViewController collectionView:cellForItemAtIndexPath:] + 512
8 UIKit 0x0000000108ed1fab -[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:] + 244
9 UIKit 0x0000000108ed36e4 -[UICollectionView _updateVisibleCellsNow:] + 3445
10 UIKit 0x0000000108ed7391 -[UICollectionView layoutSubviews] + 243
11 UIKit 0x000000010891c1c3 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 521
12 QuartzCore 0x000000010cc5ac58 -[CALayer layoutSublayers] + 150
13 QuartzCore 0x000000010cc4f87e _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
14 QuartzCore 0x000000010cc4f6ee _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
15 QuartzCore 0x000000010cbbd36e _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 242
16 QuartzCore 0x000000010cbbe482 _ZN2CA11Transaction6commitEv + 390
17 UIKit 0x00000001088a068d -[UIApplication _reportMainSceneUpdateFinished:] + 44
18 UIKit 0x00000001088a1375 -[UIApplication _runWithMainScene:transitionContext:completion:] + 2684
19 UIKit 0x000000010889fd35 -[UIApplication workspaceDidEndTransaction:] + 179
20 FrontBoardServices 0x000000010bd92243 __31-[FBSSerialQueue performAsync:]_block_invoke + 16
21 CoreFoundation 0x00000001081a4c7c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
22 CoreFoundation 0x000000010819a9c5 __CFRunLoopDoBlocks + 341
23 CoreFoundation 0x000000010819a183 __CFRunLoopRun + 851
24 CoreFoundation 0x0000000108199bc6 CFRunLoopRunSpecific + 470
25 UIKit 0x000000010889f7a2 -[UIApplication _run] + 413
26 UIKit 0x00000001088a2580 UIApplicationMain + 1282
27 InfanTree 0x00000001079d19d3 main + 115
28 libdyld.dylib 0x000000010aa60145 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Whole code is here
Below is part of my code.
#interface ViewController ()<UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout>
{
DataModel *_data;
// save the indexPath value itself of the picture which is selected at specific index path
NSMutableArray *_displayedImageIndexPathHistory;
// save 1 for the first rendering so next time can avoid to be selected
NSMutableArray *_isSelectedBefore;
// save 1 if rendered at least once so can avoid duplication
NSMutableArray *_preventDuplication;
}
#end
#implementation ViewController
.
.
.
- (void)viewDidLoad {
[super viewDidLoad];
.
.
.
// _data.imageSet is a two dimensional 'MUTABLE' array which has 'MUTABLE' arrays in it.
// Declared in a Model class. Each element has NSString *imageName.png.
_preventDuplication = [_data.imageSet mutableCopy];
_displayedImageIndexPathHistory = [_data.imageSet mutableCopy];
_isSelectedBefore = [_data.imageSet mutableCopy];
// set all arrays with 0
NSInteger sectionNum = [_data.imageSet count];
NSNumber *defaultNumber = [NSNumber numberWithInt:0];
for (NSInteger i = 0; i < sectionNum; i++) {
for (NSInteger j = 0; j < [_data.imageSet[i] count]; j++) {
[_displayedImageIndexPathHistory[i] replaceObjectAtIndex:j withObject:defaultNumber];
[_isSelectedBefore[i] replaceObjectAtIndex:j withObject:defaultNumber];
[_preventDuplication[i] replaceObjectAtIndex:j withObject:defaultNumber];
}
}
.
.
.
}
.
.
.
-(UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
CollectionViewCell *cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
NSNumber *defaultNumber = [NSNumber numberWithInt:0];
NSNumber *markingNumber = [NSNumber numberWithInt:1];
if (indexPath.row == 0) {
cell.cellImageView.image = [UIImage imageNamed:[_data.imageSet[indexPath.section] objectAtIndex:indexPath.row]];
// **Have error at this sentence!!**
[_preventDuplication[indexPath.section] replaceObjectAtIndex:indexPath.row withObject: markingNumber];
}
else {
.
.
.
}
.
.
return cell;
}
Thanks in advance.
Your code has the expression:
[UIImage imageNamed:[_data.imageSet[indexPath.section] objectAtIndex:indexPath.row]]
It would seem that this part:
[_data.imageSet[indexPath.section] objectAtIndex:indexPath.row]
Is producing an instance of NSNumber, not an instance of NSString. Of course, +[UIImage imageNamed:] requires its argument to be a string. It's apparently invoking -length on it. Since NSNumber doesn't respond to -length, you get that exception and crash.

xcode - unrecognized selector sent to instance

I called method in another class (they are both singletons).
WebserviceHelper.h
#interface WebserviceHelper : NSObject {
int currentType;
NSString *SERVER_URL;
WebserviceManager *webService;
}
#property (nonatomic, assign) id delegate;
- (void)retrieveStudentwithCode:(NSString *)code {
currentType = STUDENT_TYPE;
NSString *param = [NSString stringWithFormat:#"token=uencom&cid=%#", code];
NSString *link = [NSString stringWithFormat:#"%#getStudentInfo", SERVER_URL];
[webService retrieveData:link withParameters:param];
}
After call webservice and get data it cached here in received data. I check and it works fine
but when it deliver to didFinishLoading error happen here
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)receivedData {
data = [NSMutableData new];
[data appendData:receivedData];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[self stopPostingToWebservice];
//it carsh here
[delegate: data];
}
Call stack:
2014-08-20 10:39:05.187 School-Link[1030:60b] -[WebserviceHelper :]: unrecognized selector sent to instance 0xa88a420
2014-08-20 10:39:05.188 School-Link[1030:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[WebserviceHelper :]: unrecognized selector sent to instance 0xa88a420'
*** First throw call stack:
(
0 CoreFoundation 0x01bf31e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x018f08e5 objc_exception_throw + 44
2 CoreFoundation 0x01c90243 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
3 CoreFoundation 0x01be350b ___forwarding___ + 1019
4 CoreFoundation 0x01be30ee _CF_forwarding_prep_0 + 14
5 School-Link 0x00030c82 -[WebserviceManager connectionDidFinishLoading:] + 242
6 Foundation 0x016b9e49 ___NSURLConnectionDidFinishLoading_block_invoke + 40
7 Foundation 0x016507e1 __65-[NSURLConnectionInternal _withConnectionAndDelegate:onlyActive:]_block_invoke + 62
8 Foundation 0x014d8f5e -[NSURLConnectionInternalConnection invokeForDelegate:] + 119
9 Foundation 0x014d8ec6 -[NSURLConnectionInternal _withConnectionAndDelegate:onlyActive:] + 208
10 Foundation 0x014d8dd8 -[NSURLConnectionInternal _withActiveConnectionAndDelegate:] + 76
11 Foundation 0x014d9188 _NSURLConnectionDidFinishLoading + 43
12 CFNetwork 0x02a3169f ___ZN27URLConnectionClient_Classic26_delegate_didFinishLoadingEU13block_pointerFvvE_block_invoke + 111
13 CFNetwork 0x02a2f3de ___ZN27URLConnectionClient_Classic18_withDelegateAsyncEPKcU13block_pointerFvP16_CFURLConnectionPK33CFURLConnectionClientCurrent_VMaxE_block_invoke_2 + 104
14 CoreFoundation 0x01b94c69 CFArrayApplyFunction + 57
15 CFNetwork 0x02998441 _ZN19RunloopBlockContext7performEv + 155
16 CFNetwork 0x02a7a3f4 _ZThn16_N19RunloopBlockContext24multiplexerClientPerformEv + 20
17 CFNetwork 0x02998257 _ZN17MultiplexerSource7performEv + 299
18 CFNetwork 0x0299806c _ZN17MultiplexerSource8_performEPv + 76
19 CoreFoundation 0x01b7c77f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
20 CoreFoundation 0x01b7c1d5 __CFRunLoopDoSources0 + 437
21 CoreFoundation 0x01b991ae __CFRunLoopRun + 910
22 CoreFoundation 0x01b989d3 CFRunLoopRunSpecific + 467
23 CoreFoundation 0x01b987eb CFRunLoopRunInMode + 123
24 GraphicsServices 0x0338d5ee GSEventRunModal + 192
25 GraphicsServices 0x0338d42b GSEventRun + 104
26 UIKit 0x005b0f9b UIApplicationMain + 1225
27 School-Link 0x00018f6d main + 141
28 libdyld.dylib 0x03026701 start + 1
29 ??? 0x00000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Try this, have a protocol declaration in WebserviceHelper.h like
#protocol studentDataDelegate <NSObject>
-(void)WebserviceHelper:(WebserviceHelper *)webserviceHelper didStudentDataDownloadCompleteWithData:(NSMutableData *)data;
#end
WebserviceHelper.m
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[self stopPostingToWebservice];
[self.delegate WebserviceHelper:self didStudentDataDownloadCompleteWithData:data];
}
so which ever class confirms to the above protocol should implement the delegate method like,
#interface RequestingDataClass : UIViewController <studentDataDelegate>
by doing this you will receive the warning that you have not implemented didStudentDataDownloadCompleteWithData:method so do it like
-(void)WebserviceHelper:(WebserviceHelper *)webserviceHelper didStudentDataDownloadCompleteWithData:(NSMutableData *)data;
{
webserviceHelper.delegate=self;
// Do something with the `data`
}
You do no show the declaration of the delegate, however this statement:
[delegate: data];
Should be:
[delegate haveSomeData:data];
(or something similar)
did you create protocol in your WebserviceHelper.h file like this?
#protocol WebserviceHelperDelegate <NSObject>
#required
-(void)reciveData:(NSData *)data;//or your method
#end
decleare a property
#property (nonatomic,strong) id <WebserviceHelperDelegate> delegate;
then call this method like
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[self stopPostingToWebservice];
//it carsh here
[self.delegate reciveData: data];
}
And implement this method from where you call webservice class and assign delegate
-(void)reciveData:(NSData *)data{
}

Replace values inside NSMutableDicitionary that sits inside a NSMutableArray

I have an NSMutableArray that I have build up that consists or holds a NSMutableDictionary.
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
self.userNameArray = [NSMutableArray arrayWithArray:[userDefaults arrayForKey:#"userNameTextArray"]];
NSMutableArray *arrayToAdd = [[NSMutableArray alloc] init];
for (id object in self.userNameArray) {
[arrayToAdd addObject:#"Negative"];
}
self.namesDictionary = [#{ #"userNameText" : self.categoriesMutableNameArray, #"selectedCellState" : arrayToAdd}mutableCopy];
self.namesFinalArr = [[NSMutableArray alloc] init];
self.namesDictMutableDict = [NSMutableDictionary dictionaryWithDictionary:self.namesDictionary];
[self.namesFinalArr addObject:self.namesDictMutableDict];
The result in my NSlog of the above code is like this:
(
{
selectedCellState = (
Negative,
Negative,
Negative,
Negative,
Negative,
Negative,
Negative,
Negative,
Negative,
Negative,
Negative,
Negative,
Negative,
Negative
);
userNameText = (
"userText - Text",
"userText1 - Text1",
"userText2 - Text2",
"userText3 - Text3",
"userText4 - Text4",
"userText5 - Text5",
"userText6 - Text6",
"userText7 - Text7",
"userText8 - Text8",
"userText9 - Text9",
"userText10 - Text10",
"userText11 - Text11",
"userText12 - Text12",
"userText13 - Text13"
);
}
)
I am using a UITableview and I populate the UITableview with self.namesFinalArr . in the CellForRow method like this and it works:
labelForTableCell.text = [[[self.namesFinalArr objectAtIndex:0] objectForKey:#"userNameText"]objectAtIndex:indexPath.row];
This populates my UITableview with the data under userNameText in self.namesFinalArr
I am trying to enable or disable an image on a cell when it is selected and I use the didDeselectRowAtIndexPath and didselectRowAtIndexPath methods to show and hide a UImageview
This works but I am trying to update selectedCellState in self.namesFinalArr at the index row or row that was pressed but I get the following error.
In the didselectRowAtIndexPath method I do something like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedRows = [self.tableView indexPathsForSelectedRows];
[[[[self.namesFinalArr objectAtIndex:0] objectForKey:#"selectedCellState"]objectAtIndex:indexPath.row] setValue:#"Positive" forKey:#"selectedCellState"];
}
When trying to change the array value and index row I get a error:
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFConstantString 0x23fef0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key selectedCellState.'
*** First throw call stack:
(
0 CoreFoundation 0x020c75e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x01e4a8b6 objc_exception_throw + 44
2 CoreFoundation 0x021576a1 -[NSException raise] + 17
3 Foundation 0x0075d9ee -[NSObject(NSKeyValueCoding) setValue:forUndefinedKey:] + 282
4 Foundation 0x006c9cfb _NSSetUsingKeyValueSetter + 88
5 Foundation 0x006c9253 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 267
6 Piccing 0x0004880c -[PiccImageCategoriesViewController tableView:didSelectRowAtIndexPath:] + 828
7 UIKit 0x010a77b1 -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 1513
8 UIKit 0x010a7924 -[UITableView _userSelectRowAtPendingSelectionIndexPath:] + 279
9 UIKit 0x010ab908 __38-[UITableView touchesEnded:withEvent:]_block_invoke + 43
10 UIKit 0x00fe2183 ___afterCACommitHandler_block_invoke + 15
11 UIKit 0x00fe212e _applyBlockToCFArrayCopiedToStack + 403
12 UIKit 0x00fe1f5a _afterCACommitHandler + 532
13 CoreFoundation 0x0208f4ce __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
14 CoreFoundation 0x0208f41f __CFRunLoopDoObservers + 399
15 CoreFoundation 0x0206d344 __CFRunLoopRun + 1076
16 CoreFoundation 0x0206cac3 CFRunLoopRunSpecific + 467
17 CoreFoundation 0x0206c8db CFRunLoopRunInMode + 123
18 GraphicsServices 0x027779e2 GSEventRunModal + 192
19 GraphicsServices 0x02777809 GSEventRun + 104
20 UIKit 0x00fc5d3b UIApplicationMain + 1225
21 Piccing 0x000138cd main + 141
22 libdyld.dylib 0x02f4d70d start + 1
23 ??? 0x00000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
In this case,there is one array which contains two dictionary each contains array and you are suppose to change the values in array and you should used this method to change the value
[[[self.namesFinalArr objectAtIndex:0] objectForKey:#"selectedCellState"] replaceObjectAtIndex:indexPath.row withObject:#"Positive"];

Resources