First of all, I'm new to objective-c programming so I've probably made some mistakes in my code.
Here's what I've done : I've created a php file with some xml to get values from my MySQL database. Everything goes into a NSArray in objective-C. If I look at the log, everything works fine because it shows my arrays with every MySQL rows and columns like this:
2012-04-02 08:20:14.822 POS[64632:707] (
{
CPU = 0;
TPS = "(null)";
TVQ = "(null)";
consigne = 0;
coutantQuantiteRecue = 0;
description = "";
nom = "";
prixProduit = 0;
quantiteRecue = 0;
stock = 0;
},
{
CPU = 768;
TPS = "(null)";
TVQ = "(null)";
consigne = 0;
coutantQuantiteRecue = 0;
description = "";
nom = hhh;
prixProduit = 0;
quantiteRecue = 0;
stock = 0;
},
2012-04-02 08:20:14.836 POS[64632:707] The number of rows is:2
The problem is that the only thing I get in my TableView is { in each cell like this:
Here's my .h :
#interface InventoryManagement : NSObject<NSApplicationDelegate, NSTableViewDataSource>
{
IBOutlet NSTableView* inventoryTable;
NSArray* m_items;
}
-(int)numberOfRowsInTableView:(NSTableView *)inventoryTable;
-(id)tableView:(NSTableView *)inventoryTable objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)rowIndex;
-(void)dealloc;
#property (retain) NSArray* m_items;
#end
And here's my .m file :
#implementation InventoryManagement
#synthesize m_items;
-(id)init
{
[super init];
NSInteger index = 0;
NSString *urlString = [NSString stringWithFormat:#"http://localhost:8888/php/getProducts.php?index=%d&", index];
m_items = [NSArray arrayWithContentsOfURL:[NSURL URLWithString: urlString]];
NSLog(#"%#", [m_items description]);
[m_items retain];
[inventoryTable reloadData];
return self;
}
-(int)numberOfRowsInTableView:(NSTableView *)inventoryTable
{
NSLog(#"The number of rows in fullResult is:%i", [m_items count]);
return [m_items count];
}
-(id)tableView:(NSTableView *)inventoryTable objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)rowIndex
{
return [m_items objectAtIndex:rowIndex];
}
-(void)dealloc
{
[m_items release];
[super dealloc];
}
#end
My object is well-connected to dataSource and delegate of my TableView. I want those cells to be filled by my database values.
Take a look at Cocoa Bindings for future works. They are great.
Regarding your question: the problem is in the method
-(id)tableView:(NSTableView *)inventoryTable objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)rowIndex
{
return [m_items objectAtIndex:rowIndex];
}
You are returning the whole object, that is:
{
CPU = 768;
TPS = "(null)";
TVQ = "(null)";
consigne = 0;
coutantQuantiteRecue = 0;
description = "";
nom = hhh;
prixProduit = 0;
quantiteRecue = 0;
stock = 0; }
which is a string.
You have to check the tableColumn variable and return only the right information: e.g. quantiteRecue, CPU, etc..
The best way to do this is to create a Model class in ObjectiveC which wraps a row of your db. Then your m_items array will contains your Model class, and you can return the right property without parsing every time the string...
Related
This is my response ... My dictnary name is "msg"
{
Result = {
Data = {
engine = {
service = {
data = (
{
checked = 1;
field = 1;
name = Ettersyn;
},
{
checked = 1;
field = 1;
name = "Med Alpha VP";
},
{
checked = 0;
field = 0;
name = "Med B.IMP.";
}
);
"engine_service_id" = 1;
"engine_service_name" = "4 Cyl";
};
type = {
"engine_id" = 1;
"engine_name" = Benzin;
};
};
tact = {
service = {
data = (
{
checked = 0;
field = 1;
name = "Little ettersyn";
},
{
checked = 0;
field = 1;
name = "Short ettersyn";
}
);
"tact_service_id" = 2;
"tact_service_name" = "21-50 hk";
};
type = {
"tact_id" = 1;
"tact_name" = "2 Takt";
};
};
};
status = success;
};
}
I try to to store the data like this
var arrayMain : NSMutableArray = msg.valueForKey("Result")?.valueForKey("Data") as NSMutableArray
My problem is i got "EXC_BAD_ACCESS" error While running ... Am also check allocation of array ... I try to store it in NSMutableDictionary its work perfectly ... How can i store this response in NSMutableArray ?
If you look carefully at the response data structure you'll see the problem.
This first operation: msg.valueForKey("Result") would return an dictionary with two key/values; a "Data" dictionary, and "Status" string.
Your second operation .valueForKey("Data") would return a dictionary with two key/values; an "Engine and "Tact" dictionary.
Because it's a dictionary, you can create a dictionary from it, which is what you said worked, or you're going to have to rethink how you want to store if if indeed you want it in an array, but you can't create an array directly from a dictionary - they are different data structures.
You cannot assign Dictionary object to Array, that's why it is giving the error.
But you can store that dictionary to array as:
var arrayMain : NSMutableArray = NSMutableArray()
arrayMain.addObject(msg.valueForKey("Result")?.valueForKey("Data"))
my Dictionary output is-
i want to fire insert command to insert this dictionary data to the sqlite database
(
{
iCardReceiverName = rp;
iCardSenderName = madhusudan;
isDeleted = 0;
isReceiverSynk = 0;
},
{
iCardReceiverName = rp;
iCardSenderName = mmmm;
isDeleted = 0;
isReceiverSynk = 0;
}
)
i want to insert this data into sqlite database.
here is my code-
NSDictionary *jsonData = [NSJSONSerialization
JSONObjectWithData:urlData
options:NSJSONReadingMutableContainers
error:&error];
NSMutableString *query = [NSMutableString stringWithFormat:#"Insert into iCardUsers ("];
[self.dbManager executeQuery:query];
if (self.dbManager.affectedRows != 0) {
NSLog(#"Query was executed successfully. Affected rows = %d", self.dbManager.affectedRows);
}
else{
NSLog(#"Could not execute the query.");
}
for (int i = 0; i<[[jsonData allKeys] count]; i++)
{
[query appendFormat:#"%#,",[[jsonData allKeys] objectAtIndex:i]];
}
[query appendFormat:#")values ("];
for (int i = 0; i<[[jsonData allKeys] count]; i++)
{
[query appendFormat:#"%#,",[jsonData valueForKey:[[jsonData allKeys] objectAtIndex:i]]];
}
[query appendFormat:#");"];
NSLog(#"qry : %#",query);
You can insert your data in sqlite db like in following example.
You can create a function with required parameters and insert data using the function.
-(void)InsertRecords:(NSMutableString *)txt{
NSString *dbPath = [[[NSBundle mainBundle] resourcePath ]stringByAppendingPathComponent:#"movieData.sqlite"];
const char *dbpath = [dbPath UTF8String];
sqlite3 *contactDB;
sqlite3_stmt *statement;
NSLog(#"%#",dbPath);
if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat: #"INSERT INTO myMovies (movieName) VALUES (\"%#\")", txt];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(contactDB, insert_stmt, -1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
sqlite3_bind_text(statement, 1, [txt UTF8String], -1, SQLITE_TRANSIENT);
} else {
NSLog(#"error");
}
sqlite3_finalize(statement);
sqlite3_close(contactDB);
}
}
I am new to programming and am trying to make a PageViewController using xib's.
I have followed a tutorial found on SO which showed me how to make a PageViewController using different UIViewControllers in storyboard (I have pasted the code below). This works well, however, for my final app I would like to use a PageViewController in an xib (with multiple different xibs).
#import "IntroPages.h"
#implementation IntroPages
{
NSArray *myViewControllers;
}
-(void)viewDidLoad
{
[super viewDidLoad];
self.delegate = self;
self.dataSource = self;
UIViewController *p1 = [self.storyboard instantiateViewControllerWithIdentifier:#"1ID"];
UIViewController *p2 = [self.storyboard instantiateViewControllerWithIdentifier:#"2ID"];
UIViewController *p3 = [self.storyboard instantiateViewControllerWithIdentifier:#"3ID"];
UIViewController *p4 = [self.storyboard instantiateViewControllerWithIdentifier:#"4ID"];
myViewControllers = #[p1,p2,p3,p4];
[self setViewControllers:#[p1]
direction:UIPageViewControllerNavigationDirectionForward
animated:NO completion:nil];
}
-(UIViewController *)viewControllerAtIndex:(NSUInteger)index
{
return myViewControllers[index];
}
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger currentIndex = [myViewControllers indexOfObject:viewController];
--currentIndex;
currentIndex = currentIndex % (myViewControllers.count);
return [myViewControllers objectAtIndex:currentIndex];
}
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
NSUInteger currentIndex = [myViewControllers indexOfObject:viewController];
++currentIndex;
currentIndex = currentIndex % (myViewControllers.count);
return [myViewControllers objectAtIndex:currentIndex];
}
-(NSInteger)presentationCountForPageViewController: (UIPageViewController *)pageViewController {
return myViewControllers.count;
}
-(NSInteger)presentationIndexForPageViewController: (UIPageViewController *)pageViewController {
return 0;
}
I am trying to map attributes to a class in RESTKit without a nested KVC and without much luck i keep getting nil for my values even though the response contains values.
I have read over the object mapping manual and tried it with path patterns without path patterns etc. Does anyone have any insight?
Request and Response from server
2014-06-16 15:58:07.162 game[5961:60b] T
restkit.network:RKObjectRequestOperation.m:178 POST 'https://api.myURL.com/api/0_0_1/notify/player':
request.headers=
{
Accept = "application/json";
"Accept-Language" = "en;q=1, fr;q=0.9, de;q=0.8, zh-Hans;q=0.7, zh-Hant;q=0.6, ja;q=0.5";
"Content-Type" = "application/json; charset=utf-8";
"User-Agent" = "game/1470 (iPhone; iOS 7.1; Scale/2.00)";
}
request.body=
{
"game":"539e75acadae8fb03900057e",
"to":"533bd7eb5317b88f61000006",
"message":"Ben Fowler is waiting for you to play the game",
"from":"5332b4f5edfc9beb7900004d"
}
2014-06-16 15:58:08.856 game[5961:5607] T restkit.network:RKObjectRequestOperation.m:248 POST 'https://api.myURL.com/api/0_0_1/notify/player' (200 OK / 1 objects) [request=1.6911s mapping=0.0020s total=1.6989s]:
response.headers={
Connection = "keep-alive";
"Content-Length" = 42;
"Content-Type" = "application/json; charset=utf-8";
Date = "Mon, 16 Jun 2014 07:58:09 GMT";
"X-Powered-By" = Express;
}
response.body=
{
"result": 1,
"notify": "871720292"
}
The class being mapped
-(void)WtfGameNotifcationResponse
{
RKObjectMapping *notifyMapping = [RKObjectMapping mappingForClass:[WTFGameNotification class]];
[notifyMapping addAttributeMappingsFromDictionary:
#{
#"result" : #"result",
#"notify" : #"notifyID",
}];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:notifyMapping
method:RKRequestMethodGET
pathPattern:#"notify/player"
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[[RKObjectManager sharedManager] addResponseDescriptor:responseDescriptor];
}
The class in question
#interface WTFGameNotification : NSObject
#property (nonatomic,copy) NSString* to;
#property (nonatomic,copy) NSString* from;
#property (nonatomic,copy) NSString* gameID;
#property (nonatomic,copy) NSString* message;
#property (nonatomic,strong) NSNumber* result;
#property (nonatomic,copy) NSString *notifyID;
+ (WTFGameNotification*)Create;
#end
It seems that if you are trying to map a response from a POST this is the method and syntax one should use.
+ ( void )SendNotification:(GameInfo*)gameInfo withMessage:(NSString*)message forView:(UIViewController*)view
{
WTFGameNotification *_wtfGameNotif = [WTFGameNotification Create];
[_wtfGameNotif setTo:[gameInfo opponentWTFID]];
[_wtfGameNotif setFrom:[PlayerWTFInfo Load]._wtfID];
[_wtfGameNotif setGameID:[gameInfo gameID]];
[_wtfGameNotif setMessage:message];
if ([_wtfGameNotif to] && [_wtfGameNotif gameID])
{
RKObjectRequestOperation *operation = [[RKObjectManager sharedManager] appropriateObjectRequestOperationWithObject:_wtfGameNotif
method:RKRequestMethodPOST
path:nil
parameters:nil];
RFResponse *r1 = [RFResponse new];
operation.targetObject = r1;
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)
{
if (r1.result.integerValue != 0)
{
[Utilities FacebookPostWithResult:#{#"fbId": r1.notify}];
}
}
failure:^(RKObjectRequestOperation *operation, NSError *error)
{
DDLogError(#"POST REQUEST FAILED IN CONFIRMFOTOVC : %#",[error description]);
if (view)
{
[LoadingView PopToRootShutterCloseOnView:view willOpen:YES];
}
}];
[operation start];
}
else
{
DDLogInfo(#"NO PLAYER ID");
}
}
If you are POSTing the object to the server then the response descriptor you have will not match because you link it to a GET with method:RKRequestMethodGET. You need to change that to method:RKRequestMethodPOST.
When using a path pattern of #"notify/player" the base URL should be set to https://api.myURL.com/api/0_0_1/, but it doesn't look like this is an issue for you.
I'm attempting to parse category data from a web store served in JSON Array format via REST into core data on iOS. Before I begin inserting to core data, i'm simply just logging the output to screen and keeping count of the results to check everything is ok.
The Problem In my test data set I have 152 categories, however I am only getting a 'Final counter' of 141 outputted to the log?
I've looked and looked at the recursive function and believe its ok, therefor I think the problem lies somewhere in the findSubcategoriesForCategoryID function?
Any feedback on the problem would be most grateful as this has kept me up for hours now.
Example JSON data returned from Web Service:
Node: {
categoryID = 259;
categoryTitle = "Engine Parts";
parentID = 0; // Parent ID of 0 indicates a root category
}
Node: {
categoryID = 300;
categoryTitle = "Camshafts";
parentID = 259; // Parent ID indicates this category is a subcategory
}
Node: {
categoryID = 317;
categoryTitle = "Kent Camshafts";
parentID = 300;
}
The following methods are what I have so far in my application.
/**
* Kickstarts parsing operation
*/
- (void)parseCategoriesData:(NSArray *)downloadedData {
NSMutableDictionary *fakeCategory = [NSMutableDictionary dictionary];
[fakeCategory setObject:[NSNumber numberWithInt:0] forKey:#"categoryID"];
int counter = 0;
[self recursiveFunction:downloadedData parentCategory:fakeCategory counter:&counter];
NSLog(#"Final counter = %d", counter);
}
/**
* Recursive function to traverse the passed NSArray
*/
- (void)recursiveFunction:(NSArray *)array parentCategory:(id)parentCategory counter:(int *)i {
NSArray *subCategories = [self findSubcategoriesForCategoryID:[[parentCategory valueForKey:#"categoryID"] intValue] categoryData:array];
for (id object in subCategories) {
NSLog(#"Node: %# depth: %d",[object description], *i);
*i = *i + 1;
[self recursiveFunction:array parentCategory:object counter:i];
}
}
/**
* Returns an NSArray of subcategories for the passed categoryID
*/
- (NSArray *)findSubcategoriesForCategoryID:(int)categoryID categoryData:(NSArray *)categoryData {
NSIndexSet *indexsForFilteredCategories = [categoryData indexesOfObjectsPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {
return (BOOL)([[obj valueForKey:#"parentID"] intValue] == categoryID);
}];
return [categoryData objectsAtIndexes:indexsForFilteredCategories];
}
Your recursive function looks OK, but it is rather convoluted, so only a test can guarantee that it really works for all special cases.
If I understand your algorithm correctly, you start from the top and go down to the items that have the present id as the parent id. It follows, that you might have parent ids that do not exist as category ids.
This is quite easy to test:
NSArray *allIDs = [downloadedData objectForKey:#"categoryID"];
NSArray *allParentIDs = [downloadedData objectForKey:#"parentID"];
for (NSNumber *x in allParentIDs) {
if (x.intValue==0) continue;
NSArray *allChildren = [allIDs filteredArrayUsingPredicate:
[NSPredicate predicateWithFormat:#"self = %#", x]];
if (allChildren.count == 0) {
NSLog(#"There are no category ids for parent id %d.", x.intValue);
}
}