Salesforce Rest Request, insert data - objective-c

I'm using the salesforce iphonesdk, I wonder if anybody knows how to submit data into the salesforce object, like using INSERT ? Which method is to be used?

You need to use the create() call, passing it an array of SObjects to insert — see the documentation here.
You should probably read the Getting Started section of the reference material, especially the API Call Basics. Your question demonstrates a considerable lack of research, and I'd advise making sure you do research things yourself before asking a question on stackoverflow if you don't want it to be closed out. If you've read the documentation and still don't understand how to do something, then you're in a good position to ask for help!

Swift version:
Your controller class should conform to RestClientDelegate protocol
data is the dictionary(object) to be inserted
let data = ["Percentage__c": "1", "Amount__c":"11", "Volume__c":"111", "Promotion_Details__c": "00112233"]
let request = RestClient.shared.requestForCreate(withObjectType: "<your_table_name_>", fields: data)
RestClient.shared.send(request, delegate: self)
Another Way:
If you don't want to conform to RestClientDelegate, simply call:
RestClient.shared.send(request: request, onFailure: { (err, res) in
// some closure to handle error
}) { (any, res) in
// another closure to handle error
}

With guidance by Lacey Snr,
Found my own answer
NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];
[dic setObject:#"Smith" forKey:#"Name_c"];
[dic setObject:#"5" forKey:#"PAX_c"];
SFRestRequest *request = [[SFRestAPI sharedInstance]
requestForCreateWithObjectType:#"Booking_Forms_c" fields:dic];
[[SFRestAPI sharedInstance] send:request delegate:self];

Related

Inviting Peer to MCSEssion

This is my first time posting on stackoverflow, and I'm aware of the strict posting requirements. Please let me know if I'm not following any of the guidelines.
I'm currently writing an IOS (8.4) application in Xcode, using Objective-C. The goal is to use MCSessions in order to stream data between IOS devices. I'm currently struggling with the concept of sessions, despite reading numerous posts here and elsewhere that attempt to clarify the topic. Here are the resources I'm already aware of:
https://developer.apple.com/videos/play/wwdc2013-708/
https://medium.com/#phoenixy/using-multipeer-connectivity-120abacb9db
Here's my current understanding: At the most basic level, you have an advertiser, and a browser. The advertiser has a local session, which allows them to "advertise". When the browser sees an advertiser, the browser sends an invite to the advertiser to his (the browser's) local MCSession. Assuming this is all correct, here's where I'm getting confused. The advertiser can accept the invite, and in the process, passes his local session to the invitationHandler.
I have implemented the following logic in code, as shown below. However, in tracing MCSession state changes for both the advertiser and browser, a connection is attempted, but the final state is always didNotNonnect.
Code for sending invitation (Browser):
[self.broadcasterBrowser invitePeer:[broadcasterPeerIDs objectAtIndex:indexPath.row]
toSession: self.appDelegate.mpcHandler.session withContext:nil timeout:30.0 ];
Code for accepting invitation (Advertiser):
- (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser
didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void(^)(BOOL accept, MCSession *session))invitationHandler
{
ArrayInvitationHandler = [NSArray arrayWithObject:[invitationHandler copy]];
// ask the user
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:peerID.displayName
message:#"Would like to create a session with you"
delegate:self
cancelButtonTitle:#"Decline"
otherButtonTitles:#"Accept", nil];
[alertView show];
if (alertViewResult)
{
void (^invitationHandler)(BOOL, MCSession *) = [ArrayInvitationHandler objectAtIndex:0];
invitationHandler(YES, self.appDelegate.mpcHandler.session);
}
}
Any help is greatly appreciated!
Austin
I ran into a similar problem trying to use MPC. I created a custom class to handle all of the MPC connectivity details. While testing though, every time my advertiser would accept the invite, it would complain about wrong connection data and fail. I discovered that the problem was that I was vending out the MCPeerID object for my device from a class variable I created as below:
static var peerObject : MCPeerID {
return MCPeerID(displayName: deviceNameString)
}
lazy var sessionIVar = MCSession (peer: MyConnectivityClass.peerObject)
func startAdvertisingForConnectivity () {
advertiserService = MCNearbyServiceAdvertiser (peer: MyConnectivityClass.peerObject, discoveryInfo: nil, serviceType: "my-multipeer-connectivity-service-identifier")
}
Then when I got an invitation I would initialize a MCSession object using the "peerObject" computed property and return it in the invitation handler, like this:
func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didReceiveInvitationFromPeer peerID: MCPeerID, withContext context: Data?, invitationHandler: #escaping (Bool, MCSession?) -> Swift.Void) {
invitationHandler(true, sessionIVar)
}
I assumed that each time I called for "MyConnectivityClass.peerObject" it would give back an identical peerID because I was always initializing it with the same display name. It turns out that's not true. So when I was advertising I was using one peerID object and then when I was responding to the invitation, I was responding with a MCSession object that contained an entirely different peerID.
So the solution was to change the "MyConnectivityClass.peerObject" computed class property to a constant, or an Ivar, in my connection handler class. Like this:
let peerObject : MCPeerID = MCPeerID(displayName: deviceNameString)
Then the rest of the code just worked because no matter how many times I called for the MCPeerID object, it was always the same. Looking back I don't know why I started out with it the way I did. :-)
Then in my connectivity class I archived and stored the MCPeerID objects for both the browser and the advertiser so that I could have the advertiser automatically accept the invitation for trusted MCPeerIDs. That's not possible if you create the MCPeerID object each time you use it, even if you always initialize it with the same DisplayName.

How would you write fetching a collection the "Reactive Cocoa" way?

The client I'm building is using Reactive Cocoa with Octokit and so far it has been going very well. However now I'm at a point where I want to fetch a collection of repositories and am having trouble wrapping my head around doing this the "RAC way"
// fire this when an authenticated client is set
[[RACAbleWithStart([GHDataStore sharedStore], client)
filter:^BOOL (OCTClient *client) {
return client != nil && client.authenticated;
}]
subscribeNext:^(OCTClient *client) {
[[[client fetchUserRepositories] deliverOn:RACScheduler.mainThreadScheduler]
subscribeNext:^(OCTRepository *fetchedRepo) {
NSLog(#" Received new repo: %#",fetchedRepo.name);
}
error:^(NSError *error) {
NSLog(#"Error fetching repos: %#",error.localizedDescription);
}];
} completed:^{
NSLog(#"Completed fetching repos");
}];
I originally assumed that -subscribeNext: would pass an NSArray, but now understand that it sends the message every "next" object returned, which in this case is an OCTRepository.
Now I could do something like this:
NSMutableArray *repos = [NSMutableArray array];
// most of that code above
subscribeNext:^(OCTRepository *fetchedRepo) {
[repos addObject:fetchedRepo];
}
// the rest of the code above
Sure, this works, but it doesn't seem to follow the functional principles that RAC enables. I'm really trying to stick to conventions here. Any light on capabilities of RAC/Octokit are greatly appreciated!
It largely depends on what you want to do with the repositories afterward. It seems like you want to do something once you have all the repositories, so I'll set up an example that does that.
// Watch for the client to change
RAC(self.repositories) = [[[[[RACAbleWithStart([GHDataStore sharedStore], client)
// Ignore clients that aren't authenticated
filter:^ BOOL (OCTClient *client) {
return client != nil && client.authenticated;
}]
// For each client, execute the block. Returns a signal that sends a signal
// to fetch the user repositories whenever a new client comes in. A signal of
// of signals is often used to do some work in response to some other work.
// Often times, you'd want to use `-flattenMap:`, but we're using `-map:` with
// `-switchToLatest` so the resultant signal will only send repositories for
// the most recent client.
map:^(OCTClient *client) {
// -collect will send a single value--an NSArray with all of the values
// that were send on the original signal.
return [[client fetchUserRepositories] collect];
}]
// Switch to the latest signal that was returned from the map block.
switchToLatest]
// Execute a block when an error occurs, but don't alter the values sent on
// the original signal.
doError:^(NSError *error) {
NSLog(#"Error fetching repos: %#",error.localizedDescription);
}]
deliverOn:RACScheduler.mainThreadScheduler];
Now self.repositories will change (and fire a KVO notification) whenever the repositories are updated from the client.
A couple things to note about this:
It's best to avoid subscribeNext: whenever possible. Using it steps outside of the functional paradigm (as do doNext: and doError:, but they're also helpful tools at times). In general, you want to think about how you can transform the signal into something that does what you want.
If you want to chain one or more pieces of work together, you often want to use flattenMap:. More generally, you want to start thinking about signals of signals--signals that send other signals that represent the other work.
You often want to wait as long as possible to move work back to the main thread.
When thinking through a problem, it's sometimes valuable to start by writing out each individual signal to think about a) what you have, b) what you want, and c) how to get from one to the other.
EDIT: Updated to address #JustinSpahrSummers' comment below.
There is a -collect operator that should do exactly what you're looking for.
// Collect all receiver's `next`s into a NSArray. nil values will be converted
// to NSNull.
//
// This corresponds to the `ToArray` method in Rx.
//
// Returns a signal which sends a single NSArray when the receiver completes
// successfully.
- (RACSignal *)collect;

Some basic HTTP protocol questions (programming and theory)

Before you decide its a tl:dr (too long, didnt read) post try to read at least some, since Its a question broken down in a lot of small pieces. Some of which you can probably answer and help me.
Please try to help me as much as you can. These types of problems are very common on the internet and I think you will help me and much more people after me.
I am currently researching HTTP services and the protocol itself so that I can discover if it is useful to me.
I have some basic questions as well as some code that needs to be discussed.
First I would like to know how does the communication start? I have discovered that the client sends a message in which it requests a resource (is this correct?). Then what happens? I (as a server) have to reply with what?
Do I need to append a carriage return and a line feed after every response? Somewhere it says there even need to be two (\r\n\r\n).
How can an asynchronous writing be established? (I hope this question is understandable) My primary goal is to achieve a connection between a client and a server and then a continuous data stream from server to the client. Does the client need to reply for every message it gets?
I hope I made my questions clear, since I'm not an expert in these things (yet, I am very interested in it).
And for the programming part of my problem.
I have managed to put together a simple program in Qt in C++ (server side) and a simple client in Objective C (iOS). The client connects and I can read the request header. It is like this:
Data available, incoming: "GET / HTTP/1.1
Host: localhost:9990
Connection: close
User-Agent: CFStream%20test/1.0 CFNetwork/609 Darwin/12.2.0
Should I reply to this header manually? And if so, what?
The client side code looks like this (i know its not pseudo but i think its pretty self-explanatory):
- (void)setupStream
{
NSURL *url = [NSURL URLWithString:#"http://localhost:9990"];
CFHTTPMessageRef message = CFHTTPMessageCreateRequest(NULL, (CFStringRef)#"GET", (CFURLRef)url, kCFHTTPVersion1_1);
stream = CFReadStreamCreateForHTTPRequest(NULL, message);
CFRelease(message);
if (!CFReadStreamSetProperty(stream, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue))
{
NSLog(#"Some error.");
}
CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings();
CFReadStreamSetProperty(stream, kCFStreamPropertyHTTPProxy, proxySettings);
CFRelease(proxySettings);
if (!CFReadStreamOpen(stream))
{
CFRelease(stream);
NSLog(#"Error opening stream.");
}
CFStreamClientContext context = {0, self, NULL, NULL, NULL};
CFReadStreamSetClient(stream, kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred, readStreamCallback, &context);
CFReadStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
NSLog(#"Done");
}
This is the setup stream method. The stream variable is a class variable of type CFReadStreamRef.
The callback looks like this:
static void readStreamCallback(CFReadStreamRef aStream, CFStreamEventType event, void *client)
{
ViewController *controller = (ViewController*)client;
[controller handleEvent:event forStream:aStream];
}
And the handle event like this:
- (void)handleEvent:(CFStreamEventType)event forStream:(CFReadStreamRef)aStream
{
if (aStream != stream)
{
return;
}
NSLog(#"Handle event callback");
switch (event)
{
case kCFStreamEventHasBytesAvailable:
NSLog(#"Work log");
UInt8 bytes[11];
CFIndex length;
length = CFReadStreamRead(stream, bytes, 11); //I know 11 bytes is hard coded, its in testing stage now. Feel free to suggest me how to do it better.
if (length == -1)
{
NSLog(#"Error, data length = -1");
return;
}
NSLog(#"Len: %li, data: %s", length, bytes);
break;
default:
NSLog(#"Other event");
break;
}
}
And thats practically all the client code that is worth mentioning. The Qt Server part (I will only post the important parts) is done like this: (this is a subclassed QTcpServer class). First the startServer(); is called:
bool Server::startServer()
{
if (!this->listen(QHostAddress::Any, 9990))
return false;
return true;
}
When there is a connection incoming the incomingConnection is fired off with the socket descriptor as a parameter:
void Server::incomingConnection(int handle)
{
qDebug("New client connected");
ServerClient *client = new ServerClient(handle, this); //The constructor takes in the socket descriptor needed to set up the socket and the parent (this)
client->setVectorLocation(clients.count()); //This is a int from a Qvector in which i append the clients, its not important for understanding right now.
connect(client, SIGNAL(clientDisconnected(int)), this, SLOT(clientDisconnected(int)), Qt::QueuedConnection); //When the client socket emits a disconnected signal the ServerClient class emits a client disconnected signal which the server uses to delete that client from the vector (thats why I use "setVectorLocation(int)") - not important right now
clients.push_back(client); //And then I append the client to the QVector - not important right now
}
The ClientServer class constructor just creates a new socket and connects the required methods:
ServerClient::ServerClient(int handle, QObject *parent) :
QObject(parent)
{
socket = new QTcpSocket(this); //Socket is a class variable
connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
socket->setSocketDescriptor(handle);
}
Ready read just writes me the data incoming (it wont be much user later i think):
void ServerClient::readyRead()
{
qDebug() << "Data available, incoming: " << socket->readAll();
}
And finally the write data:
void ServerClient::writeData(QByteArray *data)
{
data->append("\r\n\r\n"); //I have read this must be appended to all outgoing data from a HTTP server
socket->write(*data);
socket->flush();
qDebug() << "Written data to client: " << *data;
}
This code however does not always work. Sometimes when I write message like "Message" the client recieves all the data and some things that shouldnt be there (the new line and a wierd symbol - can NSLog cause this?). Sometimes when I send "Hellow" the client only gets "Hel" and some other funky stuff.
What are the problems? What should I pay more attention about? Anything that will help me will be MUCH appreciated. And please dont paste in some links that contain a book with a few hundred pages, Im sure this can be solved just by explaining things to me.
THANKS A LOT!
Jan.
You asked many questions ... and that's a perfectly legitimate thing to do :)
I confess - it was too long, I didn't read :(
BUT ...
1) Yes, the HTTP protocol does expect na "CRLF" ("\r\n"). Many servers and many clients are "forgiving", but strictly speaking - yes, you need them.
REFERENCE: RFC 2616
2) Wanting to understand HTTP "internals" is also perfectly legitimate - I applaud you.
One good way is to read the RFC(s).
Another is to use a "telnet" client: http://blog.tonycode.com/tech-stuff/http-notes/making-http-requests-via-telnet
Yet another is to study requests and responses in FF Firebug
3) Socket programming is another issue - which explains why sometimes you might read "hello world", and other times you might just get "hel".
Strong recommendation: Beej's Guide to Network Programming
4) Finally, no way would I actually write a server in Qt with C++ (except maybe as a toy "science experiment", or for some really off-the-wall requirement)
I would definitely write server code in C# (for Windows servers), Java (for everything else) or a scripting language I felt comfortable with (Perl, Ruby/RoR, Python and Lua all come to mind).
IMHO .. and hope that helps!
Your questions pretty much amount to "how does HTTP work", and the full answer lies in the specification.

Improve my asyncronous request design

I would like some opinions on a design that i have. My app is starting to send an asynchronous request to get some JSON data and if that goes well i get to my callback method and then start some other asynchronous request for some data then in another callback i go on and on and i feel my code is getting to be like spaghetti code, i jump from one callback method to a request to another callback then request and so on, any ideas of an better design ?
Let me show some example code (not the real code but shows my point) :
-(void)startApp {
//make an request and use callBackMethod to parse data
}
-(void)callBackMethod {
//parse data and check it, if ok go make next request and use CallBackMethod1
}
-(void)callBackMethod1 {
//parse data and check it, if ok go make next request and use CallBackMethod2
}
-(void)callBackMethod2 {
//parse data and check it, if ok go make next request and use CallBackMethod3
}
-(void)callBackMethod3 {
//parse data
}
You get the point. It's a mess after my opinion and i want to refactor the code to something more readable and easier to maintain. I heard about blocks. Not sure how/if that might make my design better.
donnib
Your asynchronous request design is fine, although you should use more descriptive method names. The example here is not really spaghetti code, it's just you're doing something somewhat complicated and the code structure necessarily reflects that.
An implementation using blocks would look something vaguely like this:
- (void)startApp {
[self makeRequest:... completionHandler:^(NSData *data){
// Parse data and check it, as in callBackMethod
if (ok) [self makeRequest:... completionHandler:^(NSData *data){
// Parse data and check it, as in callBackMethod1
if (ok) [self makeRequest:... completionHandler:^(NSData *data){
// Parse data and check it, as in callBackMethod2
if (ok) [self makeRequest:... completionHandler:^(NSData *data){
// Parse data, as in callBackMethod3
}];
}];
}];
}];
}
Depending on the situation, that may or may not be easier to follow. Another alternative, if you control the web service you're querying and the "check" is amenable, is to have the web service do all the checking on its end and return all the data in one response instead of requiring all this back-and-forth.

How is it better to wait an asynchronous method to be finished in iPhone app?

everybody.
I want to understand, how i shoud procceed situations when an asynchronous method has "didFinish:#selector(SEL)" parameter.
My code example is:
//
// Authentication check
- ( void )authenticationSuccess: ( GDataServiceTicket* ) ticket
authenticatedWithError: ( NSError* ) error {
if ( error == nil )
{
NSLog( #"authentication success" );
}
else
{
NSLog( #"authentication error" );
}
}
//
- ( void ) fetchFeedOfSpreadsheets {
//create and authenticate to a google spreadsheet service
if ( !(mService) )
{
GDataServiceGoogleSpreadsheet *service = [self spreadsheetService];
[mService autorelease];
mService = [service retain];
}
// check autentication success ( invoke "authenticationSuccess" method for debug success & error )
[mService authenticateWithDelegate: self
didAuthenticateSelector:#selector(authenticationSuccess:
authenticatedWithError:) ];
// HERE I WANT TO MAKE A PAUSE AND WHAIT THE RESULT, EITHER I AUTHENTICATED OR NOT
// AND MAKE AN "IF" STATEMENT TO CONTINTUE WORKING ON SERVER, OR RETURN ERROR
//fetch retrieves the feed of spreadsheets entries
NSURL *feedURL = [ NSURL URLWithString: kGDataGoogleSpreadsheetsPrivateFullFeed ];
GDataServiceTicket *ticket;
ticket = [mService fetchFeedWithURL: feedURL
delegate: self
didFinishSelector: #selector(spreadsheetsTicket:finishedWithFeed:
error: ) ];
// HERE I WANT TO WAIT SECOND TIME. I WANT "spreadsheetsTicket:
// finishedWithFeed:error:" TO PROCCEED ERROR AND PUT A FEED IN SOME NSARRAY OBJECT
// AND AFTER THAT I WANT TO WORK WITH THAT NSARRAY RIGHT HERE
}
I's clear, that i can push the code i want into the end of "authenticationSuccess" method section, but it's also clear, that it's a wrong a way to solve the proble. There a number of situations like this, where i call an asynchronous method with a selector parameter, and i want to find a solution providing me a flexible code writing.
Thanks in advance.
It's a standard practice in Objective-C to put the code to be executed after the authentication in the authenticationSucess: method. You might not like it, but that is life.
Many people had the same complaint as you, so
on iOS 4 and later, there's something called blocks which allow you to write the code to be executed after the authentication in the method which initiates the authentication, as in
[mService authenticateAndExecute:^{
code to be executed when successfully authenticated ;
} whenError:^{
code to be executed when authentication failed;
} ];
But in this case you need to modify the API, which is possible by using categories. See this blog post by Mike Ash. He has many other posts on blocks on the same blog, which are also very instructive.
If you're going to use a library that works asynchronously (and therefore doesn't block your UI), you should have a good reason for trying to force it to work synchronously.
You should be checking for an authentication error at the end of your authenticationSuccess:authenticatedWithError: method, and calling the next request from there if there's a success. Similarly, in your spreadsheetsTicket:finishedWithFeed:error: check for an error, and continuing processing if there isn't one. It might be a better design to do that continued work in a separate method, but that's up to you.
Is there a specific reason you want to use the GData API in a synchronous fashion?