Swift Package Manager compatible Platform X

Acheron

Acheron 是一组用于开发 iOS 应用程序的实用工具集合。

Swift Package Manager (Swift 包管理器)

您可以使用 SPM 将 Acheron 集成到您的项目中。您可以将以下内容添加到您的依赖项中:

.package(url: "https://github.com/aepryus/Acheron.git", from: "1.1.0"),

或者从 Xcode 中转到File/Add Packages并输入 URL:https://github.com/aepryus/Acheron.git

Loom ORM

一个轻量级的线程安全无 SQL ORM。

AepLayout

一组轻量级的扩展和便捷方法,用于以编程方式布局 iOS 屏幕。它在使多个屏幕尺寸看起来相同方面特别有用。

Pen

Pen 是一组工具,可以简化 UIKit 中字体的使用。主要地,它是一个不可变对象 'Pen',它封装了所有的字体“属性”;使其易于定义和访问。可以通过 clone() 方法创建略微调整过的新 Pen。它还包括许多 Apple 类的扩展,允许直接与它们一起使用 Pen。

用法

let greenPen: Pen = Pen(font: UIFont(name: "ChicagoFLF", size: 19)!, color: UIColor.green.tint(0.7), alignment: .right)
let whitePen: Pen = greenPen.clone(color: .white)

let attString = NSMutableAttributedString()
attString.append("This is GREEN", pen: greenPen)
attString.append("This is WHITE", pen: whitePen)

let label = UILabel()
label.pen = greenPen

NSString("Hello, White Pen").draw(at: .zero, pen: whitePen)
NSString("Hello, Green Pen").draw(at: .zero, withAttributes: greenPen.attributes)

RGB

RGB 是一组工具,可以轻松获取颜色的色调、阴影和明暗度,或混合两种完全不同的颜色。它包括 RGB 类,该类将颜色转换为可以进行数学操作的向量。它还包括 UIColor 的扩展,使这些操作可以直接对 UIColor 本身进行。

用法

let lightBlue = UIColor.blue.tint(0.5)
let greyGreen = UIColor.green.tone(0.5)
let transparentPink = UIColor.red.tint(0.5).alpha(0.5)

let blueRGB = RGB(uiColor: .blue)
let redRGB = RGB(uiColor: .red)
let purpleRGB = (blueRGB + redRGB) * 0.5
let purpleRGB2 = blueRGB.blend(rgb: redRGB, percent: 0.5)

可展开的表格视图

用于创建可展开表格视图的类和委托。

Node View (节点视图)

一个使表格数据易于显示的视图。

AepImage

AepImage 是一种非常轻量级的异步图像加载和缓存工具,它嵌入到 UIImageView 中,但也可以直接从 UIImage 上的静态方法中使用。该工具确保正确处理位于 UITableViews 上的 UIImageView。它不包含磁盘缓存。

用法

imageView.loadImage(url: "https://aepryus.com/resources/aexels01s.png")
imageView.loadImage(url: "https://aepryus.com/resources/Force3.jpg", placeholder: tempImage) {
    print("Image Loaded")
}
    
UIImage.loadImage(url: "https://aepryus.com/resources/tnEvolizer1.jpg") { (image: UIImage) in
    print("already loaded")
} willLoad: {
    print("will load")
} finishedLoading: { (image: UIImage) in
    print("finished loading")
}

Pond and Pebbles (池塘与鹅卵石)

Pond and Pebbles 是一个异步控制流系统,可以极大地帮助解开复杂的异步任务,如应用程序初始化。通过 BackgroundPond,它还可以更容易地在应用程序关闭后完成异步任务。

用法

class BootPond: Pond {
    lazy var needNotMigrate: Pebble = {/*...*/}()
    lazy var migrate: Pebble = {/*...*/}
    lazy var ping: Pebble = {
        pebble(name: "Ping") { (complete: @escaping (Bool) -> ()) in
            Pequod.ping { complete(true) }
                failure: { complete(false) }
        }
    }()

