NSMutableData setLength:NSUInteger crashing the app - xcode

Trying to create a connection of a request with an URL. An NSMutableData instance (responseData) also gets called with it. When the connection starts receiving response, the setLength:NSUInteger method gets called up on the NSMutableData Instance.
-(void)startDataDownloading
{
NSURLRequest *_request = [NSURLRequest requestWithURL:self.url];
if (_request) {
if (!connecton) {
connecton = [NSURLConnection connectionWithRequest:_request delegate:self];
if (connecton) {
responseData = [NSMutableData data];
[connecton start];
}
}
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[responseData appendData:data];
}
But somehow it causes a crash with a warning on the setLength call. The error states that
" -[__NSCFDictionary setLength:]: unrecognized selector sent to instance 0x6a8cf70
2012-11-30 18:00:38.948 RSSReader[8997:f803] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary setLength:]: unrecognized selector sent to instance 0x6a8cf70' "
Any hint about this would be appreciated.
#import <Foundation/Foundation.h>
#import "DataParser.h"
#protocol DataConnectionDelegate <NSObject>
//protocol methods
#end
#interface UCDataConnection : NSObject <ModelParser>
#property (nonatomic, strong) NSURL *url;
#property (nonatomic, strong) NSURLConnection *connecton;
#property (strong, nonatomic) NSMutableData *responseData;
#property (nonatomic, assign) id<DataConnectionDelegate> delegate;
-(void)startDataDownloading;
- (id)initWithUrl:(NSURL *)_url andDelegate:(id<DataConnectionDelegate>)_delegate;
That is a part of the header file.Sorry for late response.

Most likely you're not retaining responseData correctly, so it's being released and in your above example you happen to end up getting an NSDictionary allocated in the same place.
If you're using ARC then the code you posted is fine (other than that "responseData" should probably have an underscore prefix, assuming it's an instance variable).
If you're using retain-release, then you need to add a call to retain when you allocate responseData.
Update: Based on your header file it looks like you're referring to the instance variable directly, and using retain-release. Your best option is to refer to responseData only through the property mechanism - i.e. prefix all its uses with self..

I don't know if this is the answer, but what I see suspicious here is that you have a property
#property (strong, nonatomic) NSMutableData *responseData;
and by default it should be accessed with self. responseData;
if you intend to access private ivar you should by default use _responseData.
Unless you said differently in .m file which I would also like to see, so to be sure what's going on (in case this answer won't help).

Related

Cocoa POST issue

