Git Product home page Git Product logo

hydra's Introduction

Hello 👋 I'm Daniele and I work as Mobile Tech Lead Manager at ImmobiliareLabs, the IT dept of Immobiliare.it.
I'm a passionate software engineer with a love for minimalism, product design and sushi.
I started programming on macOS in 2000 and iOS on 2007.

malcommac

OpenSource Projects

Maintaing and developing tools consumes resources and time.
While I enjoy making them your support is foundamental to allow me continue its development.
Consider becoming a Sponsor](https://github.com/sponsors/malcommac) of my works.

RealHTTP is lightweight await/async http client made for Swift.

RealFlags makes it easy to configure feature flags in your codebase.

Before async await there was promises. Hydra is a fast full-featured promise library for Swift.

Async/await client to interact with GitLab API v4 with Swift

With over 3 milion of downloads on CocoaPods, since 2015 SwiftDate is the #1 toolkit to parse, validate, manipulate, compare and display dates.

It allows you to use all system's location based services (plus external services like Google Maps, MapBox, OpenStreet and Nokia Here) directly from an easy to use and elegant APIs set.

SwiftRichString is a library which allows to create and manipulate attributed strings easily on all Apple Platforms.

Create complex scrollable layout using UIViewControllers or plain UIViews and simplify your code.

hydra's People

Contributors

akostylev0 avatar anykao avatar bryanoltman avatar chrispix avatar daaavid avatar hachinobu avatar heckj avatar hy9be avatar malcommac avatar mcastagnolo avatar moaible avatar nhnam avatar numen31337 avatar pedrovereza avatar r-plus avatar revolter avatar tasanobu avatar terhechte avatar yaslab 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hydra's Issues

Is the minimum requirement still iOS 9?

I'm using Hydra 2.0.6 with Xcode 13, but at compile time I get a message that Hydra requires iOS 12 or higher.
But I didn't have any problems when using Xcode 12 and Hydra 2.0.5.
Did the minimum requirements change? Thank you.

Showing Recent Messages
/Users/hoge/Test/ViewController.swift:11:8: Compiling for iOS 10.0, but module 'Hydra' has a minimum deployment target of iOS 12.0: /Users/hoge/Library/Developer/Xcode/DerivedData/Test-akvdfnkqlvyyxafhnfgahlouszoz/Build/Products/Debug-iphonesimulator/Hydra.framework/Modules/Hydra.swiftmodule/x86_64-apple-ios-simulator.swiftmodule

Leaks?

Played around with this library a bit and noticed Xcode is reporting quite a few memory leaks using the latest version and with a simple function:

func testPromise() -> Promise<Int> {
        return Promise<Int>(in: .utility, { (resolve, reject, _) in
            resolve(5)
        })
}

testPromise().then { result in
        print(result)
}

screen shot 2017-07-30 at 17 03 32

Ubuntu compilation error

/home/user/Project/.build/checkouts/Hydra.git-8391472609009747209/Sources/Hydra/Promise+Await.swift:99:20: error: binary operator '!=' cannot be applied to two 'DispatchQueue' operands
                guard self.queue != DispatchQueue.main else {
                      ~~~~~~~~~~ ^  ~~~~~~~~~~~~~~~~~~

Swift version 5.0.1 (swift-5.0.1-RELEASE)
Target: x86_64-unknown-linux-gnu

Ubuntu 16.04.6 LTS

Feature request: zip analog with failed promises

I think this will be helpful to have some function analog to the 'zip' function which will accept the list of promises, wait until all of them is finished and returns both failed and resolved in the result.

Can't get notified in Promise

return Promise( { [unowned self] (resolve, reject) in

        NotificationCenter.default.addObserver(
            forName: SOME_NOTIFICATION,
            object: nil,
            queue: nil,
            using: { (notification:Notification) -> Void in
                resolve() // never called
        })
        SOME_ACTION_TRIGGER_NOTIFICATION()
    
    })

How to use Promise<Void> in Swift 5.2

Hi, I want to use Promise<Void> in Hydra 2.0.2 and Swift 5.2 (Xcode 11.4).

I tried to use it as following code.

Promise<Void>(in: .main, token: token) { resolve, reject, _ in
     resolve()
}

However compiler reports an error Missing argument for parameter #1 in call.

How do I change the code to use Promise<Void>?

Zip with promises array

Hey, great library! I have been looking for something like this for a while.

I'd like to suggest that zip should receive an array of promises (if all of them shares the same return type) and a return a promise that combines all the inputs. It could also receive a reduce function as argument. What do you think?

I mean something like this:

var promises = [Promise<User>]()

// Some code here. 

Promise.zip(promises)
      .then { (users: [User]) in 

      }

Thanks!

Deprecation of `await` keyword in Swift 5.4+. Using new Hydra.await()

Ciao 👋

As reported in the release notes, the await keyword will start to emit warnings in Xcode 12.5:

Deprecations
The Swift compiler emits a warning for the use of the await keyword as an unqualified identifier. Wrap await with back-ticks so Swift always treats it as an identifier, or fully qualify declarations named await (for example, by adding self if it is a reference to an instance member named await from within the instance). (SE-0296, 67000350)

Is there any plan to address this in Hydra?

Thanks 🙌

Can't install using Carthage

I am getting next errors

*** Building scheme "Hydra-macOS" in Hydra.xcodeproj
** CLEAN FAILED **

The following build commands failed:
Check dependencies
(1 failure)
** BUILD FAILED **

The following build commands failed:
Check dependencies
(1 failure)
warning: no umbrella header found for target 'Hydra-macOS', module map will not be generated
warning: no umbrella header found for target 'Hydra-macOS', module map will not be generated
A shell task failed with exit code 65:
** CLEAN FAILED **

The following build commands failed:
Check dependencies
(1 failure)
** BUILD FAILED **

The following build commands failed:
Check dependencies
(1 failure)

Make .voidPromise() public

.voidPromise() should be public in order to be used to chain multiple Promises which return different results.

Example:

let op_1: Promise<User> = asyncGetCurrentUserProfile()
let op_2: Promise<UIImage> = asyncGetCurrentUserAvatar()
let op_3: Promise<[User]> = asyncGetCUrrentUserFriends()
all(op_1.void,op_2.void,op_3.void).then { _ in
  let userProfile = op_1.result
  let avatar = op_2.result
  let friends = op_3.result
}.catch { err in
  // do something
}

We will also rename voidPromise() func to void variable.

Version 1.0.0 does not compile in Swift 3

I am currently unable to build Hydra 1.0.0 in Swift 3 for the MacOS target.

In Promise+Recover.swift, the recover method does not compile correctly because it is unable to resolve which then method to invoke. The build error is: /Hydra/Promise+Recover.swift:47:11: Ambiguous reference to member 'then(in:_:)'

If you remove the lines:
.cancelled(in: ctx, { _ -> Void in operation.cancel() })

then the swift compiler is able to resolve the appropriate then helper and the framework compiles.

await does not work on ios11

Hey I used to use await to queue up my task executions

for a in self.aaa {
    try await(self.do[a].execute())
}

But I upgraded to ios 11 today and run into a EXC_BREAKPOINT here. The call stack is
image

And the error is
image

Promise object will not dispose.

I add this line to DemoApp's viewDidLoad method.
Promise<Int>(resolved: 3).catch { _ in }

After launch the DemoApp, invoke memory visualizer in Xcode 8(below screenshot is it) that indicate two Promise object is still exist and memory leak(Strong reference cycle).

I confirmed this issue on 5692f3e.

2017-03-18 23 53 26

v0.9.9 doesn't compile on Swift 4

I get 3 warnings and 4 errors when compiling on Swift 4 (even though the readme says v0.9.6 and above is swift 4 compatible). The readme also references a swift-4 branch, which doesn't seem to exist.

Add support for cancellable Promise in await operator

Let's say I use the example:

let asyncFunc = async({ _ -> Int in
  let loggedUser = try await(loginUser(username,pass))
  let followersList = try await(getFollowers(loggedUser))
  let countUnfollowed = try await(unfollow(followersList))
  return countUnfollowed
}).then({ value in
  print("Unfollowed \(value) users")
})

How would I make that cancelable?

zip() function as global function (outside Promise class)

What I was wishing for:

all(promiseA,promiseB).then { resultA, resultB in
}

Based on the docs it would have to be

all(promiseA,promiseB).then { result in
  let resultA = result[0]
  let resultB = result[1]
}

or

Promise<Void>.zip(promiseA, promiseB).then { resultA, resultB in
}

Any thoughts?

Hydra compile issues in Xcode 13

It seems because of the use of await function in Hydra source code, any code referencing Hydra would fail to compile in Xcode 13.
截圖 2021-06-10 下午9 53 38

Importing Hydra in a file where there is a UIViewControllerRepresentable gives compilation errors

Hi everyone!
I'm using Hydra 2.0.6 on iOS on Xcode 13.2.1.

I would like to import Hydra on this file

import SwiftUI

struct VideocallViewControllerWrapper: UIViewControllerRepresentable {
    ...
}

but as soon as I import it, Xcode tells me that Type 'VideocallViewControllerWrapper' does not conform to protocol 'UIViewControllerRepresentable'. I have other files where I have successfully imported both SwiftUI and Hydra. I think the problem is the presence of UIViewControllerRepresentable.

Thank you

Progress block

Hi Malcom! Is there any kind of progress block for things like uploading an avatar for example.

uploadAvatar()
.progress { p in
  // Here update progressView for example
}
.then(doSomething)
.onError(showErrorPopup)
.finally(doSomething)

Hydra and iOS 9 compatibility

Nice library! This is exactly what I'm looking for. But I got this error message when I tried to integrate it with my project (by Carthage).

Module file's minimum deployment target is ios10.2 v10.2: ./Carthage/Build/iOS/Hydra.framework/Modules/Hydra.swiftmodule/arm64.swiftmodule

How to put a Promise into always?

Hey guys, first of all thank you very much for this great library!

I have dismissActivityIndicator method, which returns a promise:

func dismissActivityIndicator<T>(any: T) -> Promise<T> {
    return Promise<T> { resolve, _, _ in
        KVNProgress.dismissAnyway {
            resolve(any)
        }
    }
}

My question is how can I inject it into the promise chain, so it is always executed at end? It's fairy simple with always and a plain non-async method, but how to achieve the same result with the method returning a Promise?

help wanted would be an appropiate tag for this question, as this is not an issue :)

A second resolve in the Promise

Hi Daniele and contributors,

I was wondering if you had thoughts on this situation. I'm wrapping an Alamofire download, which would resolve a temporary url, and then the final destination url. It would be nice to have a couple of Promises. Any perspective would be greatly appreciated.

func streamFile(key: String = "default") -> Promise<URL> {
        let source = self.serverURL(forKey: key)
        let (localURL, exists) = self.fileURL()
        return Promise<URL>({ resolve, reject in
            if !exists {
                Alamofire.download(source, to: { temp, response in
                    // Temporary URL
                    resolve(temp)
                    return (localURL, [.removePreviousFile, .createIntermediateDirectories])
                }).response { response in
                    if response.error == nil {
                        // Final URL
                        resolve(response.destinationURL!)
                    }
                    else {
                        log(error: response.error.debugDescription)
                        reject(CommonError.networkConnectionError)
                    }
                }
            }
            else {
                resolve(localURL)
            }
        })
    }

Retry vs Delay

Hi! First of all, I have to say that I really love this library 🙏
The reason for this issue is cause I'm not sure if I found a bug or if I misunderstood the semantics of retry with delay.

Context

I was trying to implement polling to a web server leveraging Promises.
Say we have promise: Promise<Value> which encapsulate the async call to our backend. Then I expressed polling with something like:

promise
  .validate { value in /* predicate to decide if continue polling */ }
  .retry(10, delay: pollingTime)

Expectation

Since:

  • validate rejects the promise if the predicate is not met
  • retry allow to execute source chained promise if it ends with a rejection (exactly what I need, to re-issue the web call)
  • delay is the delay between each attempt (starting when failed the first time)

My expectation was to retry the promise at most 10 times, each with a delay of pollingTime.

Result

AFAIU, the delay is implemented with the defer which in turn defers only the happy path (then) but the retryWhen is actually targeting a rejected promise. This results in the delay being applied in the only attempt that succeeds (if any).

I've also tried to encapsulate the validate inside the promise (rejecting it if the predicate is not met) but it didn't move the problem.
I could achieve what I expected only pushing the validation inside the promise and implementing a deferAll:

  func `deferAll`(in context: Context = .background, _ seconds: TimeInterval) -> Promise<Value> {
    guard seconds > 0 else { return self }

    let fireTime: DispatchTime = .now() + seconds
    return self
      .then(in: context) { value in return Promise<Value> { resolve, _, _ in
        context.queue.asyncAfter(deadline: fireTime) { resolve(value) }
      }}
      .recover { error in return Promise<Value> { _, reject, _ in
        context.queue.asyncAfter(deadline: fireTime) { reject(error) }
      }}
  }
}

