I am trying to load xml data using newTBXMLWithURL method and once success block returns xml, I am trying to dispatch it using delegation so that controller receives NSMutableArray of records but I must be doing something wrong and I get an error in console that says "PROGRAM RECEIVED EXC_BAD_ACCESS" I am not sure where I have gone wrong. Code attached below
#import "XmlParser.h"
#import "TBXML+HTTP.h"
#import "NewsObject.h"
#implementation XmlParser
#synthesize delegate = _delegate;
- (void)GetNewsList
{
TBXMLSuccessBlock s = ^(TBXML *tbxml) {
NSMutableArray *arrayOfNews;
TBXMLElement *root = tbxml.rootXMLElement;
TBXMLElement *newsListElement = [TBXML childElementNamed:#"NewsList" parentElement:root];
TBXMLElement *newsElement = [TBXML childElementNamed:#"News" parentElement:newsListElement];
while(newsElement !=nil){
NewsObject *news = [[NewsObject alloc]init];
news.headLine = [TBXML textForElement: newsElement ->firstChild];
news.description = [TBXML textForElement:newsElement ->firstChild->nextSibling];
news.imageUrl = [TBXML textForElement:newsElement->firstChild->nextSibling->nextSibling];
if(arrayOfNews==nil)
arrayOfNews = [NSMutableArray arrayWithObject:news];
else
[arrayOfNews addObject:news];
newsElement = newsElement ->nextSibling;
}
[self.delegate XmlParser:self feedReady:arrayOfNews];
};
TBXMLFailureBlock f = ^(TBXML *tbxml, NSError *error) {
NSLog(#"nay");
};
[TBXML newTBXMLWithURL:[NSURL URLWithString:#"url"]
success: s
failure: f];
}
#end
Input sample:
<xmlData>
<NewsList>
<News newsId="1" providerId="1" articleId="95020" sportId="6" sportName="RBL">
<Headline>Matai signs on with Manly</Headline>
<Description>
Manly has retained another one of its premiership stars with Steve Matai committing to the Sea Eagles until the end of the 2015 season.
</Description>
<Image>
http:google.com/All.png
</Image>
</News>
<News newsId="2" providerId="1" articleId="95019" sportId="7" sportName="RBU">
<Headline>Reds lose Lucas for Brumbies clash</Headline>
<Description>
Queensland has lost key utility back Ben Lucas to injury on the eve of Saturday night's vital match with the Brumbies at Canberra Stadium.
</Description>
<Image>
http:google.com/All.png
</Image>
</News>
</NewsList>
<xmlData>
Thanks for letting us know the actual error message. There is no a single reason for that error or warning.
Also, are you using ARC or just forgot to autorelease the stuff? Which Xcode version and compiler are you using? All these details matter.
I'd say you can fix this avoiding self inside the block:
__block id _self = self;
TBXMLSuccessBlock s = ^(TBXML *tbxml) {
/* use _self inside the block, not self */
};
See https://stackoverflow.com/a/7854315/143097.
Previous answer:
It seems you're calling a method that doesn't exist: newTBXMLWithURL:success:failure:. At least in my version of TBXML it is called: tbxmlWithURL:success:failure:.
I bet there is a hint about this somewhere in the error message, isn't it?
Related
I am trying to generate source code from a wsdl file for iOS. I've stumbled upon a couple of tools and so far wsclient++ and sudzc at least seem to work. But I need to send requests to different servers with the same soap interface, depending on the state of the iOS app.
In the source code generated by wsclient I can set the server URL via
MyWebService* ws = [MyWebService service];
// // set base url for entire application
[SoapWebService setGlobalBaseUrl: #"http://domain.com"];
NSError* error = nil;
Result* rs = [ws callMethod: p1 param2:p2 error:&error];
Which would me allow me to do something like
if(condition1) [SoapWebService setGlobalBaseUrl: #"http://betaserver.com"];
if(condition2) [SoapWebService setGlobalBaseUrl: #"http://developserver.com"];
if(condition3) [SoapWebService setGlobalBaseUrl: #"http://liveserver.com"];
Is there a way to archive something similar with the source code generated by sudzc?
As long as the soap is the same response you shouldn't have a problem using your code. There is a file that stores the server address. The code generated by sudzc can be modified to any address. I actually created a dynamic way of hitting servers. I will find the file and code I used to do this.
You can search the project for your domain you used for sudzc.
I'm not in front of a mac right now, but I will update later.
UPDATE:
Ok, so I created a settings tab and allowed the user to input a specific ip address if necessary. It saves the IP address in a dictionary and then this file retrieves it from the dictionary. I left some of my original comments and added some in the code so you can see both ways. If it confuses you let me know and I'll edit again. In my sudzc generated code I modified the file to this:
/*
wsUpdateQOH.m
The implementation classes and methods for the wsUpdateQOH web service.
Generated by SudzC.com
*/
#import "wsUpdateQOH.h"
#import "Soap.h"
#import "Settings.h"
#define URL #"http://%#/webServiceAddress/updateqoh.asmx"
/* Implementation of the service */
#implementation wsUpdateQOH
- (id) init
{
if(self = [super init])
{
// take out hard coded address and add variable to have a dynamic IP #"http://www.site.com/webServiceAddress/updateqoh.asmx"
// here is the dictionary return and format of the url string
NSString *savedValue = [[NSUserDefaults standardUserDefaults] stringForKey:#"serverIP"];
self.serviceUrl = [[NSString alloc] initWithFormat:URL, savedValue];
// uncomment for a hard coded address self.serviceUrl = #"http://%#/webServiceAddress/updateqoh.asmx";
self.namespace = #"http://tempuri.org/webServiceAddress/UpdateQOH";
self.headers = nil;
self.logging = NO;
}
return self;
}
- (id) initWithUsername: (NSString*) username andPassword: (NSString*) password {
if(self = [super initWithUsername:username andPassword:password]) {
}
return self;
}
+ (wsUpdateQOH*) service {
return [wsUpdateQOH serviceWithUsername:nil andPassword:nil];
}
+ (wsUpdateQOH*) serviceWithUsername: (NSString*) username andPassword: (NSString*) password {
return [[[wsUpdateQOH alloc] initWithUsername:username andPassword:password] autorelease];
}
// *** Below here is the soap actions ***
I am sending reguest to webserver in this function:
-(void)getData
{
NSURL *url = [NSURL URLWithString:#"http://10.10.10.10/application.php"]; //some address
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
request.delegate = self;
[request setPostValue:#"6577098" forKey:#"serial_number"];
[request startAsynchronous];
}
Then on server part in application.php :
<?php
//$serial_number from $_POST["serial_number"];
$serial_number = $this->getString('serial_number', 64);
$stmt = $this->pdo->prepare('SELECT S.DateTime, SN.Name FROM States S LEFT JOIN StateNames SN on SN.ID=S.State_ID WHERE S.SerialNumber = ?');
$stmt->execute(array($serial_number));
$states = $stmt->fetchAll(PDO::FETCH_ASSOC);
$result = array();
foreach ($states as $state)
{
$result[] = $state;
}
sendResponse(200, json_encode($result));
?>
This part works when I try it from browser, it works and I get this:
[{"DateTime":"2013-05-15 10:22:11","Name":"No water"},{"DateTime":"2013-05-13 14:55:31","Name":"Water"}]
Then back to process it in Xcode:
-(void)requestFinished:(ASIHTTPRequest *)request
{
if (request.responseStatusCode == 200)
{
NSString *responseString = [request responseString];
NSLog(#"%#",responseString); //if I try this nothing happened
}
}
I think I have to do something with JSON.
I thing I have bad response on my request. But I have responceStatusCode 200.
Can anyone help me? I didn't find what's wrong.
Thanks
I would need specifics to tell you what server settings you need to adjust. My next best advice - debug line by line. For example in php file, do:
$serial_number = $this->getString('serial_number', 64); //there I get serial_number from $_POST["serial_number"];
echo $serial_number; die;
// ...
at this point if you run your app again, you should see the serial # printed in -(void)requestFinished:(ASIHTTPRequest *)request, if nothing breaks up to here. If you do see it, remove echo and die, move on
//...
$stmt = $this->pdo->prepare('SELECT S.DateTime, SN.Name FROM States S LEFT JOIN StateNames SN on SN.ID=S.State_ID WHERE S.SerialNumber = ?');
$stmt->execute(array($serial_number));
$states = $stmt->fetchAll(PDO::FETCH_ASSOC);
print_r($states); die;
// ...
if no responce there, this might mean that you don't have PDO driver installed with your php.
If the next line sendResponse(200, json_encode($result)); breaks it, then my guess is that your php installation lacks json module.
I have some values generated from my native code that I would like to pass to phonegap. These data are generated in real time and are not directly influenced by the user's actions through the phonegap gui.My native code is part of a plugin that I made.
What is the best way to approach this? I want to have a function to send data over anytime and have a listener on the cordova side. I'm using Cordova 1.5 with Xcode 4.3.
Here is what I have so far:
swipe.js:
var swipe={
callNativeFunction: function (success, fail, resultType) {
return Cordova.exec( success, fail,
"ca.swipe",
"nativeFunction",
[resultType]); }
};
index.html:
...
function callNativePlugin( returnSuccess ) {
swipe.callNativeFunction( nativePluginResultHandler, nativePluginErrorHandler, returnSuccess );
}
function nativePluginResultHandler (result) {
alert("SUCCESS: \r\n"+result );
}
function nativePluginErrorHandler (error) {
alert("ERROR: \r\n"+error );
} ... <body onload="onBodyLoad()"> <h1>Hey, it's Cordova!</h1>
<button onclick="callNativePlugin('success');">Success</button>
<button onclick="callNativePlugin('error');">Fail</button>
</body> ...
swipe.h:
...
#interface swipe : CDVPlugin
- (void) nativeFunction:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
#end
swipe.m:
...
- (void) nativeFunction:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options {
NSLog(#"Hello, this is a native function called from PhoneGap/Cordova!");
//get the callback id
NSString *callbackId = [arguments pop];
NSString *resultType = [arguments objectAtIndex:0];
NSMutableArray *GlobalArg=arguments;
CDVPluginResult *result;
if ( [resultType isEqualToString:#"success"] ) {
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString: #"Success :)"];
//writes back the smiley face to phone gap.
[self writeJavascript:[result toSuccessCallbackString:callbackId]];
}
...
The code that I have right now has nothing for doing what I want. I'm not really sure how to setup the code in both cordova and native.
Sounds like you need to be able to talk back down to PhoneGap from objective C, in which case you should be able to use something like:
NSString *jsResult = [theWebView stringByEvaluatingJavaScriptFromString:#"hello()"];
NSLog(#"jsResult=%#",jsResult);
And if you have a JS function like "hello" in your index.html like this:
function hello(){return "hello";}
Its a way of talking back to your PhoneGap web layer
create a class of type CDVPlugin
import #import in that class
initialize a handler method .h class
- (void)Device:(CDVInvokedUrlCommand *)command;
and implement the method in .m class
- (void)openDevice:(CDVInvokedUrlCommand *)command{
CDVPluginResult *pluginResult = nil;
BOOL checkOpenDevice=NO;
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:checkOpenDevice];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
}
in this way through self.commandDelegate your data will be able to reach to the cordova class
if the .js file hit(calls) that particular method which is initialized in .h class.
I am currently developing an iOS Messenger application and I would like to talk about these two classes relationship: MessengerConversation and MessengerMessage.
Supposing that I already have a local MessengerConversation instance which can have many MessengerMessage instances related into its messages relationship property, I would like to request and mapping the following JSON payload:
Request: GET /conversations/:conversationID/msgs
Response:
{
"messages": [
{
...
"messageid": n,
"content": "..."
...
},
...
]
}
As the response JSON payload didn't indicate which conversation the delivered messages are from. I used the following approach to fix this issue into my MessengerManager class (Responsible for interacting with the shared RKObjectManager instance):
- (void)objectLoader:(RKObjectLoader *)objectLoader willMapData:(inout id *)mappableData {
//
// GETs Resource Paths.
if ([objectLoader method] == RKRequestMethodGET) {
if ([pathMatcherConversationsMessagesGET matchesPath:objectLoader.resourcePath tokenizeQueryStrings:NO parsedArguments:Nil]) {
//
// Get requested conversationID from the following resource path Pattern:
// kMessengerManagerResourcePathMessages: /conversations/:conversationID/msgs
NSNumber *currentConversationID = Nil;
NSDictionary *arguments = Nil;
BOOL isMatchingPattern = [pathMatcherConversationsMessagesGET matchesPattern:kMessengerManagerResourcePathConversationsMessagesGET
tokenizeQueryStrings:YES
parsedArguments:&arguments];
if (isMatchingPattern) {
currentConversationID = [arguments objectForKey:#"conversationID"];
//
// Get the original returned array of messages:
NSArray *origMessagesArray = [*mappableData valueForKeyPath:#"messages"];
NSMutableArray *reformattedData = [NSMutableArray arrayWithCapacity:[origMessagesArray count]];
//
// Create copies of objects adding the already knew reference.
for (NSDictionary *origMessagesArrayObject in origMessagesArray) {
NSMutableDictionary *newMessagesArrayObject = [origMessagesArrayObject mutableCopy];
[newMessagesArrayObject setObject:currentConversationID forKey:#"conversationid"];
[reformattedData addObject:newMessagesArrayObject];
}
//
// Replace the new objects instead of the response objects
[*mappableData setObject:reformattedData forKey:#"messages"];
}
}
}
}
And so everything worked properly. That is, all loaded MessengerMessages from the specified MessengerConversation (into the RKObjectLoader resource path) are being inserted into the wanted relationship.
Now comes the real problem, as I am working with my MessengerManager class which adopts the RKObjectLoaderProtocol, I could implement the objectLoader:willMapData: method. But as my View classes are using the RKFetchedResultsTableController and every table controller instance is also its RKObjectLoader delegate, I don't know which would be the best practice to enable a RKFetchedResultsTableController instance to update a received JSON payload before the mapping operation.
Shall I subclass it?
And are there better ways to map received objects into a pre-defined object specified by a RKObjectLoader resource path (e.g: GET /conversations/2/msg where all resulted messages should be mapped inside the defined MessengerConversation object with its primary key value equal to 2)?
Best regards,
Piva
You don't need this method. When you launch the RKObjectLoader, set your Conversation object as the targetObject and make the mapping relative to this object. For example:
RKManagedObjectMapping* cMapping = [RKManagedObjectMapping mappingForClass: [MessengerConversation class]];
RKManagedObjectMapping* mMapping = [RKManagedObjectMapping mappingForClass: [MessengerMessage class]];
//Configure mappings
[cMapping mapKeyPath: #"messages" toRelationship: #"messages" withObjectMapping: mMapping];
[mappingProvider setMapping cMapping forKeyPath: #""];
I tried with the below code snippet taken from the website after replacing with my namespace and realm. But when i try to run the application, I am receiving the parser error like
Entity: line 1: parser error : Start tag expected, '<' not found
WACloudAccessControlClient *acsClient =
[WACloudAccessControlClient
accessControlClientForNamespace:#“iostest-walkthrough”
realm:#“uri:wazmobiletoolkit”];
[acsClient showInViewController:self
allowsClose:NO
withCompletionHandler:^(BOOL authenticated)
{
if (!authenticated) {
NSLog(#"Error authenticating");
} else {
WACloudAccessToken *token = [WACloudAccessControlClient sharedToken];
NSString *securityToken = [token securityToken];
}
}];
I am not able to understand the issue clearly.
Please guide me with example. Thank you
I would suggest looking at the samples here:
https://github.com/WindowsAzure-Toolkits/wa-toolkit-ios
You can also look at this for getting started:
http://www.wadewegner.com/2011/05/windows-azure-toolkit-for-ios/
My guess is that you didn't #import something you need.