Code Monkey home page Code Monkey logo

cupcake's Introduction

cupcake

Swift4 Swift5 Platform Version License

Introduction

Cupcake is a framework that allow you to easily create and layout UI components for iOS 8.0+. It use chaining syntax and provides some frequent used functionalities that are missing in UIKit.


Easy way to create UIFont, UIImage and UIColor objects

You can create UIFont object with Font() function.

Font(15)                    //UIFont.systemFontOfSize(15)
Font("15")                  //UIFont.boldSystemFontOfSize(15)
Font("body")                //UIFontTextStyle.body
Font("Helvetica,15")        //helvetica with size of 15

You can create UIImage object with Img() function.

Img("imageName")            //image with name
Img("#imageName")           //prefixed with # will return a stretchable image
Img("$imageName")           //prefixed with $ will return a template image
Img("red")                  //1x1 size image with red color

You can create UIColor object with Color() function.

Color("red")                //UIColor.red
Color("0,0,255")            //RGB color
Color("#0000FF")            //Hex color
Color("random")             //random color

Color("red,0.5")            //even with alpha
Color("0,0,255,0.8")
Color("#0000FF,0.5")
Color("random,0.2")

Color(Img("pattern"))       //or image

Easy way to create NSAttributedString objects and String manipulations

You can create NSAttributedString object with AttStr() function.

AttStr("hello").color("red")                        //red color string
AttStr("hello, 101").select("[0-9]+").underline     //101 with underline
AttStr("A smile ", Img("smile"), " !!")             //insert image attachment

String manipulations:

Str(1024)                                           //convert anything to string
Str("1 + 1 = %d", 2)                                //formatted string

"hello world".subFrom(2).subTo("ld")                //"llo wor"
"hello world".subAt(1..<4)                          //"ell"
"hello 12345".subMatch("\\d+")                      //"12345"

4 basic UI components

You can create UIView, UILabel, UIImageView and UIButton objects simply by using View, Label, ImageView and Button variables.

View.bg("red").border(1).radius(4).shadow(0.7, 2)

Label.str("hello\ncupcake").font(30).color("#FB3A9F").lines(2).align(.center)

ImageView.img("cat").mode(.scaleAspectFit)

Button.str("kitty").font("20").color("#CFC8AC").highColor("darkGray").onClick({ _ in
    print("click")
}).img("cat").padding(10).border(1, "#CFC8AC")

As you can see, .font(), .img() and .color() can take the same parameters as Font(), Img() and Color(). Also you can pass String, NSAttributedString or any other values to .str().

Enhancements

You can add click handler and adjust click area to any view.
To round a view with half height no matter what size it is, simply use .radius(-1).

ImageView.img("mario").radius(-1).touchInsets(-40).onClick({ _ in
    print("extending touch area")
})

You can add line spacing and link handling to UILabel.

let str = "Lorem ipsum 20 dolor sit er elit lamet, consectetaur cillium #adipisicing pecu, sed do #eiusmod tempor incididunt ut labore et 3.14 dolore magna aliqua."
let attStr = AttStr(str).select("elit", .number, .hashTag, .range(-7, 6)).link()

Label.str(attStr).lineGap(10).lines().onLink({ text in
    print(text)
})

.bg() allow you to set background for any view with color or image.
.highBg() allow you to set highlighted background for UIButton (which is very useful).
Also you can add spacing to title and image within button or even exchange their position.

Button.str("More").img("arrow").color("black").bg("lightGray,0.3").highBg("lightGray").gap(5).reversed()

You can add placeholder and limit text input to UITextField and UITextView.

TextField.hint("placeholder").maxLength(10).padding(0, 10).keyboard(.numberPad)

TextView.hint("placeholder").maxLength(140).padding(10).onChange({ textView in
    print(textView.text)
})

Easy way to Setup Constraints

You use .pin() to setup simple constraints relative to self or superview.

.pin(200)                       //height constriant
.pin(100, 200)                  //width and height constraints			
.pin(.xy(50, 50))               //left and top constraints relative to superview
.pin(.maxXY(50, 50))            //right and bottom constraints relative to superview
.pin(.center)                   //center equals to superview
 ...
.pin(.lowHugging)               //low content hugging priority, useful when embed in StackView
.pin(.lowRegistance)            //low content compression resistance priority, useful when embed in StackView

You use .makeCons() and .remakeCons() to setup any constraints just like SnapKit.

.makeCons({
    $0.left.top.equal(50, 50)
    $0.size.equal(view2).multiply(0.5, 0.7)
})

.remakeCons({ make in
    make.origin.equal(view2).offset(10, 20)
    make.width.equal(100)
    make.height.equal(view2).multiply(2)
})

