JSONModel - Key is a number, can I get the children by offset? - objective-c

How do I parse this JSON in Objective C? I've been using jsonmodel.com's code to parse.
{
"found":10958,
"start":3141,
"hits":[
{
"pid":"76493",
"title":"Beton Armu00e9",
"artist":"Raiden",
"genre":"Dubstep",
"image":"A76493_BetonArm_BetonArm.jpg",
"label":"Offkey",
"year":"2011",
"price":9.99,
"release":"Beton Armu00e9",
"type":"Album",
"tracks":{
"0":{
"name":"Barbican",
"file":"A76481_Barbican.mp3",
"tracknum":1,
"pid":"76481"
},
"1":{
"name":"Trinity",
"file":"A76482_Trinity.mp3",
"tracknum":2,
"pid":"76482"
},
"2":{
"name":"Tricorn",
"file":"A76483_Tricorn.mp3",
"tracknum":3,
"pid":"76483"
},
"3":{
"name":"Brutalist",
"file":"A76484_Brutalist.mp3",
"tracknum":4,
"pid":"76484"
},
"4":{
"name":"Trellick",
"file":"A76485_Trellick.mp3",
"tracknum":5,
"pid":"76485"
}
}
}
]
}
JSONModel expects a pointer string to declare the keys, but the keys here are numbers. This is what I need, but won't work:
#import "JSONModel.h"
#import "songParentModel.h"
#protocol albumModel #end
#interface albumModel : JSONModel
#property (strong,nonatomic) NSString *title;
#property (strong,nonatomic) NSString *image;
#property (strong,nonatomic) NSString *artist;
#property (strong,nonatomic) songParentModel *0; // THIS DOESN'T WORK (of course)
#end
I just need to get the first track, but it would be nice to know how to get them all.
My best guess for a solution would be to stop using JSONModel and parse the JSON with some other simplified method.

Create a class like this :
The header:
#import "JSONModel.h"
#protocol Track #end
#interface Track : JSONModel
#property (strong, nonatomic) NSString* name;
#property (assign, nonatomic) NSString* file;
#property (assign, nonatomic) int tracknum;
#property (strong, nonatomic) int pid;
#end
Leave the implementation as default.
now in your model add this property:
#property (strong, nonatomic) NSArray<Track>* allTracks;
And also change the implementation for +(JSONKeyMapper*)keyMapper and add the below item to your dictionary.
+(JSONKeyMapper*)keyMapper
{
return [[JSONKeyMapper alloc] initWithDictionary:#{
#"tracks":#"allTracks",
}];
}
In this way you get an array of all the tracks and you can also get all the details for each track as well.

Related

Why the code does not work to avoid Circular References?

I am compiling code to avoid Retain Cycle, When I use weak , I got this error: 1. property of weak attribute must be of object type; 2. Unknown type name 'OrderEntry'. What is wrong with the code? Thanks!
// OrderEntry.h
#import <Foundation/Foundation.h>
#import "OrderItem.h"
#import "Address.h"
#interface OrderEntry : NSObject
#property (strong, nonatomic)OrderItem *orderItem;
#property (strong, nonatomic)Address *shippingAddress;
#property (strong, nonatomic) NSString *orderID;
#end
// OrderItem.h
#import <Foundation/Foundation.h>
#import "OrderEntry.h"
#interface OrderItem : NSObject
#property (strong,nonatomic) NSString *name;
#property (weak, nonatomic) OrderEntry *entry;
#end
The problem is with both .h files each including the other. This causes a circular dependency on the declarations. The simple solution is to use forward declarations instead.
OrderEntry.h:
#import <Foundation/Foundation.h>
#import "Address.h"
#class OrderItem;
#interface OrderEntry : NSObject
#property (strong, nonatomic) OrderItem *orderItem;
#property (strong, nonatomic) Address *shippingAddress;
#property (strong, nonatomic) NSString *orderID;
#end
OrderItem.h:
#import <Foundation/Foundation.h>
#class OrderEntry;
#interface OrderItem : NSObject
#property (strong, nonatomic) NSString *name;
#property (weak, nonatomic) OrderEntry *entry;
#end
Then you import the .h files in the .m file.
The general guideline is to import the fewest possible .h files in another .h file. Use forward declarations for classes and protocols whenever possible.

property not found on object of type error but property is there

So I'm trying to access the property isPortClosed(BOOL) in SerialPortController and its giving me an error, I'm kinda new to objective-c. I feel like this should work as I've got a reference to the class with *port. Here is a link to the project.
Error messages: ~/GroundStation/GroundStation/ViewController.m:16:22: Property 'isPortClosed' not found on object of type 'SerialPortController *'
#import <Cocoa/Cocoa.h>
#import "SceneView.h"
#import "SerialPortController.h"
#interface ViewController : NSViewController
#property (strong) IBOutlet SerialPortController *port;
#property (weak) IBOutlet SceneView *accelSceneView;
#end
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
while(!self.port.isPortClosed) {
}
}
- (void)setRepresentedObject:(id)representedObject {
[super setRepresentedObject:representedObject];
// Update the view, if already loaded.
}
#end
SerialPortController.h class
#import <Foundation/Foundation.h>
#import <ORSSerial/ORSSerial.h>
#interface SerialPortController : NSObject <ORSSerialPortDelegate>
#property (nonatomic, strong) ORSSerialPort *serial;
#property (nonatomic, strong) ORSSerialPortManager *serialPortManager;
#property (nonatomic) NSInteger xAngle;
#property (nonatomic) NSInteger yAngle;
#property (nonatomic) NSInteger zAngle;
#property (nonatomic) NSString *stringBuffer;
#property (nonatomic) BOOL isPortClosed;
#end
From the downloaded project I see that you have two SerialPortController class definitions (one at the root directory, and one in /GroundStation/), and the latter doesn't have any public properties. You should have only one SerialPortController class definition linked in your project (the one with the public properties).

