Combine publisher bridges for UIKit

Related tags

UI hacktoberfest
Overview

CombineCocoa



Build Status
CombineCocoa supports CocoaPods CombineCocoa supports Swift Package Manager (SPM) CombineCocoa supports Carthage

CombineCocoa attempts to provide publishers for common UIKit controls so you can consume user interaction as Combine emissions and compose them into meaningful, logical publisher chains.

Note: This is still a primal version of this, with much more to be desired. I gladly accept PRs, ideas, opinions, or improvements. Thank you ! :)

Basic Examples

Check out the Example in the Example folder. Open the project in Xcode 11 and Swift Package Manager should automatically resolve the required dependencies.

Usage

tl;dr:

import Combine
import CombineCocoa

textField.textPublisher // AnyPublisher
   
segmented.selectedSegmentIndexPublisher // AnyPublisher
   
slider.valuePublisher // AnyPublisher
   
button.tapPublisher // AnyPublisher
   
barButtonItem.tapPublisher // AnyPublisher
   
switch.isOnPublisher // AnyPublisher
   
stepper.valuePublisher // AnyPublisher
   
datePicker.datePublisher // AnyPublisher
   
refreshControl.isRefreshingPublisher // AnyPublisher
   
pageControl.currentPagePublisher // AnyPublisher
   
tapGesture.tapPublisher // AnyPublisher
   
pinchGesture.pinchPublisher // AnyPublisher
   
rotationGesture.rotationPublisher // AnyPublisher
   
swipeGesture.swipePublisher // AnyPublisher
   
panGesture.panPublisher // AnyPublisher
   
screenEdgePanGesture.screenEdgePanPublisher // AnyPublisher
   
longPressGesture.longPressPublisher // AnyPublisher
   
scrollView.contentOffsetPublisher // AnyPublisher
   
scrollView.reachedBottomPublisher(offset:) // AnyPublisher
   

Installation

CocoaPods

Add the following line to your Podfile:

pod 'CombineCocoa'

Swift Package Manager

Add the following dependency to your Package.swift file:

.package(url: "https://github.com/CombineCommunity/CombineCocoa.git", from: "0.2.1")

Carthage

Add the following to your Cartfile:

github "CombineCommunity/CombineCocoa"

Future ideas

  • Support non UIControl.Event-based publishers (e.g. delegates).
  • ... your ideas? :)

Acknowledgments

License

MIT, of course ;-) See the LICENSE file.

The Apple logo and the Combine framework are property of Apple Inc.