and leveraging it inside the retryWhen in place of the defer.

Am I misunderstanding the semantic of retry with delay?

Thank you 😄

How to use async function (example)

This will not run:

image

not even the print statement runs.

This however runs:

image

Does the async func always need to be used in a chain using methods like .always? The README examples seem to show this is not needed, but I am confused about its actual usage.

NOTE: the waitUntil func is from Nimble

Even if there was some sort of problem w/ the waitUntil func, shouldnt the 1st print statement at least execute before it timesout?

Cancellable Promise in a Chain

Hi guys, I have been using this library for a while and I have to say it's very easy to work with it.

I have a concern about cancellable promises, specifically the behaviour of a chain of promises when a promise in the middle has been cancelled.
Let's say we have:

A.then(B).then(C).then(D).then(E)
    .then { _ in
        print("success")
    }.catch { _ in
        print("failed")
    }.cancelled { in
        print("cancelled")
    }

If, for example, C gets cancelled while A and B resolve correctly, I'm expecting that cancelled is printed out, but what I observe is that the sequence gets stuck in pending state.
This behaviour can be checked with the following test that recalls the ones provided with the library, which fails for timeout:

  func test_cancelledPromiseChainable2() {
    let exp = expectation(description: "test_cancelledPromiseChainable2")
    
    let invalidator: InvalidationToken = InvalidationToken()
    invalidator.isCancelled = true
    
    intPromise().then { _ in
        self.test_invalidationToken(token: invalidator)
      }.then { total in
        print("Operation finished with: \(total)")
        XCTFail()
      }.catch { _ in
        print("Operation failed")
      }.cancelled {
        print("Operation cancelled")
        exp.fulfill()
    }
    
    waitForExpectations(timeout: expTimeout, handler: nil)
  }

