Missing argument for parameter #1 in call - objective-c

I am doing a Obj-C to Swift Conversion, and am hitting a roadblock. I am getting the error 'Missing argument for parameter #1 in call' after calling
self.tabataTimerUpdated() //error
This function that is being called (which I converted to swift) is:
func tabataTimerUpdated(NSNotification) {
self.showTime()
}
Here is what it looks like in it's original Obj-C form:
- (void)tabataTimerUpdated:(NSNotification *)notification {
[self showTime];
}
Where did I go wrong in the conversion, and how can I fix it? Thanks.

You get the error because you have
func tabataTimerUpdated(NSNotification) {
}
try remove NSNotification, look like this:
func tabataTimerUpdated() {
}
or specify something in there, like this:
func tabataTimerUpdated(notification: NSNotification){
}
and when you call the function, use:
self.tabataTimerUpdated(yourNotificationVariableInHere)

Related

#objc func expression resolves to an unused function

I'm new to swift and trying to call a method when the user presses some hotkey shortcut.
I have the following code: https://pastebin.com/pF8wk7jL
I'm trying to run togglePopover on this handler: hotKey.keyDownHandler.
This:
hotKey.keyDownHandler = {
self.togglePopover(_:)
}
returns the error "Expression resolves to an unused function"
and this:
hotKey.keyDownHandler = {
let call = self.togglePopover(_:)
call(_:)
}
returns the error "Cannot find call in scope".
Cannot fix the issue, can someone help?
If I do:
hotKey.keyDownHandler = {
print("teste")
}
works good!

Objective C Array completionHandler used in Swift