You use .embedIn() to embed inside superview with edge constriants.

.embedIn(superview)                     //top: 0,  left: 0,  bottom: 0,  right: 0
.embedIn(superview, 10)                 //top: 10, left: 10, bottom: 10, right: 10
.embedIn(superview, 10, 20)             //top: 10, left: 20, bottom: 10, right: 20
.embedIn(superview, 10, 20, 30)         //top: 10, left: 20, right: 30
.embedIn(superview, 10, 20, 30, 40)     //top: 10, left: 20, bottom: 30, right: 40
.embedIn(superview, 10, 20, nil)        //top: 10, left: 20

Easy way to Layout

Setup constraints for every views manually could be tedious. Luckily, you can build most of the layouts by simply using HStack() and VStack() (which are similar to UIStackView) and hopefully without creating any explicit constirants.

indexLabel = Label.font(17).color("darkGray").align(.center).pin(.w(44))
iconView = ImageView.pin(64, 64).radius(10).border(1.0 / UIScreen.main.scale, "#CCC")
    
titleLabel = Label.font(15).lines(2)
categoryLabel = Label.font(13).color("darkGray")
    
ratingLabel = Label.font(11).color("orange")
countLabel = Label.font(11).color("darkGray")
    
actionButton = Button.font("15").color("#0065F7").border(1, "#0065F7").radius(3)
actionButton.highColor("white").highBg("#0065F7").padding(5, 10)
    
iapLabel = Label.font(9).color("darkGray").lines(2).str("In-App\nPurchases").align(.center)
    
let ratingStack = HStack(ratingLabel, countLabel).gap(5)
let midStack = VStack(titleLabel, categoryLabel, ratingStack).gap(4)
let actionStack = VStack(actionButton, iapLabel).gap(4).align(.center)
    
HStack(indexLabel, iconView, 10, midStack, "<-->", 10, actionStack).embedIn(self.contentView, 10, 0, 10, 15)

appStore

Lightweight Style

Some of the chainable properties can be set as style.

//local style
let style1 = Styles.color("darkGray").font(15)
Label.styles(style1).str("hello world")

//global style
Styles("style2").bg("red").padding(10).border(3, "#FC6560").radius(-1)
Button.styles(style1, "style2").str("hello world")

//copy style from view
let style3 = Styles(someButton)
Button.styles(someButton).str("hello world")

Others

You can create static tableView with PlainTable() or GroupTable() functions.

let titles = ["Basic", "Enhancement", "Stack", "StaticTable", "Examples"]
PlainTable(titles).onClick({ row in
    print(row.indexPath)
})

You can present Alert And ActionSheet using the chaining syntax as well.

Alert.title("Alert").message("message go here").action("OK").show()

ActionSheet.title("ActionSheet").message("message go here").action("Action1", {
    print("Action1")
}).action("Action2", {
    print("Action2")
}).cancel("Cancel").show()

Installation

Cocoapods

Cupcake can be added to your project using CocoaPods by adding the following line to your Podfile:

pod "Cupcake"

Carthage

If you're using Carthage you can add a dependency on Cupcake by adding it to your Cartfile:

github "nerdycat/Cupcake"

cupcake's People

Contributors

nerdycat 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

cupcake's Issues

Value of type 'UILabel' has no member 'pin'

For the following line

indexLabel = Label.font(17).color("darkGray").align(.center).pin(.w(44))

Xcode throws the following error

Value of type 'UILabel' has no member 'pin'

Can you add shadow color ?

Thank you for this awesome library
Can you add shadow color to shadow() to fill xxx.layer.shadowColor
Cheers,

HStack Fill equally

Hello,
I have two label inside HStack and i want to make them fill equally (each label = 50% width of content)
How can i do that ? I tried align(.fill) but didn't work

Failed to build with Carthage

This happened with Xcode 12.0 and Carthage:

*** Building scheme "Cupcake" in Cupcake.xcodeproj
Build Failed
Task failed with exit code 1:
/usr/bin/xcrun lipo -create /Users//Library/Caches/org.carthage.CarthageKit/DerivedData/12.0_12A7209/Cupcake/1.3.1/Build/Intermediates.noindex/ArchiveIntermediates/Cupcake/IntermediateBuildFilesPath/UninstalledProducts/iphoneos/Cupcake.framework/Cupcake /Users//Library/Caches/org.carthage.CarthageKit/DerivedData/12.0_12A7209/Cupcake/1.3.1/Build/Products/Release-iphonesimulator/Cupcake.framework/Cupcake -output /Users//Desktop//Carthage/Build/iOS/Cupcake.framework/Cupcake