    lazy var loadOTID: Pebble = {
        pebble(name: "Load OTID") { (complete: @escaping (Bool) -> ()) in
            complete(Pequod.loadOTID() && Pequod.loadExpired())
        }
    }()
    lazy var loadUser: Pebble = {
        pebble(name: "Load User") { (complete: (Bool) -> ()) in
            complete(Pequod.loadUser())
        }
    }()
    lazy var loadToken: Pebble = {
        pebble(name: "Load Token") { (complete: (Bool) -> ()) in
            complete(Pequod.loadToken())
        }
    }()

    lazy var isLocallySubscribed: Pebble = {/*...*/}()
    lazy var isRemotelySubscribed: Pebble = {/*...*/}()

    lazy var receiptValidation: Pebble = {/*...*/}()
    lazy var userLogin: Pebble = {/*...*/}()
    lazy var otidLogin: Pebble = {/*...*/}()

    lazy var showOffline: Pebble = {/*...*/}()
    lazy var showSubscribe: Pebble = {/*...*/}()
    lazy var showSignUp: Pebble = {/*...*/}()
    lazy var queryCloud: Pebble = {/*...*/}()
    lazy var startOovium: Pebble = {/*...*/}()

    lazy var invalid: Pebble = {/*...*/}()

// Init ============================================================================================
    override init() {
         super.init()

        loadOTID.ready = { true }
        loadToken.ready = { true }
        loadUser.ready = { true }
        needNotMigrate.ready = { true }
        ping.ready = { true }
        queryCloud.ready = { true }

        migrate.ready = { self.needNotMigrate.failed }

        isLocallySubscribed.ready = { self.loadToken.succeeded }
        isRemotelySubscribed.ready = {
            self.ping.succeeded
            && self.isLocallySubscribed.failed
        }

        userLogin.ready = {
            self.ping.succeeded
            && self.loadToken.failed
            && self.loadUser.succeeded
        }

        receiptValidation.ready = {
            self.ping.succeeded
            && self.loadToken.failed
            && self.loadOTID.failed
            && (self.loadUser.failed || self.userLogin.failed)
        }

        otidLogin.ready = {
            self.ping.succeeded
            && self.loadToken.failed
            && (self.loadOTID.succeeded || self.receiptValidation.succeeded)
            && (self.loadUser.failed || self.userLogin.failed)
        }

        showOffline.ready = {
            self.ping.failed
            && self.loadToken.failed
        }

        showSubscribe.ready = {
            self.ping.succeeded
            && (self.receiptValidation.failed || self.isRemotelySubscribed.failed)
        }

        showSignUp.ready = {
            self.ping.succeeded
            && self.loadToken.succeeded
            && self.loadOTID.succeeded
            && (self.isLocallySubscribed.succeeded || self.isRemotelySubscribed.succeeded)
            && self.loadUser.failed
        }

        startOovium.ready = {
            self.loadToken.succeeded
            && self.loadOTID.succeeded
            && (self.loadUser.succeeded || self.ping.failed)
            && (self.isLocallySubscribed.succeeded || self.isRemotelySubscribed.succeeded)
            && (self.needNotMigrate.succeeded || self.migrate.succeeded)
            && self.queryCloud.succeeded
        }

        invalid.ready = {
            self.loadToken.succeeded
            && self.loadOTID.failed
        }
    }
}

class ExitPond: BackgroundPond {
    lazy var saveAether: Pebble = {
        pebble(name: "Save Aether") { (complete: @escaping (Bool) -> ()) in
            Oovium.aetherView.saveAether { (success: Bool) in
                complete(success)
            }
        }
    }()

    init() {
        super.init { print("ExitPond timed out without completing.") }
        saveAether.ready = { true }
    }
}

class OoviumDelegate: UIResponder, UIApplicationDelegate {
    let bootPond: BootPond = BootPond()
    let exitPond: ExitPond = ExitPond()
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        bootPond.start()
        return true
    }
    func applicationWillResignActive(_ application: UIApplication) {
        exitPond.start()
    }
}

它还包括为各种异步路径编写测试的机制

XCTAssert(pond.test(shouldSucceed: [
    pond.needNotMigrate,
    pond.ping,
    pond.queryCloud,
    pond.showSubscribe,
], shouldFail: [
    pond.loadOTID,
    pond.loadUser,
    pond.loadToken,
    pond.receiptValidation,
]))

Odds and Ends (杂项)

用法

let button: UIButton = UIButton()
button.addAction {
    print("Hello, Acheron")
}