Giter Site home page Giter Site logo

vhesener / closures Goto Github PK

View Code? Open in Web Editor NEW
1.7K 27.0 147.0 3.99 MB

Swifty closures for UIKit and Foundation

License: MIT License

Objective-C 0.07% Swift 99.84% Shell 0.08%
swift closures convenience-methods uicontrol cocoapods carthage delegation datasource uigesturerecognizer uiimagepickercontroller

closures's Introduction

Closures logo

Language License Release

Closures is an iOS Framework that adds closure handlers to many of the popular UIKit and Foundation classes. Although this framework is a substitute for some Cocoa Touch design patterns, such as Delegation & Data Sources and Target-Action, the authors make no claim regarding which is a better way to accomplish the same type of task. Most of the time it is a matter of style, preference, or convenience that will determine if any of these closure extensions are beneficial.

Whether you're a functional purist, dislike a particular API, or simply just want to organize your code a little bit, you might enjoy using this library.


Convenient Closures

Some days, you just feel like dealing with UIControl's target-action using a closure instead.

button.onTap {
    // UIButton tapped code
}
mySwitch.onChange { isOn in
    // UISwitch value changed code
}

Adding a gesture recognizer can be compacted into one method.

view.addPanGesture() { pan in
    // UIPanGesutreRecognizer recognized code
}

Populating views with an array? I gotchu.

tableView.addElements(myArray, cell: MyTableViewCell.self) { element, cell, index in
    cell.textLabel!.text = "\(element)"
}
collectionView.addFlowElements(myArray, cell: MyCustomCollectionViewCell.self) { element, cell, index in
    cell.myImageViewProperty.image = element.thumbImage
}
pickerView.addStrings(myStrings) { title, component, row in
    // UIPickerView item selected code
}

Daisy Chaining

Almost all convenience methods allow for the use of daisy chaining. This allows us to have some nice syntax sugar while implementing optional delegate methods in a concise way. Using UITextField as an example, we can organize and visualize all of the UITextFieldDelegate behavior.

textField
    .didBeginEditing {
        // UITextField did begin editing code
    }.shouldClear {
        true
    }.shouldChangeCharacters { range, string in
        // some custom character change code
        return false
}

Retain Control

At no time are you locked into using these convenience methods. For instance, UITableView does not need to be populated with an array. You can just as easily provide your own UITableViewDelegate and UITableViewDataSource handlers.

tableView.register(MyTableViewCell.self, forCellReuseIdentifier: "Cell")
tableView
    .numberOfRows { _ in
        myArray.count
    }.cellForRow { indexPath in
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        cell.textLabel!.text = myArray[indexPath.row]
        return cell
    }.didSelectRowAt { indexPath in
        // IndexPath selected code
}

You aren't limited to which delegate/dataSource methods you wish to implement. Similarly, you can act on any UIControl events.

anyControl.on(.touchDown) { control, event in
    // UIControlEvents.touchDown event code
}

These two UIImagePickerController snippets are equivalent. As you can see, there are lots of ways to provide more granular control by mixing and match various convenience methods and closure handlers.

UIImagePickerController(source: .camera, allow: .image) { result, picker in
    myImageView.image = result.editedImage
}.present(from: self)
let pickerController = UIImagePickerController()
pickerController.sourceType = .camera
pickerController.mediaTypes = [kUTTypeImage]
pickerController.didFinishPickingMedia { [weak self] info in
    myImageView.image = info[UIImagePickerControllerEditedImage] as? UIImage
    self?.dismiss(animated: true)
}.didCancel { [weak self] in
    self?.dismiss(animated: true)
}
self.present(pickerController, animated: true)

There are several ways to learn more about the Closures API, depending on your learning style. Some just like to open up Xcode and use autocomplete to view the various properties/functions. Others prefer a more documented approach. Below are some documentation options.


   Playground

To play with the Playground demo, open the Closures workspace (Closures.xcworkspace file), build the Closures framework target, then click on the ClosuresDemo playground, and click on the play button:

Playgrounds


   Class Reference Documentation

The Reference Documentation has all of the detailed usage information including all the public methods, parameters, and convenience initializers.

Class Reference Documentation


Swift Package Manager

If using Swift Package Manager, in Xcode, go to File > Swift Packages > Add Package Dependency... and enter the following URL:

https://github.com/vhesener/Closures

CocoaPods

If using CocoaPods, add the following to your Podfile:

pod 'Closures'

Carthage

If using Carthage, add the following to your Cartfile:

github "vhesener/Closures"

Manual