Swift 4 Support.

Hi. Thanks for helpfully lib but could you please add Swift 4 support. Thanks!

Xcode 10.2 support

After updated Xcode 10.2, swift compiler gets error following

if style != .none && style != .single && style != .thick && style != .double {
:: 'none' is unavailable: use [] to construct an empty option set

I think ".none" option is gone now.

UITextView causes NSZomebie when deallocating.

co-worker found this issue.

I do not know what is make this problem exactly.

This issue does not appear if remove below code and KVO observes.
UITextView.cpk_swizzle(method1: "dealloc", method2: #selector(UITextView.cpk_deinit))

image

I found some answers. but I can not found the reason.

Someone did test method swizzle already(https://github.com/inamiy/Swizzle/blob/master/SwizzleTests/_TestObject.swift).

It can be a reason.

Deinitializers are called automatically, just before instance deallocation takes place. You are not allowed to call a deinitializer yourself. Superclass deinitializers are inherited by their subclasses, and the superclass deinitializer is called automatically at the end of a subclass deinitializer implementation. Superclass deinitializers are always called, even if a subclass does not provide its own deinitializer.

Safe Area vs Top Layout Guide

Hi! Thanks a lot for this cool library :)

I use Swift 4 with latest Xcode 9 and want to embed a table in the view of my main view controller, which I embedded in a navigation controller via the storyboard in interface builder, looks quite similar to the cupcake demo. Now on newer projects, I do not have the top and bottom layout guides, as they are deprecated, only the safe area. When I add a GroupTable to my main view now, the navigation item / bar on top overlays the group table I created. I have to add it with e.g. addTo(self.view, 60, 0, 0, 0) in setupUI so that the table is rendered below the navigation bar. If I run the same code on iOS 9.3 devices (with 60
top), this adds a not so nice margin between the header and the table, meaning I have to use different parameters for addTo for iOS 9.3 and iOS 11
to get the same result. Do you know if this needs a fix in the library or is the problem somewhere else / can be fixed otherwise?

Thanks a lot for your support!
Cheers

How to solve flicker?

    let bgView = View.bg(UIColor.c_mask_b)
    
    let contentView = View.bg("white").radius(Specs.metric.cornerRadius).pin(.center)
    contentView.addTo(bgView).makeCons({ (make) in
        make.right.equal(bgView).offset(Specs.metric.ratioMargin)
        make.right.equal(bgView).offset(-Specs.metric.ratioMargin)
        make.center.equal(bgView)
    })
    var stacks = [Any]()
    for (index, desc) in descs.enumerated() {
        var text = "\(index+1)"
        if !firstHasNo {
            text = "\(index)"
        }
        let icon = Button
            .bg(UIColor.c_tint)
            .str(text)
            .color("white")
            .font(Specs.font.small)
            .pin(.wh(16, 16))
            .radius(8)
        
        let label = Label
            .str(desc)
            .lines(0)
            .font(Specs.font.small)
            .color(UIColor.c_title)
        if !firstHasNo && index == 0 {
            stacks.append(
                HStack(label).align(.top)
            )
        } else {
            stacks.append(
                HStack(icon ,label).gap(Specs.metric.marginTen).align(.top)
            )
        }
        stacks.append(Specs.metric.marginTen)
    }
    
    let imgView = ImageView
        .bg("gray")
        .pin(.whRatio(1.86))
    let imgStack = HStack(Specs.metric.ratioMargin, imgView, Specs.metric.ratioMargin)
    
    let sureButton = Button
        .str("Được").color("white").font(Specs.font.llarge)
        .bg(UIColor.c_tint)
        .radius(Specs.metric.cornerRadius)
        .pin(.h(44.0))
    let buttonStack = HStack(sureButton)
    
    VStack(imgStack,
           Specs.metric.ratioMargin,
           stacks,
           Specs.metric.ratioMargin,
           buttonStack
        )
        .embedIn(contentView, Specs.metric.ratioMargin)
        .align(.fill)
    bgView.embedIn(UIApplication.shared.keyWindow!)
    bgView.setNeedsLayout()
    bgView.layoutIfNeeded()

Update constraint added in storyboard

I have two view (view1 and view2) in storyboard and i have constraints top space between them,
I want to update it by code, i did this:

view2.remakeCons({
$0.top.equal(view1).bottom.offset(40)
})

But i got this error:
'Unable to activate constraint with anchors <NSLayoutYAxisAnchor:0x1c4a70e00 "UIView:0x13dd5e590.top"> and <NSLayoutYAxisAnchor:0x1c067ca00 "View1:0x13de2fd70.bottom"> because they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies? That's illegal.'

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.