How can I cast my NSURLSessionDownloadTask to my custom NSURLSessionDownloadTask (inheritance)?

I have created a custom NSURLSessionDownloadTask named VJSessionTask and I have just added some custom things like a type (enum) and a custom object (id):
#interface VJSessionTask : NSURLSessionDownloadTask
typedef enum types
{
LS, LSH, DL, UL, RM, TH
} type;
#property enum types type;
#property (strong, nonatomic) id customObject;
#property (strong, nonatomic) NSString *progressNotif;
#property (strong, nonatomic) NSString *doneNotif;
#property (strong, nonatomic) NSURL *tmpFile;
#end
And when I do this:
VJSessionTask *taskSession = (VJSessionTask *)[self.prioritySession downloadTaskWithRequest:listFileRequest];
// init taskSession with its type
taskSession.type = LS;
I get this error:
-[__NSCFLocalDownloadTask setType:]: unrecognized selector sent to instance 0x1556198f0
Then I come to you as I don't understand or I don't know how to do that...
Thank you in advance ;)
NSURLSessionTasks are not strictly speaking subclass-able unfortunately. This is evident in that the system can queue a data task and return a NSCFLocalDownloadTask (presumably meaning that the task will return its content from the cache).
The best way to go about doing this is to borrow on from the architectural decision of AFNetworking and have individual taskDelegates that monitor all the responses an individual task works on. Then when you want to find the data relating to a task you can query your dictionary of taskDelegates. Each task has a unique identifier that you can use to key your dictionary with.
In AFNetworking you can see the taskDelegate is defined as follows:
#interface AFURLSessionManagerTaskDelegate : NSObject <NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate>
#property (nonatomic, weak) AFURLSessionManager *manager;
#property (nonatomic, strong) NSMutableData *mutableData;
#property (nonatomic, strong) NSProgress *progress;
#property (nonatomic, copy) NSURL *downloadFileURL;
#property (nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading;
#property (nonatomic, copy) AFURLSessionTaskCompletionHandler completionHandler;
#end
#implementation AFURLSessionManagerTaskDelegate
and subsequently retrieved as follows:
- (AFURLSessionManagerTaskDelegate *)delegateForTask:(NSURLSessionTask *)task {
NSParameterAssert(task);
AFURLSessionManagerTaskDelegate *delegate = nil;
[self.lock lock];
delegate = self.mutableTaskDelegatesKeyedByTaskIdentifier[#(task.taskIdentifier)];
[self.lock unlock];
return delegate;
}
See this post for more info

JSONModel: can't assign fetched JSON to model

My JSON I fetch:
{"username":"example","confirmed_rewards":"5","round_estimate":"0.73605946","total_hashrate":"0","payout_history":"10","round_shares":"85",
"workers":{
"worker.1":{"alive":"0","hashrate":"0"},
"worker.2":{"alive":"0","hashrate":"0"}
}
}
My model:
#import "JSONModel.h"
#protocol LKCoinFCPoolModel #end
#interface LKCoinFCPoolModel : JSONModel
#property (strong, nonatomic) NSString* username;
#property (strong, nonatomic) NSString* confirmed_rewards;
#property (strong, nonatomic) NSString* round_estimate;
#property (strong, nonatomic) NSString* total_hashrate;
#property (strong, nonatomic) NSString* payout_history;
#property (strong, nonatomic) NSString* round_shares;
#property (strong, nonatomic) NSString<Optional> * ErrorCode;
#end
I created the following function which is to fetch a JSON structure and assign it to a model.
-(void)viewDidAppear:(BOOL)animated
{
//show loader view
[HUD showUIBlockingIndicatorWithText:#"Fetching JSON"];
//fetch the feed
LKCoinFCPoolModel* test;
test = [[LKCoinFCPoolModel alloc] initFromURLWithString:#"http://example.com/ap/key"
completion:^(LKCoinFCPoolModel *model, JSONModelError *err) {
//hide the loader view
[HUD hideUIBlockingIndicator];
//json fetched
NSLog(#"user: %#", test.username);
}];}
the problem I'm having is that instead of user: example it prints user: (null).
I'm unsure what I'm doing wrong, it's the first app I'm trying to write in xcode (I'm coming from a Python/Java background).
Your callback is passing the the parsed JSON to you in the LKCoinFCPoolModel *model. In fact I don't think that you can assign test the way you do. If you really wanted to get it into the test model, you should assign it inside the block. Remember that this block runs asynchronous after the JSON is downloaded and parsed. So test won't be valid until then.

Getter for NSInteger not working

So I have a class with a NSInteger in it and now I want to return the NSInteger value. For some kind of reason, the code for that is not working. I have already declared the #property for the NSInteger class.
#property (readwrite, assign, nonatomic) NSInteger numberFun;
- (NSInteger)sampleMethod {
...
return sample.numberFun;
}
The compiler says "Return from pointer without a cast". I'm pretty sure that means that I'm using a C type for an objective-c method. I want to know the work around for this. (Though I don't want it to return a casted NSInteger as a NSNumber).
Thanks
The following code sample compiles fine. I suggest you present a more complete example of your problem so we can figure out what you are doing wrong.
#interface MyObject : NSObject
{ }
#property (readwrite, assign, nonatomic) NSInteger numberFun;
#end
#implementation MyObject
#synthesize numberFun;
#end
#interface MyObject2 : NSObject
{ }
#property (nonatomic, copy) MyObject* sample;
#end
#implementation MyObject2
#synthesize sample;
- (NSInteger)sampleMethod { return sample.numberFun; }
#end