Survey application with offline capabilities and how to capture the data from multiple ipads to one? - ios

I am trying to build a Survey application where the surveys will be taken offline on multiple ipads and when these ipads are online they are going to upload the data(survey answers) to our servers? I am really struggling how to send the survey to multiple ipads and more importantly to capture from different ipads to one source ?
I need help to clear my architecture part and I need some examples to do the coding part. Do you know anything similar?
What are you ideas?
Many Thanks in advance,
Arda

Create a web server to accept and send survey questions and answers.
I would envision an app that goes like this:
1) Slave iPads makes a HTTP POST request to server asking for the survey
This is usually done using a networking library for iOS like MKNetworkKit or AFNetworking. The general process is to:
create a NSDictionary of key-value pairs to form the HTTP POST request
submit the data through a block construct with completion handler
So something like:
MKNetworkOperation *op = [engine operationWithURLString:#"http://www.mywebserver.com/api/fetchQuestions"
params:nil
httpMethod:#"POST"];
2) Server receives request, grabs all survey questions in database and return JSON encoded questions to slave ipads.
I'm not sure what platform your web server is on but in the past, I used Symfony 2.0 which is a PHP web framework.
It provides very helpful tools like Doctrine (an Object Relational Mapper or ORM) to let me work with my MySQL data as if they're programming objects.
So my general process for fetching data would be something like:
// pseudo php function codes
public function sendSurveyQuestionAction()
{
$repository = $this->getDoctrine()->getRepository('MyAppBundle:Survey');
$query = $repository->createQueryBuilder('query')->getQuery();
$arrObjs = $query->getResult();
$arrObjDatas = NULL;
foreach($arrObjs as $obj)
{
$arrObjDatas[] = $obj->toArray();
}
$response = new Response(json_encode(array('data' => $arrObjDatas)));
$response->headers->set('Content-Type', 'application/json');
$return $response;
}
This would return all survey in JSON format, ready to be parsed by your master iPad app.
3) Users on slave iPads fill in the questions through the app UI and submits. The app saves
the data to disk, checks for a working internet connection before sending data back to server.
Submitting the answer is very similar grabbing the questions, so your iOS code should be something like:
// ------------------------------------------------------------------------------------
// store all question-answers into a dictionary to be submitted as HTTP POST variables
// obviously, you wouldn't create it here, this is just example code, you would likely
// have stored your questions and answers when user presses 'finish' button
// ------------------------------------------------------------------------------------
NSMutableDictionary *paramDictionary = [[NSMutableDictionary alloc] init];
[paramDictionary setObject:#"5" forKey:#"q1"];
[paramDictionary setObject:#"10" forKey:#"q2"];
[paramDictionary setObject:#"15" forKey:#"q3"];
// this helps your web server know how many question-answers to expect, or you could hard code it into your business logic
[paramDictionary setObject:[NSNumber numberWithInteger:3] forKey:#"numberOfQA"];
MKNetworkOperation *op = [engine operationWithURLString:#"http://www.mywebserver.com/api/submitAnswers"
params:paramDictionary
httpMethod:#"POST"];
This will submit your answers for each of your question. You may have noticed I used q1, q2, q3.
These are for your web server code to identify each questions and extract the respective answers from them.
4) Server receives finished answers and commit them to database
So if you were using Symfony 2.0 PHP code, then something like:
// pseudo php function
public function saveAnswersAction()
{
$numOfQA = $_REQUEST['numberOfQA'];
for($i = 0; $i < $numOfQA; $i++)
{
// ----------------------------------------------------------------------
// looping through all the questions such as q1, q2, q3, q4, q5....
// by appending the counter variable to the question identifier
// ----------------------------------------------------------------------
$currentAnswer = $_REQUEST['q'.$i];
// use Doctrine to create new answer entities, and fill in their data
$answerEntity.answer = $currentAnswer;
$surveyEntity->addAnswerEntity($answerEntity);
// mark survey as complete so we can fetch all 'completed' surveys later
$surveyEntity.complete = true;
}
// tell Doctrine to commit changes to MySQL Database
// return HTTP OK status message
}
5) Now all that's left is for your master iPad app to make a HTTP POST request to get all surveys.
The process is the same with your iOS code making a HTTP POST requesting for all 'completed' survey entities from your web server.
The web server grabs them and return them as JSON encoded data.
Your app then receives the completed surveys with question answer like this:
surveys
{
{
questionNumber: 1,
questionAnswer: "5"
},
{
questionNumber: 2,
questionAnswer: "10"
},
{
questionNumber: 3,
questionAnswer: "15"
}
}
Now you use JSONKit to parse this JSON data. You should end up with a NSDictionary from JSONKit.
You can then go something like:
// pseudo code
-(void)displayCompletedSurveys
{
[MKNetworkOperationEngine doRequest:
...
^completionBlock {
// parse JSON data
NSDictionary *surveyData = [JSONKit dictionaryFromJSONData:data)
NSEnumerator *enumerator = [surveyData enumerator];
NSDictionary *currentQuestion = nil;
while([enumerator nextObject] != nil)
{
// do something with each of your question-answer e.g. show it on screen
}
}];
}
Points To Consider
Most of the code above are pseudo-codes. Your final real code would probably be much more in depth.
You'll need to build some master login into your app to prevent everyone from seeing the completed surveys.
Some Extra Information You Should Know
Here are some extra information to help you
JSONKit for fast JSON data decoding from your web server
MKNetworking or AFNetworking to submit your data to your web server
You need to know how to write web services to handle accepting the survey answers. I recommend learning a web framework like Symfony 2.0
Hope that helps.

Related

How to access data field in Dialogflow?

As the Dialogflow documentations states, the data field represents
Additional data required for performing the action on the client side.
The data is sent to the client in the original form and is not
processed by Dialogflow.
How should one access it in the iOS framework?
request?.setMappedCompletionBlockSuccess({ (request, response) in
...
}
I couldn't find it in the response object and can't find any documentation for iOS.
Thanks.
Your question is a bit vague (can you edit and narrow it down?), but i think you got it the other way round, what that snippet of documentation that you pasted means is that you are supposed to send that payload to DialogFlow and it will forward it to a connected Client (e.g Messenger, Slack etc) un-touched. It simply means that DialogFlow assumes that you know what you are doing.
Here is a sample Fulfilment response to DialogFlow in JS
module.exports.sendGenericMessageWithText = function(message) {
return {
data: {
facebook: [
{
text: message
]
}
}
}

UIWebView slow loading using NSUrlProtocol Xamarin.Forms

I'm working on an iOS application using Xamarin.Forms. This application is using UIWebView controller that shows a web application that is hosting on my server. Each time that I make a request I have to send a custom header in order to identify that this request comes to the mobile application and not from a browser, to do this I'm using an NSUrlProtocol object that overrides the method Request that inserts the custom header on each request.This is my code:
public override NSUrlRequest Request {
get {
NSMutableDictionary headers = null;
if (null == base.Request.Headers) {
headers = new NSMutableDictionary ();
} else {
headers = new NSMutableDictionary (base.Request.Headers);
}
headers.Add(NSObject.FromObject(AppVariables.headerVariable), NSObject.FromObject (AppVariables.appVersion));
NSMutableUrlRequest newRequest = (NSMutableUrlRequest)base.Request.MutableCopy ();
newRequest.Headers = headers;
return newRequest;
}
}
The problem that I have right now is that I noticed since I started using the NSUrlProtocol the loading time of the pages is increasing a lot. Right now the loading is taking 10 seconds, before this implementation the page took 3 seconds approximately.
Can anyone please point out some helpful direction to overcome this??
I don't see any reasons for the delay in response time when you're using custom headers. Like Andreas mentioned in the comments, I believe it has to do with your server code. I would recommend profiling your server code.
Do you see similar results when you send the requests (with custom headers) from Fiddler or cURL?
Just like #AndreasPaulsson and #prashant had mentioned, server might be the culprit. I would recommend testing the API with tools like Postman and check the response speed. I would also recommend you to check ModernHttpClient by Paul C Betts. In iOS the library uses NSUrlSession.

How to call xml-rpc webservice using objective c

Suppose, the webservice provider's server exposing the webservice in the form http://example.com:8000/api
What is best framework or library to access the webservice in ios 7 project
There are a few marshaling frameworks that support generating an object-graph from XML, however I would simply go for the following:
Invoke the service endpoint. My favorite library is BBHTTP, however you could use AFNetworking, NSURLConnection with gcd or whatever you prefer for asynch network calls.
Extract the relevant contents of the XML payload onto your use-case specific payload object using RaptureXML
I recommend having use-case specific payload objects because they model exactly what is needed for a given service invocation - supporting the notion of contract-first development. This allows you to change you internal model without effecting the integration to external systems. Similarly the external API can change without effecting your model.
You can create a category method on RXMLElement to return the element mapped to a use-case-specific object. A typical mapping usually takes just a handful of lines of code to marshal from wire-format to your payload object for the service invocation.
Here's an example (the code that I took it from wanted the payload wrapped in a SOAP envelope - just ignore that bit).
- (void)request:(MyUseCaseRequstPayload*)request onComplete:(void (^)(MyResponsePayload*))onSuccess
onError:(void (^)(NSError*))onError;
{
//Even more XML! You can stick your payload inside an envelope if you want
SoapEnvelope* envelope = [SoapEnvelope envelopeWithContent:[request xmlString]];
[[BBHTTPRequest postToURL:_serviceUrl data:[envelope data] contentType:#"text/xml"] execute:^(BBHTTPResponse* response)
{
RXMLElement* element = [RXMLElement elementFromXMLData:[response content]];
MyResponsePayload* response = [[element child:#"elementToBeMapped"] asMyObjectType];
if (onSuccess)
{
onSuccess(response);
}
} error:^(NSError* error)
{
LogDebug(#"Got error: %#", error);
if (onError)
{
onError(error);
}
}];
}

how to make ruby on rails database api available for a data driven ios app [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
Well , I have just started coding in general. I am trying to make an ios social app with basic picture information taking data from a website ( some what of a flickr-clone)
So , the main website will be built on Ruby on rails.
EDIT :
ok so , i want to know when a person uploads a picture , it will have the following entries:
* name
* who took
* location
I was researching about the gem logtrend (https://github.com/gorsuch/logtrend) , i was wondering if I can make a trending feed of sorts using location?
eg: the user selects a tab which shows them the trending pic ( near them (based on his core location) ?? Can we do something like that ?
I don't know anything about Ruby on Rails but I do know to do what you're trying to do (let user upload photos with their name and GPS location to a server, then allow other users to view that photo by downloading it down to their app).
One way you can build the server is to build a web service with Ruby on Rails.
Web Servcie
The web service (your server) does 2 things:
1) Accept a Request
2) Return a Response
With the web service, you accept HTTP POST or GET request, then your server's logic code will parse the "parameters" or "variables" inside the POST or GET.
Once your server has these variables, it can save them to the database (an ORM would really make it easier).
Your web service can then return a response using HTTP Status Code or a JSON formatted response.
Example Scenario
1) iPhone app takes photo and then makes a HTTP POST request to your Ruby server using ASIHttpRequest or AFNetworking.
// ASIExample
-(void)uploadPhotoToServer
{
NSURL *url = [NSURL urlWithString:myUploadWebServiceURL];
__block ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
// ---------------------------------------------------------------
// setting the POST parameters below
// note: you will need to get the NSData from a UIImage object
// ---------------------------------------------------------------
[request setData:imageData withFileName:#"myphoto.jpg" andContentType:#"image/jpeg" forKey:#"photo"];
[request setPostValue:fldName.text forKey:#"name"];
[request setPostValue:[NSNumber numberWithDouble:myLatitude] forKey:#"latitude"];
[request setPostValue:[NSNumber numberWithDouble:myLongitude] forKey:#"longitude"];
[request setCompletionBlock:^{
int statusCode = [request responseStatusCode];
if(statusCode == 200)
{
[self alertUploadComplete];
}
}];
[request setFailBlock:^{
NSLog(#"Server error: %#", [[request error] localizedDescription]);
[self alertConnectionProblem];
}];
[request startAsynchronous];
}
2) Server receives the request, parses the data and returns a response
// Symfony Web Framework example (PHP based web framework)
public function uploadPhotoAction()
{
// --------------------------------------------------
// check to make sure all POST parameters are sent
// in the POST request by iPhone app.
// --------------------------------------------------
if(
!isset($_REQUEST['name']
|| !isset($_REQUEST['latitude']
|| !isset($_REQUEST['longitude']
|| !isset($_REQUEST['photo']
)
{
return new Response($this->sendResponse(406, 'Missing POST parameters');
}
else // assumes safe to continue
{
/*
write code to save the your name, latitude, longitude to your database here
*/
/*
save your photo to your server's dedicated photo folder, then store
the file path to the file in your database entry in the above step
*/
return new Response($this->sendResponse(200, 'Photo uploaded'));
}
}
A couple of gems that you could make use of are Devise coupled with OmniAuth for social logins/authentication.
For more gems by categories, check out Ruby Toolbox.
Hope you the best of luck!
Is this achievable through ruby on rails ?
Yes, yes it is.
what gems should I be using ?
Depends upon your approach and featureset.
Also , which gems can be used to make API's to feed the IOS app ?
I think you're misunderstanding what an API is. The API is HOW the client will interact with the host.
I would suggest you investigate using JSON to communicate between your IOS app and your Web app. Both IOS and Ruby/Rails are very capable of supporting JSON and it is relatively lightweight.
Also, you need to define, in detail, what the IOS application is going to do where it needs interaction with the Web app.
Example
IOS App (IA) will save a picture to the Web App (WA).
IA may save the same picture to WA (overwriting)
IA will be told if WA is full
IA will log into WA
IA can log out from WA
IA can change password on WA
WA will reject commands from a non-logged in IA
IA can retrieve user's pictures from WA
IA can retrieve any other user's pictures from WA
etc.
Now, for each one, you design the API to support that function.

Identify Request return of (id)result

I am retrieving some user date out of my iOS app (me/friens, me/events, ...) I want to forward this JSON to a server where I do some additional data processing.
The thing is that I get an answer for my me/events object without any kind of identifier:
(
{
data = (
The only thing I get is this 'data' string: But how is it possible to manipulate the JSON in the way that I get an identifier like:
(
{
events = (
Thank you very much for any kind of help!
I was wrong. Of couse this is not JSON. It is the output of a NSDictionary object. If you want to enable Facebook SSO in your Application and handle open graph data after the User logged in you just send the Facebook Id and the access_token to the server to perform additional tasks.

Resources