If I'm not misinterpreting the situation, I will open a PR with a suggested fix, otherwise please let me know the reasoning behind this behaviour.

Thanks,
AT

Promise.all()

Promise.all is throwing a no member all error.

import Hydra 

Promise.all(promises).then({
})

Cancellable Promise

I would to implement cancel() func in Hydra.
These days I'll investigate by looking at other libs implementations.
(@r-plus have you some advices?)

Build fail on Xcode 12 beta 2

When trying to build I get the following error in Promise+Recover.swift:

Cannot convert value of type 'Promise<Void>' to closure result type()'

It works fine on Xcode 11.5.

Version 1.2.1

Crash on operation: PromiseStatus on iOS but not on macOS

We are using Hydra as part of a client API framework. There is a version without Promise that uses Alamofire for networking. We then add a Promise based wrapper for each API call.
The framework exists for both iOS and macOS.
Recently we upgraded to Xcode 11.2, swift 5.1 and Hydra 2.0.2 (from 1.2.1, using SPM).

Now our tests for macOS pass, but the iOS tests crash in Promise.swift, line 71:

	 public lazy var operation: PromiseStatus = {
		return PromiseStatus(token: self.invalidationToken, { [weak self] () -> () in
			self?.set(state: .cancelled)
		})
	}()

I tried to debug but could not figure out what is going on.