Download or clone the project files found in the master branch. Drag and drop all .swift files located in the 'Closures/Source' subdirectory into your Xcode project. Check the option Copy items if needed.


Inspired by BlocksKit, there was a need for a more Swifty version of the same library. The goal of this library was to provide similar usefulness, but with the following constraints:

  • Use Swift's strong-typed system as much as possible in the API.
  • Not use the Objective-C runtime. There are many reasons for this, but mostly because
    • It was arbitrarily challenging.
    • It was in the spirit of Swift.
  • Create a scalable mechanism to easily add additional closure wrappers in the future.

It is our goal to become irrelevant via sherlock. In addition to not having to support this library anymore, it would actually be flattering to have been validated by the API folks at Apple.


If you were hoping to see an API converted using closures and came up empty handed, there's a chance all can be right. Simply vote on a feature by adding a 👍 reaction.


Closures is provided under the MIT License.

The MIT License (MIT)
Copyright (c) 2017 Vincent Hesener
 
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

closures's People

Contributors

alexamin avatar bartleby avatar eseay avatar vhesener avatar yoiang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

closures's Issues

i have a question ask you ,about xcode source extension

hi cat
Recently, I was developing an xcode extension, but during the development process, I found that I could not make a network request in the development. He would not identify the host name, and I would like to know if you have had this kind of problem. Or are there any good solutions? Looking forward to your reply

is Closures doesn't support custom-observed property in swift ?

i define an observed property, and use observe(_, until: _, changeHandler: _) to get value changed callback,
most of time it works fine, but in iOS 10.3.3, i receive a crash log!
crash description: " *** was deallocated while key value observers were still registered with it";

i declare property like this
class Person {
@objc dynamic var age: Int = 18
}

Dependency "Closures" has no shared framework schemes

When attempting to build Closures using Carthage I receive the error

Dependency "Closures" has no shared framework schemes

I haven't developed a framework before but it seems that that would also preclude Closures from supporting building for specific platforms (e.g., carthage update --platform iOS)

UITextView

Looks like you're tracking requests here - have you considered adding for UITextView?

Memory leak

In Core.swift on line 130 there is self?.removeObserver(observer!) but I believe directly after this you should have:
observer = nil

You do this currently:

self?.removeObserver(observer!)
observer = nil

for lines 136-137 and 172-173 but I think its missing in the above scenario. I notice when I use Xcode Instruments > Leaks that I see memory leaks. Adding the above removes the leaks for me.

UIViewController

It would be reaaaaally nice to have life cycle methods:
viewDidLoad
will/did appear/disappear
etc.

Thanks for this nice kit!

UIView not release

addTapGesture or longGesture for UIView instance cause UIViewController not release when pop or dismiss

cocoapod 找不到 Closures 这个库

[!] CocoaPods could not find compatible versions for pod "Closures":
In Podfile:
Closures

Specs satisfying the Closures dependency were found, but they required a higher minimum deployment target.
chenshuodeMac-mini:SSJCMall chenshuo$ pod install
Analyzing dependencies
[!] CocoaPods could not find compatible versions for pod "Closures":
In Podfile:
Closures

Specs satisfying the Closures dependency were found, but they required a higher minimum deployment target.

App Store rejection for not including NSPhotoLibraryUsageDescription

I have no use of user's photo library into my app yet my app got rejected.
I created a build of my app and submitted it to iTunes Connect and got the following rejection a few minutes later in an automated email:
This app attempts to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSPhotoLibraryUsageDescription key with a string value explaining to the user how the app uses this data.
I was able to track down the cause of the rejection to this method into UIImagePickerController.swift file:
public convenience init(source: UIImagePickerControllerSourceType = .photoLibrary, allow: UIImagePickerController.MediaFilter = .image, cameraOverlay: UIView? = nil, showsCameraControls: Bool = true, didCancel: @escaping ( _ picker: UIImagePickerController) -> Void = dismissFromPresenting, didPick: @escaping (_ result: UIImagePickerController.Result, _ picker: UIImagePickerController) -> Void) {...
I take it that an app that makes any UIImagePickerController call (even if it’s not actually requesting access to the user’s photo library) must include an entry for NSPhotoLibraryUsageDescription in its Info.plist.

Unit testing code coverage inside the closure

Is there any way to write Unit Test that can cover the code inside the closure block?

For example, here's a block of code I'd like to cover. How can I trigger the textField closure?

Screen Shot 2022-12-09 at 15 21 37

Clear handler?

Example

button.onTap(handler:{
    // do stuff
})

How do I clear this handler to avoid a leak when my VC is deallocated?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.