I want to mock S3, but I seem unable to come up with the Swift equivalent of the following:
- (void)listObjects:(AWSS3ListObjectsRequest *)request completionHandler:(void (^ _Nullable)(AWSS3ListObjectsOutput * _Nullable response, NSError * _Nullable error))completionHandler;
I've tried quite a few alternatives:
// func listObjects(request: AWSS3ListObjectsRequest) -> AWSTask<AWSS3ListObjectsOutput>
// func listObjects(request: AWSS3ListObjectsRequest, completionHandler: (AWSTask<AWSS3ListObjectsOutput>) -> AnyObject?)
func listObjects(request: AWSS3ListObjectsRequest, completionHandler: () -> AWSTask<AWSS3ListObjectsOutput>)
// - (void)listObjects:(AWSS3ListObjectsRequest *)request completionHandler:(void (^ _Nullable)(AWSS3ListObjectsOutput * _Nullable response, NSError * _Nullable error))completionHandler;
ButI can't seem to get one that AWSS3 conforms to. I need to do this to mock the function in Swift.
func listObjects(request: AWSS3ListObjectsRequest, completionHandler: ((AWSS3ListObjectsOutput?, Error?) -> Void)?) {
}
Related
The Facebook places SDK is only available in Objective-C, I am not to good with understanding OBJC and all the documentation on how to use this library is in OBJC. I pod installed the library using cocoa pods.
use_frameworks!
pod 'FBSDKPlacesKit'
my Podfile uses framework so I don't think I would be needing a header file.
[self.placesManager
generatePlacesGraphRequestForSearchTerm:#"pizza"
categories: #[#"FOOD_BEVERAGE"]
fields: #[FBSDKPlacesFieldKeyName,
FBSDKPlacesFieldKeyAbout,
FBSDKPlacesFieldKeyPlaceID]
distance:1000
cursor:nil // Pagination cursor
completion:^(FBSDKGraphRequest * _Nullable graphRequest, CLLocation * _Nullable location, NSError * _Nullable error) {
if (graphRequest) {
[graphRequest startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
// Handle the response.
// The result will contain the JSON for the place search.
}];
}
}];
and
FBSDKGraphRequest *graphRequest = [self.placesManager
placesGraphRequestForLocation:nil
searchTerm:#"pizza"
categories: #[#"FOOD_BEVERAGE"]
fields: #[FBSDKPlacesFieldKeyName,
FBSDKPlacesFieldKeyAbout,
FBSDKPlacesFieldKeyPlaceID]
distance:1000
cursor:nil];
[graphRequest startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
// Handle the response.
// The result will contain the JSON for the place search.
}];
can someone please convert this to Swift, or tell me how to use this in Swift?
I try to serialize several asynchronous network with ReactiveCocoa:
[[[[self.profileView.signInButton rac_signalForControlEvents:UIControlEventTouchUpInside] flattenMap:^__kindof RACSignal * _Nullable(__kindof UIControl * _Nullable value) {
#strongify(self)
return [self.viewModel signInSignal];
}] flattenMap:^__kindof RACSignal * _Nullable(id _Nullable value) {
return [self.viewModel userInfoSignal];
}] subscribeNext:^(id _Nullable x) {
} error:^(NSError * _Nullable error) {
NSLog(#"error");
}];
it works if no network error happens. However, when any error happens and the error block is called, I click the 'signInButton' again but it did not work any more. I want to know the reason and how to fix it. Thanks!
The reason is that Error events are forwarded immediately through the chain of operators and that Error events terminate a subscription.
One way of dealing with this is using the retry operator which resubscribes to the signal when an error occurs. Heres a modified version of your sample using retry:
#weakify(self);
[[[[[[self.button rac_signalForControlEvents:UIControlEventTouchUpInside] flattenMap:^__kindof RACSignal * _Nullable(__kindof UIControl * _Nullable value) {
#strongify(self)
return [self.viewModel signInSignal];
}] flattenMap:^__kindof RACSignal * _Nullable(id _Nullable value) {
return [self.viewModel userInfoSignal];
}] doError:^(NSError * _Nonnull error) {
NSLog(#"Inner Error: %#", error);
}] retry:2]
subscribeNext:^(id _Nullable x) {
NSLog(#"Next: %#", x);
} error:^(NSError * _Nullable error) {
NSLog(#"Error: %#", error);
}];
Here, a variant with a retryCount is used - it will retry 2 times before propagating the error to the outside. Also, doError is used to perform a logging call as side effect when the error happens (Note: This has to be before the retry operator)
Given the signInSignal or userInfoSignal will produce an error 100% of the time, 3 button presses will produce the following output
Inner Error
Inner Error
Inner Error
Error
RACCommand
Another solution I would suggest you take a look at is to encapsulate the logic into a RACCommand (in your viewModel):
_signInCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
return [self.signInSignal flattenMap:^RACSignal *(id value) {
return self.userInfoSignal;
}];
}];
You can link this to your butto as simple as:
self.button.rac_command = self.viewModel.signInCommand;
This way, you don't need to manually handle retry: Every click on the button will invoke the command one time which can either complete successfully or error.
You can handle the side effects of the command via the commands special signals:
[[self.viewModel.signInCommand errors] subscribeNext:^(NSError * _Nullable x) {
NSLog(#"Error: %#", x);
}];
[self.viewModel.signInCommand.executionSignals subscribeNext:^(id _Nullable signal) {
[signal subscribeNext:^(id _Nullable x) {
NSLog(#"Next: %#", x);
}];
}];
One great benefit of using RACCommand this way is that it automatically disables the button while the command is running, so if your signInSignal and userInfoSignal take some time, the button will be automatically disabled in the meantime so that the user can not start the action a second time while its already running.
In the most recent Apple documentation both NSTask and Process have several deprecated methods and properties, although there's nothing marked with an API Availability Macro.
Instance Properties
#property(copy) NSString *launchPath;
#property(copy) NSString *currentDirectoryPath;
var launchPath: String? { get set }
var currentDirectoryPath: String { get set }
Instance Methods
- (void)launch;
func launch()
Type Methods
+ (NSTask *)launchedTaskWithLaunchPath:(NSString *)path
arguments:(NSArray<NSString *> *)arguments;
class func launchedProcess(launchPath path: String,
arguments: [String]) -> Process
There seemingly are no replacements available, so what gives?
There seemingly are no replacements available
There are, the API is now URL related
Instance Properties
#property(copy) NSURL *executableURL;
#property(copy) NSURL *currentDirectoryURL;
var executableURL: URL? { get set }
var currentDirectoryURL: URL? { get set }
Instance Methods
- (BOOL)launchAndReturnError:(out NSError * _Nullable *)error;
func run() throws
Type Methods
+ (NSTask *)launchedTaskWithExecutableURL:(NSURL *)url
arguments:(NSArray<NSString *> *)arguments
error:(out NSError * _Nullable *)error
terminationHandler:(void (^)(NSTask *))terminationHandler;
class func run(_ url: URL,
arguments: [String],
terminationHandler: ((Process) -> Void)? = nil) throws -> Process
Honestly I'm new to Xcode and I have no idea what this means? I'm guessing it's a problem with the code being redundant. I've attempted to remove a few areas of this code but I'm still receiving errors.
Here is the code:
+ (instancetype)executorWithBlock: (void(^)(void(^block)(void))) block {
return [[self alloc] initWithBlock:block];
}
this is the warning message:
Conflicting parameter types in implementation of executorWithBlock:: void (^ _Nonnull __strong)(void (^ _Nonnull __strong)()) vs void (^ _Nonnull __strong)(void (^ _Nonnull __strong)(void))
I must present this completion handler in Swift as variable:
-test:(void(^)(id result, NSError* error))completion;
What must this look like in Swift? Is in this case id == AnyObject and NSError == Error?
id is imported into Swift as Any, NSError * becomes Error? in Swift 3 so your completion handler should read like this in Swift:
func completionHandler(result: Any, error: Error?) {
// Do something
}
obj.test(completionHandler)
Or if you want to define it inline:
let handler = { (result: Any, error: Error?) -> Void in
// Do something
}
obj.test(handler)