the question is simple but I saw the implementation is fairly awkward!!
I want to post an object e.g. Device object to web api web service
// Initialize Client
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:#"http://rezawebapi.com"]];
//Indicationg this device is online and sending its dEVICE token to the server
Device *device = [Device new];
device.DeviceToken = [[NSUserDefaults standardUserDefaults] objectForKey:#"devicetoken"];
device.IsOnline = #"True";
//updating current active users of this app in the server
NSDictionary *dictionary = [[NSDictionary alloc]initWithObjectsAndKeys:
device.DeviceToken,#"DeviceToken",
device.IsOnline,#"IsOnline",
nil];
client.parameterEncoding = AFJSONParameterEncoding;
[client postPath:#"/api/iosAppstats" parameters:dictionary success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"%#", responseObject);
// it crashes on the next line because responseObject is NSData
}failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"%#", error.localizedDescription);
}];
1- is there anyway to send the object without creating an dictionary ?(it is error prone!)
2- when my deviceToken is null the object which it sends to the server is null. but consider here one property deviceToken is null but other properties have their own values! does anyone have any idea?
3- I have defined #property (assign, nonatomic) BOOL IsOnline; but when It creates the dictionary EXEX-BAD-ACCESS rises! how should I define bool value? (I had to define it as NSString. it is not an approved way)
1.
is there anyway to send the object without creating an dictionary ?(it is error prone!)
Your API takes JSON. JSON is just dictionaries, arrays, strings, and numbers. So, no. However, it is not error-prone. Just make sure to only put JSON-compliant objects in your dictionary. Read the NSJSONSerialization Overview for more info.
2.
when my deviceToken is null the object which it sends to the server is null. but consider here one property deviceToken is null but other properties have their own values! does anyone have any idea?
You could add deviceToken conditionally, like so:
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
NSString *deviceToken = [[NSUserDefaults standardUserDefaults] objectForKey:#"devicetoken"];
if (deviceToken) {
[dictionary setObject:deviceToken forKey:#"DeviceToken"];
}
3.
I have defined #property (assign, nonatomic) BOOL IsOnline; but when It creates the dictionary EXEX-BAD-ACCESS rises! how should I define bool value? (I had to define it as NSString. it is not an approved way)
Using a BOOL violates this rule from the NSJSONSerialization overview I linked to in #1:
All objects are instances of NSString, NSNumber, NSArray, NSDictionary, or NSNull.
So if your property is a BOOL or other simple numerical type, wrap it in #() to make it an NSNumber:
[dictionary setObject:#(device.IsOnline) forKey:#"DeviceToken"];
This is the same as:
NSNumber *isOnlineNum = [NSNumber numberWithBool:device.isOnline];
[dictionary setObject:isOnlineNum forKey:#"DeviceToken"];
Related
I use setObject:forKey: to add an object of type Rresource to a NSMutableDictionary named: resourceLib.
Then I immediately look at what's actually in the dictionary and it's OK.
When I try to look at it again in another object's method, the proper key is present but a reference to a string property "url" cases a list of error messages including:
2016-09-28 11:32:42.636 testa[760:16697] -[__NSCFString url]: unrecognized selector sent to instance 0x600000456350
Rresource object is defined as:
#interface Rresource : NSObject
#property (nonatomic,strong) NSString* url;
#property (nonatomic,strong)NSMutableArray* resourceNotesArray;
#property(nonatomic,strong)NSString* name;
#property(nonatomic,strong)NSString* resourceUniqueID;
#property(nonatomic)BOOL isResourceDirty;
This method in a ViewController adds the Rresource to the NSMutableDictionary
-(void)saveResource
{
Rresource* resource = self.currentResource;
Rresource* temp;
if (resource)
{
if ( resource.isResourceDirty)
{
[self.model.resourceLib setObject:resource forKey:resource.resourceUniqueID];
temp = [self.model.resourceLib objectForKey:resource.resourceUniqueID];
}
}
}
Resource and temp contain identical info showing the info was added correctly.
In model's method the following causes the error message described above.
for (Rresource* resource in self.resourceLib)
{
NSString* string = resource.url;
}
where model contains:
#property(nonatomic,strong)NSMutableDictionary* resourceLib;
and :
#implementation Model
- (instancetype)init
{
self = [super init];
if (self)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
self.path = [[paths objectAtIndex:0] stringByAppendingString:#"/Application Support/E2"];
BOOL exists = [[NSFileManager defaultManager] createDirectoryAtPath:self.path withIntermediateDirectories:NO attributes:nil error:nil];
if (!exists)
{
[[NSFileManager defaultManager] createDirectoryAtPath:self.path withIntermediateDirectories:NO attributes:nil error:nil];
}
self.resourceLibPath = [NSString pathWithComponents:#[self.path,#"resources"]];
self.resourceLib = [[NSMutableDictionary alloc]init];
self.noteLibPath = [NSString pathWithComponents:#[self.path, #"notes"]];
self.noteLib = [[NSMutableDictionary alloc]init];
}
return self;
I have found this question difficult to ask clearly even after spending several hours formulating it. I apologize.
I've tried pretty much everything for about a week. I'm stumped.
Any ideas?
Thanks
According to this entry on Enumeration, when you iterate over a dictionary using the fast enumeration syntax, you're iterating over its keys. In the above code sample you're assuming the enumeration happens over its values. What you're effectively doing is casting an NSString object as an Rresource, and sending it a selector only an actual Rresource object can respond to.
This should fix the loop:
for (NSString* key in self.resourceLib)
{
NSString* string = [self.resourceLib objectForKey:key].url;
}
In my OS X app, I'm trying to save and retrieve the tag of a radio button. The error occurs on the line marked "<-HERE" in setPreferenceRotor. There is a valid tag coming in.
// PreferenceController.h
extern NSString * const myCellKey;
extern NSString * const myMatrixChangedNotification;
#interface PreferenceController:NSWindowController
{
IBOutlet NSMatrix *matrixRotor;
}
- (IBAction)setRotorTag:(id)sender;
+ (NSInteger)preferenceRotorTag;
+ (void)setPreferenceRotor:(NSInteger)matrixTag;
#end
// PreferenceController.m
NSString * const myMatrixChangedNotification = #"myRotorChanged";
#implementation PreferenceController
- (void)windowDidLoad
{
[super windowDidLoad];
[matrixRotor selectCellWithTag:[PreferenceController preferenceRotorTag]];
}
+ (NSInteger)preferenceRotorTag
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *tagAsData = [defaults objectForKey:myCellKey];
return [NSKeyedUnarchiver unarchiveObjectWithData:tagAsData];
}
+ (void)setPreferenceRotor:(NSInteger)matrixTag
{
//NSInteger mt = matrixTag;
NSData *tagAsData = [NSKeyedArchiver archivedDataWithRootObject:matrixTag]; **//<-HERE**
[[NSUserDefaults standardUserDefaults]setObject:tagAsData forKey:myCellKey];
}
You are passing a primitive (non-object) value, of type NSInteger from variable matrixTag, to a method, archivedDataWithRootObject:, which expects an object reference value. That method happily tries to use the value (which is probably the integer 16, 0x10) as an object reference, and kaboom...
Your thinking looks correct, you know you cannot store non-object values in user defaults, and so you must wrap them as objects first. It is just your way of doing so that is wrong. What you need here is to create an instance of NSNumber from your integer. You could write:
NSNumber *tagAsNumber = [NSNumber numberWithInteger:matrixTag];
[[NSUserDefaults standardUserDefaults] setObject:tagAsNumber forKey:myCellKey];
However this pattern is common enough that a shortcut is provided:
[[NSUserDefaults standardUserDefaults] setInteger:matrixTag forKey:myCellKey];
and this will create the NSNumber object for you. There is also a corresponding integerForKey: method which will unwrap the integer for you when reading.
I've been through the available documentation including https://github.com/RestKit/RestKit/wiki/Object-mapping and I haven't been able to find an explanation or examples to map GET results in
(void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects
What exactly is (NSArray*)objects ?
When I returned just one JSON object from the server I was able to map it with :
NSString *bodyResults;
bodyResults = [[objectLoader response] bodyAsString];
NSDictionary *resultsDictionary = [bodyResults objectFromJSONString];
NSString *subject = [resultsDictionary objectForKey:#"subject"];
But now that i'm returning a JSON list (a selection of objects) I'm having trouble.
I'm mapped the object before submitting the get:
//map offering
RKObjectMapping* offeringMapping = [RKObjectMapping mappingForClass:[Offering class]];
[offeringMapping mapKeyPath:#"categoryId" toAttribute:#"categoryId"];
[offeringMapping mapKeyPath:#"merchantId" toAttribute:#"merchantId"];
[offeringMapping mapKeyPath:#"name" toAttribute:#"name"];
[offeringMapping mapKeyPath:#"latitude" toAttribute:#"latitude"];
[offeringMapping mapKeyPath:#"longitude" toAttribute:#"longitude"];
[[RKObjectManager sharedManager].mappingProvider setMapping:offeringMapping forKeyPath:#"offering"];
double latitude = [(AppDelegate*)[[UIApplication sharedApplication] delegate] currentLatitude];
double longitude = [(AppDelegate*)[[UIApplication sharedApplication] delegate] currentLongitude];
NSString *latitudeString = [[NSNumber numberWithDouble:latitude] stringValue];
NSString *longitudeString = [[NSNumber numberWithDouble:longitude] stringValue];
NSDictionary *getParams = [NSDictionary dictionaryWithKeysAndObjects:
#"lat",latitudeString,
#"long",longitudeString,
nil];
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:[#"/merchantofferings" stringByAppendingQueryParameters:getParams] delegate:self];
Thanks
In response to your first question, (NSArray *)objects is an array of the objects that were loaded by the objectLoader. So in your case, they should be objects of type Offering populated with the attributes that you mapped in the object mapping.
Do you have a sample of the JSON that you're returning from the GET request that you can post here? Are you sure that it's valid JSON and is being returned exactly as you anticipate?
I'm new into Cocoa and am writing a simple app to learn working with Core Data, but it crashes with EXC_BAD_ACCESS. Tried several things and haven't find the solution yet. As I said, I'm not very experienced in Cocoa.
I have followed the usual Core Data tutorials.
This is my Model:
I've added these two entities as NSArrayController in my Nib file and have two NSTableViews with Value Binding to the entity objects.
And here's the code:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSManagedObjectContext *context = [self managedObjectContext];
TaskList *list = [NSEntityDescription
insertNewObjectForEntityForName:#"TaskList"
inManagedObjectContext: context]; // EXC_BAD_ACCESS happens here
[list setTitle:#"Inbox"];
Task *task = [NSEntityDescription
insertNewObjectForEntityForName:#"Task"
inManagedObjectContext: context];
[task setKey:#"Remember the milk"];
[task setList:list];
NSError *error;
if (![context save:&error]) {
NSLog(#"Error: %#", [error localizedDescription]);
}
}
That's it! That's all my program. I am using Xcode 4.2, developing a Mac app, and ARC is enabled.
UPDATE: jrturton asked me to include implementation of [self managedObjectContext]. I didn't write this code, but here's what I found in AppDelegate.h:
#property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
And this is from AppDelegate.m:
#synthesize managedObjectContext = __managedObjectContext;
...
/**
Returns the managed object context for the application (which is already
bound to the persistent store coordinator for the application.)
*/
- (NSManagedObjectContext *)managedObjectContext {
if (__managedObjectContext) {
return __managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (!coordinator) {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setValue:#"Failed to initialize the store" forKey:NSLocalizedDescriptionKey];
[dict setValue:#"There was an error building up the data file." forKey:NSLocalizedFailureReasonErrorKey];
NSError *error = [NSError errorWithDomain:#"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
[[NSApplication sharedApplication] presentError:error];
return nil;
}
__managedObjectContext = [[NSManagedObjectContext alloc] init];
[__managedObjectContext setPersistentStoreCoordinator:coordinator];
return __managedObjectContext;
}
Check your managed object model. Make sure all the entity and attribute names are spelled correctly. Also check your object class files and make sure they contain what you expect.
Maybe the debugger does not show you the correct row when crashing: I noticed, that you have a method setKey:, but no attribute called keyin your Task entity. Try setting all the attributes with the dot notation, like list.title = #"Inbox". (This is generally easier to read and avoids similar errors.)
As suggested, before the line inserting the new entity, set a breakpoint and make sure the managed object context is not null.
Finally, perhaps you have to cast your object. insertNewObjectForEntityForName: returns an object of type NSManagedObject, but you are assigning it to a type TaskList. Try adding the cast before you use the object:
TaskList *list = (TaksList *) [NSEntityDescription
insertNewObjectForEntityForName:#"TaskList"
inManagedObjectContext: context];
I had this same issue. I resolved it like Mostafa said above. If you create a project with Core Data enabled, it will automatically create a file for you. Use this .xcdatamodeld file instead of a custom one. If you have one already created, just delete the originally created file and rename your datamodel file to the originally created file name.
I have an Editable NSTextView,In which user will write using different font style, on certain action i need to prepare the HTML Formate of it,
Can anyone suggest me, how i can retrieve the data from NSTextView,
I am able to use
[[pInputText textStorage] words];
but it returns NSArray, from which i am not able to get NSMutableString,
Can anyone suggest me the best possible way to retrieve the String/data what user typed and in which format.
Below solutions works for me,
- (NSString *)convertUnderlineTextToHTML:(NSAttributedString *)_mString
{
NSArray * exclude = [NSArray arrayWithObjects:#"doctype", #"html",
#"head", #"body",#"xml",nil];
NSDictionary * htmlAtt = [NSDictionary
dictionaryWithObjectsAndKeys:NSHTMLTextDocumentType,NSDocumentTypeDocumentAttribute,exclude,NSExcludedElementsDocumentAttribute,nil];
NSError * error;
NSData * htmlData = [_mString dataFromRange:NSMakeRange(0, [_mString
length]) documentAttributes:htmlAtt error:&error];
NSString * sdat = [[NSString alloc] initWithData:htmlData
encoding:NSUTF8StringEncoding];
NSLog(sdat);
return sdat;
}
Where _mString is
NSMutableAttributedString *pAttributedString = [pInputText textStorage];
NSString *pHtml = [self convertUnderlineTextToHTML:pAttributedString];
Regards
Rohan
NSTextView inherits from NSText, which has a -string method. So [pInputText string should do what you want.
Alternately, TextStorage is a subclass of NSMutableAttributedString, so if you want an attributed string you can just use the return of [pInputText textStorage] directly.
since NSTextStorage is a subclass of NSMutableAttributedString which has a method through its superclass NSAttributedString :initWithHTML:baseURL:documentAttributes, you can use this to get what you want. documentAttributes can be NULL.