Comments
  • Missing required module 'Runtime'

    Missing required module 'Runtime'

    I've added CombineCocoa as an SPM dependency to an app being developed in Xcode 12 that supports iOS 13+.

    When I add "import CombineCocoa" to a table view cell, it is highlighted in red and says "Missing required module 'Runtime'"

    bug 
    opened by brandtdaniels 13
  • Add `UITextView.valuePublisher`

    Add `UITextView.valuePublisher`

    This PR adds support for a UITextView.valuePublisher publisher based on the one in RxCocoa and NSTextStorage (based on @jdisho's delegate proxy support).

    Closes #19

    Control 
    opened by freak4pc 11
  • Using private handleEvent API

    Using private handleEvent API

    Describe the bug I get an error while trying to upload a binary to Testflight

    The app references non-public selectors in Payload/XXX.app/Frameworks/CombineCocoa.framework/CombineCocoa: handleEvent
    

    To Reproduce Steps to reproduce the behavior:

    1. Include CombineCocoa (using cocoapods in my case)
    2. Archive and upload to Testflight

    Expected behavior No error when distributing

    Device:

    • XCode 14.0.1
    • CombineCocoa version 0.4.0
    bug 
    opened by mandarin6b0 10
  • Big issue with the delegate proxies

    Big issue with the delegate proxies

    It seems that a delegate proxy can only be used on one item of its kind at a time.

    For example in this screen, there are two view controllers, both have a UISearchBar. The one in the main view controller works completely fine, but the one on the half-modal (that has focus) doesn't do anything, none of the new publishers (for example searchBar.textDidChangePublisher) fire. Until I remove the delegate publishers from the other search bar, and then it works in the modal.

    Screen Shot 2020-10-06 at 14 21 03 bug 
    opened by kevinrenskers 9
  • UIScrollView+Combine

    UIScrollView+Combine

    I am not sure if this extension is relevant to this lib, but is worth trying 😊

    1. Creating contentOffsetPublisher just because of contentOffset in RxCocoa
    2. Creating reachedBottomPublisher(offset:), which is a publisher, emitting if the bottom of the UIScrollView is reached. Similar to what we have in RxSwiftExt
    Control 
    opened by jdisho 9
  • fix: build failure

    fix: build failure

    For some reason it can be built separately, but building it as a dependency fails Screenshot 2021-06-22 at 00 33 55

    Also, I don't want to be toxic, but I'd like to mention that this indentation

    public init(
        control: Control,
        events: Control.Event
    ) {
        self.control = control
        self.controlEvents = events
    }
    

    looks more native to Combine, SwiftUI and Swift in general than this

    public init(control: Control,
                events: Control.Event) {
        self.control = control
        self.controlEvents = events
    }
    

    which is more like objc indentation, and it makes me sad πŸ₯² maybe you should update your styleguides πŸ˜…

    opened by maximkrouk 6
  • Added `UISearchBar` Combine publishers

    Added `UISearchBar` Combine publishers

    There seem to be a lot of changes in CombineCocoa.xcodeproj, maybe we're having an Xcode version mismatch or something? Feel free to take only UISearchBar+Combine.swift.

    opened by kevinrenskers 6
  • Can't create my own delegate-based publishers

    Can't create my own delegate-based publishers

    I'm trying to add some publishers to UISearchBarDelegate like this:

    extension UISearchBar {
      var searchBarSearchButtonClicked: AnyPublisher<UISearchBar, Never> {
        let selector = #selector(UISearchBarDelegate.searchBarSearchButtonClicked(_:))
    
        return delegateProxy
          .interceptSelectorPublisher(selector)
          .map { $0[1] as! UISearchBar }
          .eraseToAnyPublisher()
      }
    
      private var delegateProxy: UISearchBarDelegateProxy {
          .createDelegateProxy(for: self)
      }
    }
    
    private class UISearchBarDelegateProxy: DelegateProxy, UISearchBarDelegate, DelegateProxyType {
      func setDelegate(to object: UISearchBar) {
        object.delegate = self
      }
    }
    

    Sadly I am getting two compiler errors:

    'interceptSelectorPublisher' is inaccessible due to 'internal' protection level

    and

    Cannot inherit from non-open class 'DelegateProxy' outside of its defining module

    Screen Shot 2020-10-01 at 13 50 29

    bug 
    opened by kevinrenskers 6
  • UIGestureRecognizer publisher

    UIGestureRecognizer publisher

    Have you considered adding a publisher for gesture recognisers? Would be neat.

    I’m happy to have a look at adding myself, just wanted to raise the issue to track.

    opened by mattjgalloway 6
  • Work around canImport(Combine) being broken in Xcode 13

    Work around canImport(Combine) being broken in Xcode 13

    Fixes: https://github.com/CombineCommunity/CombineCocoa/issues/56

    Applying the same fix as used by the Realm project. Its not pretty but it does the job to maintain compatibility with iOS 10

    Xcode 13 beta 3 added a swiftinterface file for armv7 Combine which makes canImport(Combine) return true, but the swiftinterface file doesn't actually compile (and no armv7 devices can run OS versions with Combine). Work around this by replacing the canImport(Combine) checks with a define we manually set when building for armv7.

    realm/realm-cocoa#7401

    opened by bpollman 5
  • Combine Cocoa fails to archive with Xcode 13 RC

    Combine Cocoa fails to archive with Xcode 13 RC

    Describe the bug When we try to archive a project which has CombineCocoa as a dependency, the archive fails. The following error is generated. Instance method 'subscribe(on:options:)' requires that 'DispatchQueue' conform to 'Scheduler' To Reproduce Steps to reproduce the behavior:

    1. Add CombineCocoa as a dependency
    2. Archive a project

    Expected behavior The archive should be generated

    Actual behavior Getting the error Instance method 'subscribe(on:options:)' requires that 'DispatchQueue' conform to 'Scheduler'

    Screenshots Screenshot 2021-09-20 at 7 47 52 PM

    bug 
    opened by rizwan95 5
  • Forward delegate

    Forward delegate

    Fixes #81 by supporting forwarding delegate method calls similar to RxCocoa's setDelegate.

    RxCocoa setDelegate example. https://github.com/ReactiveX/RxSwift/blob/1a1fa37b0d08e0f99ffa41f98f340e8bc60c35c4/RxExample/RxExample/Examples/SimpleTableViewExampleSectioned/SimpleTableViewExampleSectionedViewController.swift#L68

    opened by shinichy 0
  • tableView(_:viewForHeaderInSection:) delegate method cannot be used

    tableView(_:viewForHeaderInSection:) delegate method cannot be used

    Describe the bug tableView(_:viewForHeaderInSection:) delegate method cannot be used when using tableView.didEndScrollingAnimationPublisher.

    To Reproduce

    class MyViewController: UIViewController {
        @IBOutlet private weak var tableView: UITableView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            
            tableView.didEndScrollingAnimationPublisher
                .sink { print("didEndScrollingAnimation") }
        }
    }
    
    extension MyViewController: UITableViewDelegate {
        func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
            // return my header view
        }
    }
    

    MyViewController is configured as a delegate of tableView in a storyboard.

    Expected behavior tableView(_:viewForHeaderInSection:) is called

    Device:

    • Device: iPhone 14
    • OS: iOS 16
    • 0.4.1

    Additional context RxCocoa supports this by calling tableView.rx.setDelegate(viewController).

    bug 
    opened by shinichy 1
  • UICollctionView did not work as expected. When I use colltionView to listen to both didScollPublish and didSelectedItemPublisher

    UICollctionView did not work as expected. When I use colltionView to listen to both didScollPublish and didSelectedItemPublisher

    UICollctionView did not work as expected. When I use colltionView to listen to both didScollPublish and didSelectedItemPublisher, they will not work at the same time and the first declaration will not work.

    Simple case is as follows:

    // NotWork collectionView.didScrollPublisher.sink { [weak self] _ in OMPrint("didScroll NotWork!" ) } .store(in: &cancellables)

    // Work collectionView. DidSelectItemPublisher. Sink {indexPath in OMPrint("didSelectItem Work!" ) } .store(in: &cancellables)

    bug 
    opened by SumiaFish 0
  • Bump tzinfo from 1.2.7 to 1.2.10

    Bump tzinfo from 1.2.7 to 1.2.10

    Bumps tzinfo from 1.2.7 to 1.2.10.

    Release notes

    Sourced from tzinfo's releases.

    v1.2.10

    TZInfo v1.2.10 on RubyGems.org

    v1.2.9

    • Fixed an incorrect InvalidTimezoneIdentifier exception raised when loading a zoneinfo file that includes rules specifying an additional transition to the final defined offset (for example, Africa/Casablanca in version 2018e of the Time Zone Database). #123.

    TZInfo v1.2.9 on RubyGems.org

    v1.2.8

    • Added support for handling "slim" format zoneinfo files that are produced by default by zic version 2020b and later. The POSIX-style TZ string is now used calculate DST transition times after the final defined transition in the file. The 64-bit section is now always used regardless of whether Time has support for 64-bit times. #120.
    • Rubinius is no longer supported.

    TZInfo v1.2.8 on RubyGems.org

    Changelog

    Sourced from tzinfo's changelog.

    Version 1.2.10 - 19-Jul-2022

    Version 1.2.9 - 16-Dec-2020

    • Fixed an incorrect InvalidTimezoneIdentifier exception raised when loading a zoneinfo file that includes rules specifying an additional transition to the final defined offset (for example, Africa/Casablanca in version 2018e of the Time Zone Database). #123.

    Version 1.2.8 - 8-Nov-2020

    • Added support for handling "slim" format zoneinfo files that are produced by default by zic version 2020b and later. The POSIX-style TZ string is now used calculate DST transition times after the final defined transition in the file. The 64-bit section is now always used regardless of whether Time has support for 64-bit times. #120.
    • Rubinius is no longer supported.
    Commits
    • 0814dcd Fix the release date.
    • fd05e2a Preparing v1.2.10.
    • b98c32e Merge branch 'fix-directory-traversal-1.2' into 1.2
    • ac3ee68 Remove unnecessary escaping of + within regex character classes.
    • 9d49bf9 Fix relative path loading tests.
    • 394c381 Remove private_constant for consistency and compatibility.
    • 5e9f990 Exclude Arch Linux's SECURITY file from the time zone index.
    • 17fc9e1 Workaround for 'Permission denied - NUL' errors with JRuby on Windows.
    • 6bd7a51 Update copyright years.
    • 9905ca9 Fix directory traversal in Timezone.get when using Ruby data source
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
Releases(0.4.1)
  • 0.4.1(Oct 20, 2022)

  • 0.4.0(Oct 7, 2021)

  • 0.3.0(May 30, 2021)

    • DelegateProxy now supports multiple subscriptions to a single delegate #47
    • Add didBeginEditingPublisher #45
    • Remove generated module map to support Carthage #40
    • Fix UIPageControl.currentPagePublisher emitting only once #36
    Source code(tar.gz)
    Source code(zip)
  • 0.2.2(Nov 21, 2020)

  • 0.2.1(Oct 6, 2020)

  • 0.2.0(Sep 27, 2020)

    It's been a long time since the latest release, but this one is a packed one, covering a lot of missing necessities this project aimed to achieve early on. Also - better late than never, right? πŸ˜„

    Thanks to the various contributors that made this release so great! πŸ‘πŸ‘πŸ‘πŸ‘

    • πŸ§ͺ It is now possible to wrap delegates as publishers using a new DelegateProxy (#21). Huge kudos to @jdisho for the massive work he's done on this!
      • UITableView gets willDisplayCellPublisher, willDisplayHeaderViewPublisher, willDisplayFooterViewPublisher, didEndDisplayingCellPublisher, didEndDisplayingHeaderViewPublisher, didEndDisplayingFooterView, itemAccessoryButtonTappedPublisher, didHighlightRowPublisher, didUnhighlightRowPublisher, didSelectRowPublisher, didDeselectRowPublisher, willBeginEditingRowPublisher, didEndEditingRowPublisher.
      • UICollectionView gets didSelectItemPublisher, didDeselectItemPublisher, didHighlightItemPublisher, didUnhighlightRowPublisher, willDisplayCellPublisher, willDisplaySupplementaryViewPublisher, didEndDisplayingCellPublisher, didEndDisplaySupplementaryViewPublisher.
      • UITextView gets textPublisher and valuePublisher (alias).
      • Now that the mechanism exists we'll be adding more delegate-based publishers in following versions.
    • πŸ‘¨β€πŸŽ€ Added a new assign(to:on:animation:) animated subscriber (#17). Thanks @icanzilb!
    • πŸ‘‡ The deployment target of the project has been dropped to iOS 10 with conditional compilation to allow older apps that leverage Combine to use CombineCocoa (#18). Thanks @RonKliffer!
    • πŸ“¦ Fix Carthage build from source, instead of only providing a prebuilt binary, as well as some minor issues in SPM.
    • πŸ“ New helper method on UIControl - controlEventPublisher(for:), as a shorthand to init'ing Publishers.ControlEvent (#27). Thanks @wickwirew !
    • πŸ› Various bug fixes and performance improvements.
    Source code(tar.gz)
    Source code(zip)
    CombineCocoa.framework.zip(1.24 MB)
  • 0.1.0(Aug 14, 2019)

    A new release is upon us ! πŸŽ‰

    • CombineCocoa can now provides publishers for ControlTarget-based controls using the new ControlTarget publisher.

    • UIBarButtonItem.tapPublisher added

    • All UIGestureRecognizers added:

      • UITapGestureRecognizer.tapPublisher
      • UIPinchGestureRecognizer.pinchPublisher
      • UIRotationGestureRecognizer.rotationPublisher
      • UISwipeGestureRecognizer.swipePublisher
      • UIPanGestureRecognizer.panPublisher
      • UIScreenEdgePanGestureRecognizer.screenEdgePanPublisher
      • UILongPressGestureRecognizer.longPressPublisher
    • UIScrollView.contentOffsetPublisher and UIScrollView.reachedBottomPublisher() added (thanks @jdisho !)

    Source code(tar.gz)
    Source code(zip)
    CombineCocoa.framework.zip(1.12 MB)
Owner
Combine Community
Community projects and experimentations around Apple's Combine framework
Combine Community
A set of UIKit helpers that simplify the usage of UIKit view's and controller's in SwiftUI.

A set of UIKit helpers that simplify the usage of UIKit view's and controller's in SwiftUI. Many of these helpers are useful even in a pure UIKit project.

SwiftUI+ 6 Oct 28, 2022
Fetch the star wars api from all the planets and list and show details using Swift UI and Combine

Star Wars Planets Fetch the star wars planet data by using stat war api, list and show details using SwiftUI and Combine frameworks ?? Swift UI Framew

null 1 Aug 10, 2022
SwiftUIBootStrap contains Swift UI along with MVVM and Combine

SwiftUIBootstrap Project This project provides an insight on how to write start a project with SwiftUI Below are the items that are covered in this pr

Masroor Elahi 11 Jun 3, 2022
Neumorphism framework for UIKit.

NeumorphismKit is neumorphism framework for UIKit. Requirements iOS 12.0+ Swift 5.1+ Versions NeumorphismKit version Xcode version 1.0.0 Xcode 11+ 1.1

y-okudera 42 Dec 13, 2022
Easily use UIKit views in your SwiftUI applications. Create Xcode Previews for UIView elements

SwiftUIKitView Easily use UIKit views in SwiftUI. Convert UIView to SwiftUI View Create Xcode Previews from UIView elements SwiftUI functional updatin

Antoine van der Lee 682 Dec 29, 2022
Make ComposableArchitecture work with UIKit

ComposableUIKit The ComposableArchitecture (TCA) library provides a way of structuring Swift code with the Redux-pattern. It is highly optimized for S

Manuel Maly 11 Nov 5, 2022
Swift extensions for UIKit.framework.

XUIKit Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements Installation XUIKit is a

FITZ 0 Oct 22, 2021
Convenient domain specific language for writing programmatic UI built over UIKit and more.

XYKit Swifty and convenient domain specific language for creating programmatic UI in a more declarative way and more than that. Built on top of UIKit

Denis Goloborodko 1 Nov 5, 2021
🎸🎸🎸 Common categories for daily development. Such as UIKit, Foundation, QuartzCore, Accelerate, OpenCV and more.

?????? Common categories for daily development. Such as UIKit, Foundation, QuartzCore, Accelerate, OpenCV and more.

77。 423 Jan 4, 2023
Example Catalyst app that is shown in a UIKit popover underneath an NSStatusItem

CatalystStatusItemPopoverExample Example Catalyst app that is shown in a UIKit popover underneath an NSStatusItem. References How to use macOS Specifi

Tom Irving 9 Sep 8, 2022
Create descriptive UIKit screens, faster!

Columbina's DeclarativeUIKit Create descriptive UIKit screens, faster! Get rid of constraints manipulation and use declarative language to create your

Columbina 2 Dec 12, 2021
🎨 View instance initializing sugar for Swift & UIKit

?? View instance initializing sugar for Swift & UIKit

Yongjun Lee 11 Dec 1, 2022
xTensions is a collection of useful class extensions for UIKit.

xTensions Intro xTensions is a collection of useful class extensions for UIKit. Swift Package Manager Note: Instructions below are for using SwiftPM w

Alexandre Garrefa 0 Nov 28, 2021
A simple and elegant UIKit for iOS.

HamsterUIKit A simple and elegant UIKit(Chart) for iOS, written in Swift. ?? Curve and bar Charts. ?? Protocols are designed based on UIKit(UITableVie

Howard Wang 30 Oct 2, 2022
πŸ“ Declarative UIKit in 10 lines of code.

Withable ?? Declarative UIKit in 10 lines of code. See corresponding article at Declarative UIKit with 10 lines of code A simple extension instead of

Geri BorbΓ‘s 14 Dec 20, 2022
🧩 Easy scrollable layouts in UIKit

Easy scrollable layouts in UIKit Create complex scrollable layout using UIViewControllers or plain UIViews and simplify your code! ScrollStackControll

Daniele Margutti 402 Oct 3, 2022
SampledPublisher - The SampledPublisher samples the output of a publisher based on events from another publisher

SampledPublisher The SampledPublisher samples the output of a publisher based on

Berik Visschers 1 Jan 25, 2022
CombineCoreBluetooth is a library that bridges Apple's CoreBluetooth framework and Apple's Combine framework

CombineCoreBluetooth is a library that bridges Apple's CoreBluetooth framework and Apple's Combine framework, making it possible to subscribe to perform bluetooth operations while subscribing to a publisher of the results of those operations, instead of relying on implementing delegates and manually filtering for the results you need.

Starry 74 Dec 29, 2022
Tech blog about Put Generic Protocol as Variable Type. How Combine Publisher put into AnyPublisher

How to Put Generic Protocol as Variable Type Have you ever put a Protocol on a variable? I believe you do. The Delegate pattern is using a lot in UIKi

Tsungyu Yu 8 Aug 17, 2021
content for Using Combine - notes on learning Combine with UIKit and SwiftUI

SwiftUI-Notes A collection of notes, project pieces, playgrounds and ideas on learning and using SwiftUI and Combine. Changes, corrections, and feedba

Joseph Heck 1.7k Dec 27, 2022