I have a completion handler in a framework written in Objective C...
This is a typedef for a block type. It takes an array of PHErrors.
typedef void (^PHBridgeSendErrorArrayCompletionHandler)(NSArray *errors);
When I try to use this in Swift, I'm doing....
anObject.aMethod(completionHandler: { (errors: [ AnyObject?]) -> () in
...rest of code
}
But I keep getting this error:
Cannot convert value of type '([AnyObject?]) -> ()' to expected argument type 'PHBridgeSendErrorArrayCompletionHandler!'
Can anyone help, I'm baffled, it looks like it should work to me.
Or better yet, you can still use your typedef as typealias.
DEFINE
typealias PHBridgeSendErrorArrayCompletionHandler = (_ errors: [Error]?) -> Void
IMPLEMENTATION
func myFunctionWithErrorCompletion(completion: PHBridgeSendErrorArrayCompletionHandler) {
// Define empty array to add errors to
var errors:[Error]?
// Do Your Logic that may store errors to array
// Completion and pass errors
completion(errors)
}
USAGE
func anotherOfMyFunctions() {
// Call the function
myFunctionWithErrorCompletion { (errors) in
if let completionErrors = errors {
// React to errors
}
}
}
anObject.aMethod(completionHandler: { (errors: [ AnyObject?]) -> () in
}
should be
anObject.aMethod() { errors in
}
In order to dig any deeper, I have to know what PHBridgeSendErrorArrayCompletionHandler is
So my friend solved this problem by simply changing AnyObject to Any
(errors: [Any]?) in
Which baffles me because all objects in an NSArray are objects! So didn't think to try Any.
Im pretty new to Swift mind
Try this..
anObject.aMethod(completionHandler: { (errors:NSArray?) -> () in
...rest of code
}

Macros with return value

I'm trying to reproduce this pattern in Swift
#define mustBeKindOfClassFailedReturn(object, objectClass, ret) \
if(![object isKindOfClass:objectClass]) { \
NSLog(([NSString stringWithFormat:#"%# must be kind of %# class, current class is %#", object, NSStringFromClass(objectClass), NSStringFromClass([object class])])) \
return ret; }
used like this
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
insetForSectionAtIndex:(NSInteger)section {
mustNotBeNilFailedReturn(self.adapter, UIEdgeInsetsZero)
mustBeKindOfClassFailedReturn(self.adapter, [WBCollectionViewSectionAdapter class], UIEdgeInsetsZero)
Does anyone know a good solution to this?
Edit
I know about guard but using guard i have to rewrite a lot of code each time i'll have to override a method in my subclasses for exemple
/**
* mustOverride
*/
#define mustOverride \
{ NSLog(#"You must override this function") }
#define mustOverrideFailedReturn(ret) \
{ mustOverride \
return ret; }
EDIT 2
I've ended with solution is it the optimal one ?
func needOverride(function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__) -> Bool {
REVLogManager.SharedInstance.logErrorMessage("You must override this function", function: function, file: file, line: line, exception: nil, error: nil)
return false
}
func doesObject(function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__, matchingObject: AnyObject!, matchesClass matchingClass: AnyClass) -> Bool {
guard matchingObject.isKindOfClass(matchingClass) else {
let message = "\(matchingObject) must be kind of \(matchingClass) class, current class is \(matchingObject.dynamicType)"
REVLogManager.SharedInstance.logErrorMessage(message, function: function, file: file, line: line, exception: nil, error: nil)
return false
}
return true
}
I'm calling the method like this
public func actualScrollOffsetDistanceWithScrollView(scrollView: UIScrollView!) -> Float {
guard needOverride() else { return 0.0 }
return 0.0
}
And
guard doesObject(matchingObject: self, matchesClass: REVListSectionAdapter.classForCoder()) else { return }
Swift doesn't have a macro capability of this kind.
In terms of accomplishing your goal. The pattern you are following would most correctly be handled using guard statements. A function containing a guard statement must exit the enclosing scope (or trap) and may do so with a return.
Please check the Swift documentation for information about Control Flow and Early Exit control
My answer follows the same legacy pattern using in Swift. You can use classForCoder, but I prefer dynamicType for type checking.
func mustBeKindOfClassFailedReturn(object: AnyObject, objectClass: AnyClass, returnVal: Any?) {
if !object.isKindOfClass(objectClass) {
print("\(object) must be kind of \(objectClass) class, current class is \(object.dynamicType)")
return returnVal
}
return nil // or UIEdgeInsetsZero, or whatever
}
You may also get similar results with !(object is objectClass), but things get tricky when comparing certain number types. See Swift type inference and type checking issue
You can also replace AnyObject and Any with NSObject if you know you're dealing with Objective-C types. From your comment it seems like ret could be a value type, so that's why I make it an Any type.
Swift has a better solution for this kind of problem, the guard statement. In this case, just put this in your method.
guard let adapter = self.adapter as? WBCollectionViewSectionAdapter else {
/* return value if the adapter is not setup properly. */
return .Zero
}
/* continue with valid and correctly classed adapter */
If you're looking for a way to handle this for sub classes, you may want to consider generics. It will allow you implicit type safety without having to rewrite logic in your subclasses.

Having trouble converting a simple Objective-C block to Swift

Not sure what I'm doing wrong. I'm using this module https://github.com/wenzhaot/InstagramPhotoPicker (the header file for the block is here https://github.com/wenzhaot/InstagramPhotoPicker/blob/master/TWPhotoPicker/TWPhotoPickerController.h)
In Objective-C, the syntax is:
photoPicker.cropBlock = ^(UIImage *image) {
//do something
};
I tried converting it to swift, but I'm getting an error
photoPicker.cropBlock{ (image:UIImage) -> () in
//Do something
//error: cannot invoke 'cropBlock' with an argument list of type '((UIImage) -> ())'
}
How to get it to work?
You're just missing = sign. Also image is implicitly unwrapped optional:
photoPicker.cropBlock = { (image: UIImage!) -> () in
//Do something
}
or
photoPicker.cropBlock = { image in
//Do something
}

iap - conversion from objective c to swift

I'm trying to convert my app from objective c to swift, and i have everything except for the in app purchase working.
i have the objective c helper class imported in the project, but i'm having trouble doing the RequestProductsCompletionHandler section
in the old objective c version i have the code
[[MTIAPHelper sharedInstance] requestProductsWithCompletionHandler:^(BOOL success, NSArray *products) {
if (success) {
_products = products;
if([[self appData] isPro] == FALSE)
[[self bUpgrade] setUserInteractionEnabled:TRUE];
}
}];
and i'm trying to convert this section to objective c but so far i've been unable to convert the requestProductsWithCompletionHandler part
can anyone help?
i've tried creating the completion handler the same was as in objective c using
requestProductsWithCompletionHandler(sucess: Bool, products : NSArray)
but i get the compiler errors "Extra argument 'products' in call" and "Expected member name or constructor call after type name".
if i try it without the parameters i get "Missing argument for parameter #1 in call"
In Swift, your completion handler would be a closure. The syntax is semi-similar to blocks in Objective-C but, instead of defining the parameters outside the block:
^(BOOL success, NSArray *products) { /* ... */ }
you define them inside the closure:
{ (success: Bool, products: [AnyObject]!) in /* ... */ }
So, your call to requestProductsWithCompletionHandler should look something like this:
MTIAPHelper.sharedInstance().requestProductsWithCompletionHandler {
(success: Bool, products: [AnyObject]!) in
if success {
// etc.
}
}
You can also let Swift infer the parameter types for you:
MTIAPHelper.sharedInstance().requestProductsWithCompletionHandler {
(success, products) in
if success {
// etc.
}
}