Here is a sample project that reproduces the bug.

The project has two targets, one for iOS and one for macOS. Both use the same source and test swift files.
The macOS tests pass but the iOS promise test fails (the standard api test passes, so the api part is ok).

Method is ambiguous for type lookup in this context

Need to rename the Hydra enum to something else because it causing the ambiguity error in those projects in which similar namination is used. For eg. In my project I used a class with name Promise and when I try to tell compiler that use the Promise of Hydra by Hydra.Promise<Int> then it start complaing that Hydra Enum doesn't contain a case promise. For more Information check issue

Relevant Issue

Fix for await function

I'm trying to use await using the syntax from the readme.

let city = try await(getCityPromise())

The getCityPromise function is declared like this:

func getCityPromise() -> Promise<String> { ... } 

But the compiler raises an error

cannot invoke 'await' with an argument list of type '(Promise<String>)'

Then I looked at the unit tests, and I saw that a special operator .. is used instead of calling the await function.

Using that operator my code doesn't raise any error anymore. Should the documentation be fixed or I'm missing something?

Nested generics

Hi!

How about using Nested generics released in Swift 3.1?

I want to make State and Observer nested generics.

For example as below.

extension Promise {
	
	/// ....
	internal indirect enum State {
		case pending
		case resolved(_: Value)
		case rejected(_: Error)
		
		/// It continues below....
		
	}
		
