RxCocoa RxSwift 'debounce' is deprecated: Use DispatchTimeInterval overload instead - rx-swift

How to convert deprecated debounce code to use DispatchTimeInterval?
Here is the deprecated code:
self.myObservable.asDriver().debounce(2).drive(onNext: {(v) in
doSomething()
}).disposed(by: self.disposeBag)

I expect you already solved this yourself, but...
self.myObservable.asDriver().debounce(.seconds(2)).drive(onNext: {(v) in
doSomething()
}).disposed(by: self.disposeBag)

Related

Does "Accept Interfaces" break deprecation tooling?

Deprecation
The supported way of marking functions as deprecated is something like this:
type MyStruct struct {
}
// MyFunc returns hello
// Deprecated: Use YourFunc
func (m MyStruct) MyFunc() string {
return "hello"
}
Modern IDEs will highlight any usages of this function and linters might also raise warnings (I haven't personally checked this)
Accept interfaces. Return structs.
A popular best practise is "Accept interfaces. Return structs." - which tends to encourage SOLID design in software.
However, the following code - which follows this best practise - conceals the deprecation warning:
// MyInterface specifies a single function that we require from a dependency
type MyInterface interface {
MyFunc() string
}
func main() {
var v MyInterface
v = MyStruct{}
v.MyFunc()
}
Question
Is there a solution to this problem?
If I were, for example, a library maintainer: how can I ensure that my deprecation warnings are seen by users of the library who are also following best practises and defining their own dependency interfaces.
That seems logical since the method of the interface has not been deprecated. Adding the Deprecated: line to the interface function might help in this case (didn't test, since VSCode doesn't do this yet).
// MyInterface specifies a single function that we require from a dependency
type MyInterface interface {
// Deprecated: use YourFunc
MyFunc() string
}
In this case, because the interface only has 1 function you should deprecated the whole thing. Which I know is supported by godoc/pkg.go.dev, take Queryer for example.
// MyInterface specifies a single function that we require from a dependency
// Deprecated: use YourInterface
type MyInterface interface {
MyFunc() string
}

RxJS 6.5.5 startWith deprecated. Alternative

Update Angular to 9th version and occurred on startWith function stay deprecated. The documentation linked to AsyncScheduler class, but how to use it in my simple case I can't figure out:
private subscribeFilters(): void {
this.filters.valueChanges
.pipe(
startWith(this.filters.value),
pairwise(),
)
.subscribe(([prev, next]: [any, any]) => {
if (JSON.stringify(prev) !== JSON.stringify(next)) {
this.loadPage();
}
});
}
As you can see I'm using startWith for setting the filter initial state and exclude redundantly requests in the first time page load.
How I can implement the same logic without startWith. Perhaps as the documentation says with AsyncScheduler or another way?
I think this.filters or this.filters.value is any, that causes the issue because any matches SchedulerLike.
Try to type them correctly, then it won't be detected as SchedulerLike anymore and the notice should be gone.

RxSwift: Using BehaviorRelay I get this error: Instance method 'concatMap' requires that '[Int]' conform to 'ObservableConvertibleType'

I'm trying to use concatMap on BehaviorRelay but I'm getting this error:
Instance method 'concatMap' requires that '[Int]' conform to 'ObservableConvertibleType'
This is my implementation:
class MyClass{
var disposeBag = DisposeBag()
var subject: BehaviorRelay<[Int]> = BehaviorRelay(value: [1,2,3,4,5])
func doSomething() {
subject.asObservable().concatMap { $0 }
.subscribe { print($0) }
.disposed(by: disposeBag)
}
}
I'm getting the error on this line:
subject.asObservable().concatMap { $0 }
Any of you knows why I'm getting this error or how can fix this error on my implementation ?
I'll really appreciate your help.
The problem here is conceptual. It doesn't make any sense to use concatMap on an array of Ints. The error is basically telling you that an array of Ints is not an Observable. There aren't any Observables to concat here.
You need to go back and think about what you are trying to accomplish and find the right operator for the job.

'#selector' refers to a method that is not exposed to Objective-C

The new Xcode 7.3 passing the parameter via addTarget usually works for me but in this case it's throwing the error in the title. Any ideas? It throws another when I try to change it to #objc
Thank you!
cell.commentButton.addTarget(self, action: #selector(FeedViewController.didTapCommentButton(_:)), forControlEvents: UIControlEvents.TouchUpInside)
The selector it's calling
func didTapCommentButton(post: Post) {
}
In my case the function of the selector was private. Once I removed the private the error was gone. Same goes for fileprivate.
In Swift 4
You will need to add #objc to the function declaration. Until swift 4 this was implicitly inferred.
You need to use the #objc attribute on didTapCommentButton(_:) to use it with #selector.
You say you did that but you got another error. My guess is that the new error is that Post is not a type that is compatible with Objective-C. You can only expose a method to Objective-C if all of its argument types, and its return type, are compatible with Objective-C.
You could fix that by making Post a subclass of NSObject, but that's not going to matter, because the argument to didTapCommentButton(_:) will not be a Post anyway. The argument to an action function is the sender of the action, and that sender will be commentButton, which is presumably a UIButton. You should declare didTapCommentButton like this:
#objc func didTapCommentButton(sender: UIButton) {
// ...
}
You'll then face the problem of getting the Post corresponding to the tapped button. There are multiple ways to get it. Here's one.
I gather (since your code says cell.commentButton) that you're setting up a table view (or a collection view). And since your cell has a non-standard property named commentButton, I assume it's a custom UITableViewCell subclass. So let's assume your cell is a PostCell declared like this:
class PostCell: UITableViewCell {
#IBOutlet var commentButton: UIButton?
var post: Post?
// other stuff...
}
Then you can walk up the view hierarchy from the button to find the PostCell, and get the post from it:
#objc func didTapCommentButton(sender: UIButton) {
var ancestor = sender.superview
while ancestor != nil && !(ancestor! is PostCell) {
ancestor = view.superview
}
guard let cell = ancestor as? PostCell,
post = cell.post
else { return }
// Do something with post here
}
Try having the selector point to a wrapper function, which in turn calls your delegate function. That worked for me.
cell.commentButton.addTarget(self, action: #selector(wrapperForDidTapCommentButton(_:)), forControlEvents: UIControlEvents.TouchUpInside)
-
func wrapperForDidTapCommentButton(post: Post) {
FeedViewController.didTapCommentButton(post)
}
As you know selector[About] says that Objective-C runtime[About] should be used. Declarations that are marked as private or fileprivate are not exposed to the Objective-C runtime by default. That is why you have two variants:
Mark your private or fileprivate method declaration by #objc[About]
Use internal, public, open method access modifier[About]

Issue between override and non-override function in swift

Sorry I'm not very good at explaining this stuff. Basically I have the function below to handle remote control events.
UIApplication.sharedApplication().beginReceivingRemoteControlEvents()
override func remoteControlReceivedWithEvent(event: UIEvent) {
if event.type == UIEventType.RemoteControl {
if event.subtype == UIEventSubtype.RemoteControlPlay {
stream.play()
} else if event.subtype == UIEventSubtype.RemoteControlPause {
stream.stop()
} else if event.subtype == UIEventSubtype.RemoteControlTogglePlayPause {
toggle()
}
}
}
Essentially, when I use the term "override" (shown above), I get the error
"Method does not override any method from its superclass.
If I leave out the "override", I get the error:
"Method 'remoteControlReceivedWithEvent' with Objective-C selector 'remoteControlReceivedWithEvent:' conflicts with method "remoteControlReceivedWithEvent" from superclass "UIResponder" with the same Objective-C selector.
I'm pretty new to all of this so I don't really understand what the issue is. Can someone please explain how to remedy this issue? Let me know if you need some more code or something.
Is there more code I have to use to set this up?
There is a mismatch of UIResponder method signature and your function implementation. UIResponder has optional Event as following:
func remoteControlReceibedWithEvent(_ event: UIEvent?)
So it can not override as there is no function with non-optional argument, but if you remove override it will conflict with ObjC implementation, as selector names are the same.

Resources