Can i change the server url with sudzc? - ios

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 ***

Related

Integrating LogglyLogger-CocoaLumberjack in swift project

I am trying to use LogglyLogger-CocoaLumberjack in my swift project.
I am getting this error in xCode.
Enum case 'verbose' has no associated values
I am unable to resolve this.
https://prnt.sc/uznr01
I am actually trying to translate the Objective-C code in swift 5. Here is my swift function
in appDelegate.swift class
func initLoggly(){
// static const DDLogLevel ddLogLevel = DDLogLevelVerbose;
let ddLogLevel:DDLogLevel = .verbose
// LogglyLogger *logglyLogger = [[LogglyLogger alloc] init];
let logglyLogger = LogglyLogger()
// [logglyLogger setLogFormatter:[[LogglyFormatter alloc] init]];
logglyLogger.logFormatter = LogglyFormatter()
// logglyLogger.logglyKey = #"your-loggly-api-key";
logglyLogger.logglyKey = "XXXXXXXXXXXX-XXXXXX"
//
// // Set posting interval every 15 seconds, just for testing this out, but the default value of 600 seconds is better in apps
// // that normally don't access the network very often. When the user suspends the app, the logs will always be posted.
// logglyLogger.saveInterval = 15;
logglyLogger.saveInterval = 15
// [DDLog addLogger:logglyLogger];
DDLog.add(logglyLogger)
// // Do some logging
// DDLogVerbose(#"{\"myJsonKey\":\"some verbose json value\"}");
// ddLogLevel.verbose("{\"initloggly\":\"some verbose json value\"}") // also tried this, error ==> Enum case 'verbose' cannot be used as an instance member
DDLogLevel.verbose("{\"initloggly\":\"some verbose json value\"}") // Here is the error on this line
}
Please point out what I am doing wrong!
This library is heavly based on C preprocessor macros which aren't accessible from Swift.
You will probably need to write a small set of wrapper functions in Objective-C that use these macros and are in turn callable from Swift.
Here's an example of how this could look like:
LogglyWrapper.h:
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
#interface LogglyWrapper : NSObject
+(void) logVerbose:(NSString*) msg;
#end
NS_ASSUME_NONNULL_END
and LogglyWrapper.m:
#import "LogglyWrapper.h"
#import <LogglyLogger.h>
#implementation LogglyWrapper
static const DDLogLevel ddLogLevel = DDLogLevelVerbose;
+(void) logVerbose:(NSString*) msg {
DDLogVerbose(#"%#", msg);
}
#end
usage from Swift:
LogglyWrapper.logVerbose("foo")

Upload file to Node.js server using Socket.io-stream from iOS

I'm writing a native iOS client to interact with a Node.js server using the Socket.IO-objc wrapper. I'm currently able to send individual events to the server just fine. However, the server is using Socket.IO-stream to handle upload file streams, and I need to make my iOS code interact with it somehow. My socket.io wrapper doesn't seem to have any relevant API for accomplishing this. The receiving server.js code is like:
io.sockets.on('connection', function (socket) {
console.log("connection occurring");
ss(socket).on('uploadFile', function (stream, data, callback) {
//...I can't get a 'stream' to this event for it to work with
});
socket.on('passwordLogin', function (data, callback) {
//...I can cause these kind of events just fine
});
//...other event declarations
}
I typically call events in this manner, and it works fine for 'socket.on' declared events:
[_socket sendEvent:#"passwordLogin"
withData:#{...login info...}
andAcknowledge:aCallbackBlock];
I figure I need to expand Socket.IO-objc, unless there is something I'm missing, with something like:
//TODO: Attempt to expand SocketIO to include streams.
- (void) sendEvent:(NSString *)eventName withStream:(NSStream*) stream withData:(id) data andAcknowledge:(SocketIOCallback) function
{
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObject:eventName forKey:#"name"];
// do not require arguments
if (data != nil) {
[dict setObject:[NSArray arrayWithObject:data] forKey:#"args"];
}
SocketIOPacket *packet = [[SocketIOPacket alloc] initWithType:#"event"];
packet.data = [SocketIOJSONSerialization JSONStringFromObject:dict error:nil];
packet.pId = [self addAcknowledge:function];
//Is this even a valid approach?
packet.stream = stream;//<--NEW BIT
if (function) {
packet.ack = #"data";
}
[self send:packet];
}
I'm pretty lost as to what exactly to do, having never really worked with server communications before. I've followed Apple documentation about the built-in NSStream and CFStream objects, but it doesn't seem to get me any closer to interacting with the server's event. Any help is appreciated, as I'm a bit at my wit's end.

Conditional IF/ELSE statements in iOS Constants File

Fellow Coders...
I have server url's set up in my application's global constants file.
I also have a variable called "DebugMode" in my application plist that once switched should change the urls the application will be using.
Constants.h
extern NSString * const LOGIN_URL;
Constants.m
NSString * const LOGIN_URL = #"http://www.url.com";
Anyway I can replicate the following psuedo code below into Objective C?
if([[[[NSBundle mainBundle] infoDictionary] objectForKey:#"DebugMode"] boolValue] == NO)
{
NSString * const LOGIN_URL = #"http://www.production-url.com";
}
else
{
NSString * const LOGIN_URL = #"http://www.qa-url.com";
}
What your asking for isn't exactly possible (at least not in the way your asking for). A constant is setup and established whilst compiling (not strictly true, but for the sake of this explanation, it will do) and thus means that it can not be mutated for any reason at runtime.
The traditional way of changing the values of constants depending on debug and release code is through the preprocessor. Like so:
#if __DEBUG_MODE__ == 1
NSString * const LOGIN_URL = #"http://www.qa-url.com";
#else
NSString * const LOGIN_URL = #"http://www.production-url.com";
#endif
Now __DEBUG_MODE__ needs to be defined before it can do anything, and there are a few ways you could do this. You could add the following line to you prefix header file (.pch)
#define __DEBUG_MODE__ 1 // Change to 0 to disable debug mode.
or add the compiler flag -M__DEBUG_MODE__=1 to the file you wish to effect. This means that whenever __DEBUG_MODE__ is set with a value of 1, the compiler will use your debug constant, and when it has a value of 0 the compiler will use the production constant.
This also has the benefit of keeping debug and production code separate (you should avoid having both in your binary as it can open a whole world of problems and security issues).
Hope this helps.
Whenever I've had a situation like this I've just created a class method in my constants file:
+ (NSString *)loginURL {
if([[[[NSBundle mainBundle] infoDictionary] objectForKey:#"DebugMode"] boolValue] == NO){
return #"http://www.production-url.com";
}
else {
return #"http://www.qa-url.com";
}
}
It also makes it more clear in your code that as the loginURL string is coming via a method, it may be dependent on a run time condition:
NSURL *loginURL = [NSURL URLWithString:[Constants loginURL]];

RestKit Mapping objects within a default relationship using a specified primary key reference

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: #""];

Amazon AWS IOS SDK: How to list ALL file names in a FOLDER

I'm using AWS IOS SDK and trying to list all the files in a FOLDER.
This code works to list all files etc in a BUCKET:
-(void) s3DirectoryListing: (NSString *) bucketName {
s3Client = [[AmazonS3Client alloc] initWithAccessKey:ACCESS_KEY withSecretKey:SECRET_KEY];
#try {
S3ListObjectsRequest *req = [[S3ListObjectsRequest alloc] initWithName:bucketName];
S3ListObjectsResponse *resp = [s3Client listObjects:req];
NSMutableArray* objectSummaries = resp.listObjectsResult.objectSummaries;
for (int x = 0; x < [objectSummaries count]; x++) {
NSLog(#"objectSummaries: %#",[objectSummaries objectAtIndex:x]);
}
}
#catch (NSException *exception) {
NSLog(#"Cannot list S3 %#",exception);
}
}
So if I pass a bucketName name, this works. However if I try and pass bucketName/folderName" I get an error message. This code doesn't seem to like the combination of bucket and folder path combinations.
Any ideas appreciated.
Amazon S3 is a "flat" file system, meaning it does not have physical folders. "Folders" as you know are simply prefixes added to file names.
You need to set the prefix property to your request (see the documentation)
For example, given the following set of files:
folderName1/fileNameA.txt
folderName1/fileNameB.txt
folderName2/folderName3/fileNameC.txt
If you set prefix with folderName1, and your delimiter with /, you should get only the first two entries.
Last, but not least, leave your bucketName only with the bucket name :)
More info at the S3 Developer Guide.

Resources