	/// ....
	internal indirect enum Observer {
		typealias ResolveObserver = ((Value) -> (Void))
		typealias RejectObserver = ((Error) -> (Void))
		
		case onResolve(_: Context, _: ResolveObserver)
		case onReject(_: Context, _: RejectObserver)
		
		/// It continues below...		
	}
	
}

If there is no problem I think I will give out PR.

Promise+Recover.swift does not compile for macOS / Swift 4

I get the following compile error:

/Users/stefan/Documents/Git-Workspace/Modules/Hydra/Sources/Hydra/Promise+Recover.swift:47:11: error: ambiguous reference to member 'then(in:_:)'
                        return self.then(in: ctx, {
                               ^~~~
/Users/stefan/Documents/Git-Workspace/Modules/Hydra/Sources/Hydra/Promise+Then.swift:48:14: note: found this candidate
        public func then<N>(in context: Context? = nil, _ body: @escaping ( (Value) throws -> N) ) -> Promise<N> {
                    ^
/Users/stefan/Documents/Git-Workspace/Modules/Hydra/Sources/Hydra/Promise+Then.swift:76:14: note: found this candidate
        public func then<N>(in context: Context? = nil, _ body: @escaping ( (Value) throws -> (Promise<N>) )) -> Promise<N> {
                    ^
/Users/stefan/Documents/Git-Workspace/Modules/Hydra/Sources/Hydra/Promise+Then.swift:118:14: note: found this candidate
        public func then(in context: Context? = nil, _ body: @escaping ( (Value) throws -> () ) ) -> Promise<Value> {
                    ^

I'm using Xcode 9.0 (9A235), swift 4 and a deployment target of 10.12.

Promise.zip fails to compile with "cannot invoke 'zip' with an argument list of type", Xcode 8.3

Xcode 8.3 (8E162)

I'm in the process of evaluating Hydra over PromiseKit, the overall process of converting from one to the other hasn't been too hard, actually cleaned up the code a bit, but I've hit a snag

When trying to work with zip I keep getting

Error:(695, 24) cannot invoke 'zip' with an argument list of type '(a: Promise<APIAccessRestrictionState>, b: Promise<APIServiceAccessState>)'

I've expanded the code a little in an effort to try and solve the issue (and make it easier to read)

let restrictionStatePromise: Promise<APIAccessRestrictionState> = CioffiAPIManager.shared.getServicesAuthenticatedState()
let accessStatePromise: Promise<APIServiceAccessState> = CioffiAPIManager.shared.getServiceAccessState()

return Promise<Void>.zip(
			a: restrictionStatePromise,
			b: accessStatePromise)
		.then { (restrictionState: APIAccessRestrictionState,
		         accessState: APIServiceAccessState) -> Promise<Bool> in
			self.authorisedState = DefaultAPIAccessRestrictionState(from: state)
			self.serviceAccessState = state
			self.authenticationChanged()
			return Promise<Bool>(resolved: true)
		}

I've also tried using...

return Promise.zip(
		a: restrictionStatePromise,
		b: accessStatePromise)

But neither work.

APIServiceAccessState is a typealias of APIAccessRestrictionState...

public typealias APIServiceAccessState = APIAccessRestrictionState

so I'm wondering if that's the issue and if something like all might be better

failed build on swift 3.1 spm version

using swift 3.1 version of spm and its having trouble installing though server side project is in 4.0 (using Perfect Server Side) . too many errors to copy and paste here but It tried different major and minor versions and no success.

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.