I´m newbie with Cocoa. I have one issue when I want to send data to my WS via POST
I have RequestPost program to inherit on all my projects
//
// RequestPost.h
//
// Created by Roberto on 10/01/13.
// Copyright (c) 2013 CEM. All rights reserved.
//
#import <Foundation/Foundation.h>
#protocol DelegadoRedPost <NSObject>
-(void) terminaDescarga:(NSData*)datos conID:(NSInteger) id;
-(void) errorDescarga:(NSInteger)codigo conID:(NSInteger) id;
#end
#interface RequestPost : NSObject <NSURLConnectionDelegate>
#property (strong, nonatomic) NSObject <DelegadoRedPost> *delegado;
#property (nonatomic) NSInteger id;
#property (nonatomic, strong) NSMutableData *buffer;
#property (nonatomic, strong) NSURLConnection *conexion;
-(void)descargar:(NSString*)direccion datosPost:(NSString*)datos conId:(NSInteger)id;
#end
//
// RequestPost.m
//
// Created by Roberto on 10/01/13.
// Copyright (c) 2013 CEM. All rights reserved.
//
#import "RequestPost.h"
#implementation RequestPost
-(void)descargar:(NSString*)direccion datosPost:(NSString*)datos conId:(NSInteger)id
{
self.id = id;
NSURL *url = [NSURL URLWithString:direccion];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
//NSString *strLength = [NSString stringWithFormat:#"%d", datos.length]; aqui comento 18 abr 2016
NSString *strLength = [NSString stringWithFormat:#"%lu", (unsigned long)datos.length];
[req addValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[req addValue:strLength forHTTPHeaderField:#"Content-Length"];
[req setHTTPMethod:#"POST"];
[req setHTTPBody:[datos dataUsingEncoding:NSUTF8StringEncoding]];
self.conexion = [[NSURLConnection alloc] initWithRequest:req delegate:self];
if(self.conexion){
self.buffer = [NSMutableData data];
}
}
#pragma mark - Métodos del Delegado de NSURLConnection
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
self.buffer.length = 0;
}
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[self.buffer appendData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
[self.delegado terminaDescarga:self.buffer conID:self.id];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
[self.delegado errorDescarga:error.code conID:self.id];
}
#end
Now, when I want to inherit last files I have gotten an error .... Incompatible pointer types assigning to NSObject ... In the line request.delegado = self;
This is the code when inherit
-(void) request
{
RequestPost *request = [[RequestPost alloc] init];
request.delegado = self;
NSString *postStr = [NSString stringWithFormat:#"datos=%#",self.json];
NSString *strUrl = #"http://www.futho7.com/WebService/subir_datos.php";
[request descargar:strUrl datosPost:postStr conId:100];
}
How can I fix it?
Thanks & Regards
In the .m file that contains the request method, you need to indicate that the class conforms to the DelegadoRedPost protocol and implement the required protocol methods.
Add this just before the #implementation line:
#interface WhateverClassNameThisIs () <DelegadoRedPost>
#end
Obviously replace WhateverClassNameThisIs with the actual name of this class.
As a side note, you should change the declaration of the delegado property from:
#property (strong, nonatomic) NSObject <DelegadoRedPost> *delegado;
to:
#property (weak, nonatomic) id<DelegadoRedPost> *delegado;
Note the two changes - delegates should normally be weak, not strong. This avoids reference cycles. And the type should be with id, not NSObject. The protocol itself extends the NSObject protocol.

one to many relationship not working (Restkit 0.20) addRelationshipMappingWithSourceKeyPath

I have a simpe one to many relationshipim my JSON and would like to map this into Objects (NOT Core Data entities). Mapping the poducts is working fine. But every product has an array of tracks that is not mapped.
This is the JSON:
Here is the code:
Product.h
#import <Foundation/Foundation.h>
#interface Product : NSObject
#property (nonatomic, strong) NSString* productid;
#property (nonatomic, strong) NSString* title;
#property (nonatomic, strong) NSString* artist;
//...
#property (nonatomic, strong) NSMutableArray *tracks;
Track.h
#import <Foundation/Foundation.h>
#interface Track : NSObject
#property (nonatomic, strong) NSString *artist;
#property (nonatomic, strong) NSString *title;
#property (nonatomic, strong) NSString *mixversion;
Here the code to request the JSON and map the response to Objects
/// Create Mappers for Product and Track
RKObjectMapping *mappingForProduct = [RKObjectMapping mappingForClass:[Product class]];
[mappingForProduct addAttributeMappingsFromArray:#[#"productid", #"title", #"tracks"]];
RKObjectMapping *mappingForTrack = [RKObjectMapping mappingForClass:[Track class]];
[mappingForTrack addAttributeMappingsFromArray:#[#"artist",#"title",#"mixversion"]];
/// assign relationship product-track
[mappingForProduct addRelationshipMappingWithSourceKeyPath:#"tracks" mapping:mappingForTrack];
/// setup responseDescriptor
NSString *key_path = #"products";
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mappingForProduct
pathPattern:nil
keyPath:key_path
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
/// Create Manager, connect responseDescriptor and execute
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:#"myRequestString"]];
[manager addResponseDescriptor:responseDescriptor];
[manager getObject:nil path:#"" parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)
{
self.productsArray = [NSMutableArray arrayWithArray:mappingResult.array];
}
failure:^(RKObjectRequestOperation *operation, NSError *error)
{
NSLog(#"Error: %#", error);
}
This gives an assertion error:
*** Assertion failure in -[RKObjectMapping addPropertyMapping:], /Users/.../Pods/RestKit/Code/ObjectMapping/RKObjectMapping.m:235
The magic should happen in this line:
[mappingForProduct addRelationshipMappingWithSourceKeyPath:#"tracks" mapping:mappingForTrack];
... but for some reason it doesn't.
I've searched quite some sources on SO and the documentation, tried quite some combinations of keypath changed, but nothing will give the required result. A lots of the availble sample code is regarding older versions of RestKit or deals with Core Data. I just want to get mapped objects, no Core Data entities.
Thanks in advance for any hint.
You're just trying to add a mapping for tracks twice. It should be a relationship mapping, not an attribute mapping. Change the mappingForProduct to:
[mappingForProduct addAttributeMappingsFromArray:#[#"productid", #"title"]];
And the cause of the exception should be removed.

how to store object to NSmutablearray in app delegate?

I'm having a problem with storing and accessing objects with NSmutable array in app delegate. I have tried methods form other websites and stack overlay pages but yet no solution. I want to able to access the array data in another view. Currently nothing is working for me.
Heres my code.
AppDelegate.h :
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
NSMutableArray* sharedArray;
}
#property (nonatomic, retain) NSMutableArray* sharedArray;
ViewController.h :
#import "AppDelegate.h"
-(void)viewDidLoad{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSMutableArray *model = appDelegate.sharedArray;
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:#"hello" forKey:#"title"];
[dict setObject:#"urlhere" forKey:#"thumbnail"];
[model addObject:dict];
NSLog(#"submitted to array: %#",model);
}
Are you, at any point, initializing the sharedArray? The array must be instantiated before you can add objects to it. For example:
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
self.sharedArray = [NSMutableArray array];
return YES;
}
Having done that, now attempts to add objects to this array from your view controllers should succeed.
Unrelated, but you should not define instance variables for your properties. Let the compiler synthesize that for you, e.g.:
AppDelegate.h:
#interface AppDelegate : UIResponder <UIApplicationDelegate>
// {
// NSMutableArray* sharedArray;
// }
#property (nonatomic, retain) NSMutableArray* sharedArray;
#end
What you have is technically acceptable, but it's inadvisable because of possible confusion between this sharedArray instance variable and the what the compiler will synthesize for you (e.g. if you don't have a #synthesize line, the compiler will automatically create an instance variable called _sharedArray, with a leading underscore, for you). Even if you had a #synthesize line that ensured that the instance variable was correct, having the explicitly declared instance variable is simply redundant.

unrecognized selector sent to instance for Paul Hegarty's CS193P

I'm following Paul Hegarty's CS193P course video (lecture #4 # 1:05:40 mark) and ran into problems. Please help debug this 'unrecognized selector sent to instance' error. The view has three objects - see image (https://docs.google.com/file/d/0B453_F6cDmYzMG1OQW93WVptYUU/edit?usp=sharing)
The code
// AttributeViewController.m
// Attribute
#import "AttributeViewController.h"
#interface AttributeViewController ()
#property (weak, nonatomic) IBOutlet UILabel *label; // collection of words
#property (weak, nonatomic) IBOutlet UIStepper *selectedWordStepper; // stepper
#property (weak, nonatomic) IBOutlet UILabel *selectedWordLabel; // selected word from label
#end
#implementation AttributeViewController
- (NSArray *)wordList
{
NSArray *wordList = [[self.label.attributedText string] componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if ([wordList count]) {
return wordList;
} else {
return #[#""];
}
}
- (NSString *)selectedWord
{
return [self wordList][(int)self.selectedWordStepper.value];
}
- (IBAction)updateSelectedWord {
self.selectedWordStepper.maximumValue = [[self wordList] count]-1;
self.selectedWordLabel.text = [self selectedWord];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self updateSelectedWord];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
The error
2013-03-03 18:03:28.948 Attribute[74205:c07] -[AttributeViewController updateSelectedWord:]: unrecognized selector sent to instance 0x71b93a0
2013-03-03 18:03:28.952 Attribute[74205:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[AttributeViewController updateSelectedWord:]: unrecognized selector sent to instance 0x71b93a0'
*** First throw call stack:
(0x1c91012 0x10cee7e 0x1d1c4bd 0x1c80bbc 0x1c8094e 0x10e2705 0x162c0 0x16258 0xd7021 0xd757f 0xd7056 0x42b195 0x42ae91 0xd6696 0x45cef 0x45f02 0x23d4a 0x15698 0x1becdf9 0x1c14f3f 0x1c1496f 0x1c37734 0x1c36f44 0x1c36e1b 0x1beb7e3 0x1beb668 0x12ffc 0x25cd 0x24f5)
libc++abi.dylib: terminate called throwing an exception
(lldb) gdb
I have really not seen direct calls to IBAction methods before. IBAction methods are connected to actions in your View (buttons, etc.) and are triggered when these buttons, etc.. are clicked.
If updateSelectedWord is an internal method, just replace IBAction with void:
(void)updateSelectedWord
Hope this helps.

Having problems adding objects to array

In the code below, I am trying to add objects to array. No error, but is not adding objects either. Sorry for asking this pretty basic question. Need help
The NS Object Definition
//DataDefinition.h
#import
#interface DataDefinition : NSObject
#property (nonatomic, retain) NSString *dataHeader;
#property (nonatomic, retain) NSMutableArray *dataDetails;
#end
The DataDefinition Implementation
#import "DataDefinition.h"
#implementation DataDefinition
#synthesize dataHeader;
#synthesize dataDetails;
#end
The Display header section
//DataDisplay.h
#import
#import "DataDefinition.h"
#interface DataDisplay : UITableViewController
#property (strong, nonatomic) NSMutableArray *dataSet;
#property (strong, atomic) DataDefinition *individualData;
#end
The Display implementation section
//DataDisplay.m
#import "DataDisplay.h"
#interface DataDisplay ()
#end
#implementation DataDisplay
#synthesize dataSet;
#synthesize individualData;
- (void)viewDidLoad
{
[super viewDidLoad];
individualData.dataHeader = #"Header1";
individualData.dataDetails = [[NSMutableArray alloc] initWithObjects:#"Header1-Detail1", #"Header1-Detail2", #"Header1-Detail3", nil];
//This didnot add
[dataSet addObject:individualData];
NSLog(#"Count of objects is %d:",[dataSet count]);
//Nor did this
dataSet = [[NSMutableArray alloc] initWithObjects:individualData, nil];
NSLog(#"Count of objects is %d:",[dataSet count]);
self.title = #"DataDisplay";
}
The issue is that individualData is never actually set to an instantiated object (in other words, it is never initialized).
These kinds of oversights are common due to Objective-C's non-error policy regarding sending messages to nil; it's perfectly legal and often useful principle. This means that your code will never complain until you try to pass it to some method which will crash if it sees nil. Unfortunately, you are using initWithObjects, which simply sees nil as the end of the (empty) list. If you had instead tried to use [NSArray arrayWithObject:individualData] you may have seen an error which would hint to you that you had nil instead of an object.
Note that setting properties on nil is particularly tricky, since it looks like you are simply dealing with a C-syle lvalue, when actually it translates to a message-send call at runtime:
individualData.dataHeader = #"Header1";
// is *literally* the same as:
[individualData setDataHeader:#"Header1"];
You can take your pick of solutions. The "cheap" way is to simply initialize it right there. The "better" way (usually) is lazy-instantiation (i.e. in the getter). Since the object is marked as atomic, you likely need to let the compiler write the getter for you, and just initialize it in viewDidLoad (or awakeFromNib, initWithCoder, or similar):
- (void)viewDidLoad
{
[super viewDidLoad];
self.individualData = [[DataDefinition alloc] init];
...

Resources