SwiftUI-CSS: 一個(gè)實(shí)現(xiàn)樣式系統(tǒng)的庫(kù)

本文的主角[SwiftUI-CSS](https://github.com/hite/SwiftUI-CSS) 是個(gè) SwiftUI 庫(kù)秒际,它的目的是為了實(shí)現(xiàn)類(lèi)似 web 開(kāi)發(fā)領(lǐng)域結(jié)構(gòu)樣式分離的效果:

  • HTML 負(fù)責(zé)結(jié)構(gòu)
  • CSS 負(fù)責(zé)結(jié)構(gòu)樣式

樣式不寫(xiě)在 HTML 的屬性里而是在 CSS 當(dāng)中娄徊,不僅僅為了解耦;更重要的是復(fù)用进萄,促使開(kāi)發(fā)者把所有的業(yè)務(wù)樣式需求分解,提煉良好的基礎(chǔ)樣式沿癞,以更系統(tǒng)方式的管理樣式矛渴。

CSS 天然的提供 classname 機(jī)制,可以實(shí)現(xiàn)樣式分組和組合筐赔;一個(gè)業(yè)務(wù)樣式的最終效果可以是一些基礎(chǔ)樣式組合而成揖铜,不同組合呈現(xiàn)不同的效果天吓。

<div class="fontStyle colorStyle floatStyle">
</div>

本質(zhì)上講 CSS 里的一個(gè) classname 封裝了一組屬性(property)的集合,簡(jiǎn)稱(chēng)樣式龄寞。多個(gè) classname 即可組合成為一個(gè)樣式系統(tǒng)物邑;一個(gè)樣式系統(tǒng)實(shí)現(xiàn)業(yè)務(wù)上組件設(shè)計(jì)色解。配合具體的 HTML 結(jié)構(gòu)就是一個(gè)組件(component)。

SwiftUI-CSS 將 CSS 的技術(shù)優(yōu)勢(shì)帶到了 SwiftUI 開(kāi)發(fā)中在抛,不僅可以實(shí)現(xiàn) SwiftUI 里樣式屬性的復(fù)用刚梭、解構(gòu)票唆,還可以變化出很多類(lèi)似 web 領(lǐng)域的優(yōu)秀技術(shù)方案走趋。SwiftUI-CSS 的詳細(xì)使用可參見(jiàn)SwiftUI-CSS readme簿煌。本文試圖探討 SwiftUI-CSS 能為 SwiftUI,乃至 iOS 開(kāi)發(fā)帶來(lái)什么樣促進(jìn)和影響惩琉。

(閱讀本文需要你對(duì) SwiftUI 有基本的了解)

1. 什么是樣式系統(tǒng)瞒渠?

樣式系統(tǒng)指的是對(duì) UI 設(shè)計(jì)規(guī)范中,提煉出來(lái)的一些規(guī)范嫩痰。以 Ant Design 為例串纺。它的“字體使用規(guī)范”里指出造垛,主標(biāo)題的樣式是這樣的晰搀;

主標(biāo)題

主標(biāo)題的樣式至少包含4 個(gè)關(guān)鍵屬性:

  1. 字體 font family(包括英文字體)
  2. 字重 font weight
  3. 字號(hào) font size
  4. 字體顏色 color
  5. 行高行間距(當(dāng)文字有可能多行時(shí))line-height

如果用 CSS 那么它的樣式定義是這樣的(以 main_title 作為樣式系統(tǒng)里的命名):

.main_title{
    color: rgb(102, 102, 102);
    font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", 微軟雅黑, SimSun, sans-serif;
    font-size: 16px;
    font-weight: 500;
}

定義好之后杆逗,.main_title 就代表了設(shè)計(jì)師對(duì)主標(biāo)題的視覺(jué)要求鳞疲,可以在后面的界面中反復(fù)使用尚洽,而不需要再字體腺毫、字號(hào)、字重睛挚、顏色定義一遍扎狱。

這是比較基礎(chǔ)的樣式勃教,稍微復(fù)雜點(diǎn)的例子是按鈕故源,按鈕的樣式不僅包含字體的樣式心软,還包括按鈕的邊距、圓角耳贬、背景色等屬性咒劲。

文案樣式

按鈕樣式

看起來(lái)需要定義的樣式還有點(diǎn)多腐魂;但得益于 CSS 的層疊樣式的特性蛔屹,文字和按鈕兩部分的代碼可以寫(xiě)到一個(gè)樣式 .buttonStyle里兔毒。

      .buttonStyle{
            width: 212px;
            height: 40px;
            border-radius: 20px;
            background-color: #dd1a21;
            line-height: 40px;
            font-family: PingFang-SC-Bold;
            font-size: 16px;
            color: #FFFFFF;
            text-align: center;
        }

后續(xù)界面里需要這種確定按鈕的時(shí)候育叁,只需要引用 .buttonStyle 樣式名就可以了芍殖。更好的例子可參考 Twitter 出品的 Bootstrap 來(lái)學(xué)習(xí)如何組織管理 CSS 樣式豌骏。

2. 為什么樣式系統(tǒng) 對(duì) App 開(kāi)發(fā)重要

  1. 使用樣式系統(tǒng)肯适,要求視覺(jué)和開(kāi)發(fā)同學(xué)對(duì)整體視覺(jué)有全局掌握。
    對(duì)于視覺(jué)同學(xué)蹦玫,梳理視覺(jué)規(guī)范樱溉,定義哪些是通用規(guī)則福贞,哪些是個(gè)性規(guī)則停士,哪些是基礎(chǔ)規(guī)則,以及如何對(duì)基礎(chǔ)規(guī)則進(jìn)行運(yùn)算逻族;開(kāi)發(fā)同學(xué)提供樣式接口時(shí)聘鳞,需要在實(shí)現(xiàn)視覺(jué)要求的基礎(chǔ)上要拂,還能夠保證擴(kuò)展性和易讀性脱惰。在對(duì)視覺(jué)規(guī)范有深入理解之后枪芒,設(shè)計(jì)出來(lái)的視覺(jué)規(guī)范才有用,更健壯纽甘。
  2. 作為頁(yè)面仔悍赢,在日常工作中左权,快速實(shí)現(xiàn)效果是非常重要的痴颊,希望我們的樣式:
  • 可復(fù)用蠢棱。如果視覺(jué)稿是按照原有規(guī)范實(shí)現(xiàn)的泻仙,那么新需求里的頁(yè)面玉转,也可以使用已有的樣式來(lái)快速搭建,就像搭積木一樣猾担。
  • 易維護(hù)绑嘹。而且實(shí)際工作中圾叼,在某個(gè)具體頁(yè)面迭代最多的恐怕就是視覺(jué)優(yōu)化了夷蚊。如果你使用的樣式系統(tǒng)髓介,在處理:二行變?nèi)刑拼 粹o右上角加個(gè)圖標(biāo)一膨、整個(gè)文字描述塊整體向右移動(dòng)等等需求變化時(shí)豹绪,如果能夠快速實(shí)現(xiàn),而不是需要結(jié)構(gòu)大改(這樣容易改出新問(wèn)題)蝉衣,那么說(shuō)明你的樣式系統(tǒng)和 UI 接口劃分是面向需求變化的病毡。能夠應(yīng)付大部分(不要求 100 %)需求增改啦膜,就是個(gè)設(shè)計(jì)良好的組件功戚。

3. CSS 里的樣式系統(tǒng)

上述的 main_title,buttonStyle 是基礎(chǔ)元素樣式啸臀,在組件庫(kù)里,會(huì)有一些基礎(chǔ)元素樣式豌注、基礎(chǔ)功能樣式轧铁,一些復(fù)雜的組件需要用這些基礎(chǔ)元素樣式齿风、基礎(chǔ)功能樣式組合而成绑洛。

/**元素樣式**/
.w-seperator{
    height: 2px;
    width: 100%;
    backgroundColor: #ff00ff;
}
/**功能樣式**/
.f-hide{
  display:none;
}
/**功能樣式**/
.f-clear_both{
   clear:both;
}
// 請(qǐng)忽略這個(gè)樣式的實(shí)際意義
<div class="w-seperator f-clear_both f-hide"></div>

這里w-seperator f-clear_both f-hide 即是這個(gè)分割線(xiàn)的樣式名稱(chēng)脸候。

這是原生 CSS 就支持的使用方式运沦,還是比較粗放配深,w-seperator f-clear_both f-hide 并不是那么簡(jiǎn)潔凉馆。如借助預(yù)編譯澜共,還可以使用變量嗦董、繼承等特性來(lái)簡(jiǎn)化 CSS 的定義工作京革。比方使用 sass匹摇。

.w-seperator{
    height: 2px;
    width: 100%;
    backgroundColor: #ff00ff;
}
.f-hide{
  display:none;
}
.f-clear_both{
   clear:both;
}
.seperator_in_list{
   @extend .w-seperator;
   @extend .f-hide;
   @extend .f-clear_both;
}

這樣.seperator_in_list這個(gè)名字就是我們?cè)诤竺娼缑胬锟捎玫臉邮矫炔绕?CSS 是不是更見(jiàn)文知意经窖,更易用呢画侣?

4. iOS 開(kāi)發(fā)里的樣式系統(tǒng)

Cocoa touch 并沒(méi)有提供樣式系統(tǒng)的語(yǔ)法配乱,有些開(kāi)發(fā)者可能會(huì)自己封裝一層搬泥,大部分封裝都比較初級(jí)佑钾。比方說(shuō)只對(duì) App 里的按鈕封裝了工廠(chǎng)類(lèi);或者只對(duì) Label 設(shè)置字號(hào)扰她、字體徒役、顏色做了封裝忧勿,沒(méi)有形成進(jìn)一步封裝瞻讽。

  • 對(duì)按鈕 Button 的封裝速勇;
// 黑色中空烦磁,中間是clear color
+ (instancetype)yx_BlackHollowClearButton {
    YXButton* button = [YXButton new];
    button.titleLabel.font = [UIFont systemOfSize:14];
    
    [button setTitleColor:YXColorGray4 forState:UIControlStateNormal];
    [button setTitleColor:YXColorWhite forState:UIControlStateHighlighted];
    [button setTitleColor:YXColorGray10 forState:UIControlStateDisabled];
    
    button.layer.borderWidth = YX_ONE_PIXEL;
    button.layer.borderColor = YXColorGray4;
    button.layer.cornerRadius = YXButtonCornerRadius;
    button.layer.masksToBounds = YES;
    return button;
}
  • 對(duì) UILabel 的樣式封裝
    UILabel *label = [UILabel new];
    [NYQSpec setLabelStyle:label withNYQCode:NYQCode_18_blk_med];
    label.textAlignment = NSTextAlignmentCenter;
    label.text = @"請(qǐng)確認(rèn)以下信息";

簡(jiǎn)單的對(duì)照呕乎,發(fā)現(xiàn)復(fù)用只能復(fù)用屬性猬仁,如舉例中的YXColorGray4NYQCode_18_blk_med逐虚,如果要設(shè)置一組屬性需要再次設(shè)置,沒(méi)有一個(gè)對(duì)象如 importantStyle 來(lái)代表顏色和字體等撮躁,使得下一個(gè) button 可以直接設(shè)置importantStyle 的把曼。

// 不存在這樣的系統(tǒng)接口
UIStyle *importantStyle = [UIStyle styleWithColor: [UIColor redColor] font: YX_Button_Font];
// 確認(rèn)按鈕
UIButton *confirm = [UIButton new];
[confirm setStyle: importantStyle];
// 提示按鈕
UIButton *prompt = [UIButton new];
[prompt setStyle: importantStyle];

我想原因就是 Cocoa touch 設(shè)計(jì)之初就沒(méi)有考慮用對(duì)象來(lái)表示一組屬性嗤军,沒(méi)有設(shè)計(jì)樣式系統(tǒng)的概念叙赚,導(dǎo)致在封裝實(shí)現(xiàn)樣式系統(tǒng)時(shí)比較困難僚饭。

補(bǔ)充提示

[button setStyle:] 這個(gè)接口其實(shí)可以使用category技術(shù)來(lái)實(shí)現(xiàn)鳍鸵,UIStyle 可以用自定義封裝偿乖,只要 UIStyle 實(shí)現(xiàn)了接口击罪,任何樣式的屬性都可以封裝到一個(gè) UIStyle 的實(shí)例中。這種方式和下面即將介紹 SwiftUI-CSS 的封裝本質(zhì)不同在于贪薪,UIStyle 里的屬性不能運(yùn)算媳禁,[button setStyle:]本質(zhì)是把屬性?huà)煸谝粋€(gè)全局變量下,然后遍歷画切,在性能方面沒(méi)有提升损话,充其量是一種語(yǔ)法糖。

UIStyle *importantStyle = [UIStyle styleWithColor: [UIColor redColor] font: YX_Button_Font];
// 一種 setStyle 內(nèi)部實(shí)現(xiàn)
- (void)setStyle:(UIStyle *)style{
    if(style.font){
        self.titleLabel.font = style.font
    }
    if(style.color){
        [self setTitleColor:style.color forState:UIControlStateNormal];
    }
}
// 理想中的槽唾,目前無(wú)法實(shí)現(xiàn)
- (void)setStyle:(UIStyle *)style{
    if (style.computedStyle == nil) {
        [style compute];
    }
// computedStyle 包含了字體和顏色
    [self setFinalStyle:style.computedStyle];
}

理想中的 computedStyle 在真正使用到樣式上,才對(duì)所有屬性進(jìn)行一次計(jì)算庞萍,這樣在后續(xù)其他 button 設(shè)置時(shí)拧烦,直接使用計(jì)算結(jié)果,而不是再次使用遍歷的方式去一一設(shè)置钝计。屬性計(jì)算帶來(lái)的性能提升恋博,類(lèi)似在 JS 模板引擎中常用的字符串模板編譯成 function 帶來(lái)效果齐佳,甚至更高。

使用 storyboard 的界面開(kāi)發(fā)

使用代碼實(shí)現(xiàn)樣式系統(tǒng)至少還可以使用全部變量债沮、宏炼吴、函數(shù)封裝來(lái)達(dá)到某種意義上的復(fù)用,維護(hù)疫衩。但是如果使用 storyboard 實(shí)現(xiàn)的界面硅蹦,則需要面對(duì)更多的問(wèn)題。
storyboard 在快速搭建單個(gè)界面時(shí)效率非常高闷煤。假設(shè)需要更新品牌色時(shí)童芹,至少還可以用 asset catalog 來(lái)實(shí)現(xiàn)全局的顏色修改,但是涉及到如“主標(biāo)題”字號(hào)修改時(shí)鲤拿,則顯得無(wú)能為力假褪,只能一個(gè)一個(gè) storyboard 去修改,更不要說(shuō)一起修改多個(gè)屬性的組合了近顷。

storyboard 最多可以在小組件層復(fù)用生音,向上到 ViewController 粒度太多不容易復(fù)用;向下只能使用 xib 復(fù)用組件—— storyboard 不存在樣式系統(tǒng)窒升。

直到 SwiftUI 橫空出世久锥,把描述性界面開(kāi)發(fā)體驗(yàn)帶到 iOS,它的函數(shù)式語(yǔ)法和屬性對(duì)象方式异剥,使得可以用Swift-CSS 來(lái)實(shí)現(xiàn) SwiftUI 里樣式系統(tǒng)。

5. SwiftUI

SwiftUI 里的鏈?zhǔn)秸Z(yǔ)法絮重,是函數(shù)式函數(shù)調(diào)用的體現(xiàn)冤寿。SwiftUI 實(shí)體分為 ViewContentModifierText("g_kumar") 負(fù)責(zé)視圖結(jié)構(gòu)青伤;.font(.title) 添加屬性樣式督怜。簡(jiǎn)單的實(shí)例;

Text("g_kumar")
      .bold()
      .font(.title)
Text("Notifications: \(self.profile.prefersNotifications ? "On": "Off" )")
Text("Seasonal Photos: \(self.profile.seasonalPhoto.rawValue)")
Text("Goal Date: \(self.profile.goalDate, formatter: Self.goalFormat)")

預(yù)覽

g_kumar文字組件為例狠角,我們應(yīng)用函數(shù)式編程里的運(yùn)算規(guī)律-結(jié)合律推導(dǎo)一番:

  • Text("g_kumar") 用 v 表示
  • .bold() 用 cm1 表示
  • .font(.title) 用 cm2 表示
  • 最終組件是 C
C = v * cm1 * cm2
// =>
C = (v * cm1) * cm2
// =>
C = v *( cm1  * cm2)
// =>
cm = cm1 * cm2
C = v * cm
// 假設(shè) v1 是另外一個(gè) Text号杠,則
C1 = v1 * cm

所以,上面公式里的 cm 代表了樣式的計(jì)算結(jié)果丰歌,在這里是指字形和字號(hào)的運(yùn)算結(jié)果姨蟋。利用這個(gè)計(jì)算結(jié)果,在后面的樣式設(shè)置 v1,v2 等視圖時(shí)可以直接使用 cm 來(lái)設(shè)置樣式立帖。它帶來(lái)的性能提升眼溶,取決于 Apple 對(duì) cm 這個(gè)計(jì)算變量的內(nèi)部?jī)?yōu)化程度。鑒于目前 SwiftUI 閉源晓勇,我們還無(wú)法得知這種優(yōu)化帶來(lái)多大的提升堂飞;退一步講灌旧,將計(jì)算結(jié)果封裝為一個(gè)變量,當(dāng) Apple 后續(xù)對(duì) ContentModifier 計(jì)算進(jìn)行優(yōu)化后绰筛,調(diào)用者可透明的享受到優(yōu)化提升枢泰。

以上就是屬性運(yùn)算的原理,所以有了 SwiftUI-CSS铝噩。

5. SwiftUI-CSS 的樣式系統(tǒng)

SwiftUI 的原理很簡(jiǎn)單衡蚂。就是使用CSSStyle 對(duì)象來(lái)封裝樣式對(duì)象,然后通過(guò) addClassName 這個(gè) modifier 來(lái)將樣式插入函數(shù)運(yùn)算中薄榛,和其他事件讳窟、通知、樣式(.frame\ .resizable)一起無(wú)縫協(xié)作敞恋。以 SwiftUI-CSS example 工程為例丽啡;

// without SwiftUI-CSS
Image("image-swift")
                 .resizable()
                 .scaledToFit()
                 .frame(width:100, height:100)
                 .cornerRadius(10)
                 .padding(EdgeInsets(top: 10, leading: 0, bottom: 15, trailing: 0))
// with SwiftUI-CSS
let languageLogo_clsName = CSSStyle([
    .width(100),
    .height(100),
    .cornerRadius(10),
    .paddingTLBT(10, 0, 15,0)
])
Image("image-swift")
        .resizable()
        .scaledToFit()
        .addClassName(languageLogo_clsName)

其中,languageLogo_clsName就是 logo 的樣式名硬猫,在頁(yè)面其他 logo补箍,可以直接復(fù)用這個(gè)樣式。更多使用示例請(qǐng)查看SwiftUI-CSS example 工程啸蜜。

總結(jié)下 SwiftUI-CSS 帶來(lái)的好處:

  1. 解耦
    如同 web 領(lǐng)域開(kāi)發(fā)那樣坑雅,.html 、.css 文件是分開(kāi)的衬横。以產(chǎn)品詳情為例裹粤,典型目錄結(jié)構(gòu)是:

-- ProductDetail
|----ProductDetailView.swift
|----ProductDetailStyle.swift

ProductDetailView.swift 負(fù)責(zé)構(gòu)建界面的結(jié)構(gòu),里面只有 view 元素蜂林、事件邏輯遥诉、數(shù)據(jù)流等,保持簡(jiǎn)潔噪叙;而ProductDetailStyle.swift 里面是一些樣式的定義矮锈。兩個(gè)文件分離有助于 diff 、review 和和他人協(xié)作睁蕾。

  1. 復(fù)用
    當(dāng)有視覺(jué)規(guī)范后苞笨,按照規(guī)范,在公用的樣式文件里子眶,預(yù)先定義好所有基礎(chǔ)樣式瀑凝,如“主標(biāo)題”文字樣式等,然后定義若干公用的業(yè)務(wù)樣式臭杰,如出錯(cuò)彈窗猜丹。理想情況下,業(yè)務(wù)樣式和組件樣式都可以由這些基礎(chǔ)樣式像搭積木一樣拼湊而成硅卢。
  2. 性能提升
    按照理論射窒,CSSStyle 這樣的計(jì)算結(jié)果藏杖,是一種類(lèi)似編譯后的緩存(compiled code)總是有提升的。具體的測(cè)試數(shù)據(jù)脉顿,待 iPhone 11 上市和 macOS 10.15 發(fā)布之后再做評(píng)測(cè)蝌麸。請(qǐng)關(guān)注 SwiftUI-CSS 后續(xù)會(huì)補(bǔ)充。
  3. 樣式繼承
    在 CSS 領(lǐng)域艾疟,sass 提供的一些高級(jí)應(yīng)用如樣式繼承(見(jiàn)第三節(jié)3. CSS 里的樣式系統(tǒng)的例子)来吩,SwiftUI-CSS 也內(nèi)置了;
let fontStyle = CSSStyle([.font(.caption)])
let colorStyle = CSSStyle([.backgroundColor(.red)])
        
let finalStyle = fontStyle + colorStyle

button.addClassName(finalStyle)

利用CSSStyle提供的+ 運(yùn)算蔽莱,將多個(gè)樣式合并實(shí)現(xiàn)繼承效果弟疆。

6. 更多想象空間

以上只是我個(gè)人實(shí)踐中遇到的場(chǎng)景,在別人的手里可能還會(huì)迸發(fā)出不一樣的火花盗冷,以下是我的一些構(gòu)想:

SwiftUI zen-garden 計(jì)劃

在 web 開(kāi)發(fā)早期怠苔,人們對(duì) CSS 在 web 開(kāi)發(fā)中扮演的角色定位不是很清晰。在 2003年仪糖,由 Dave Shea 發(fā)起了 CSS zen garden 計(jì)劃柑司。這個(gè)網(wǎng)站提供一套固定的帶樣式名,但是沒(méi)有樣式實(shí)現(xiàn)的 .html 文件锅劝,然后參與者提供不同的 CSS 文件攒驰,來(lái)對(duì)相同的 HTML 結(jié)構(gòu)進(jìn)行 stylize,試圖探索 CSS 對(duì) HTML 結(jié)構(gòu)可定制能力的極限故爵。時(shí)至今日玻粪,已經(jīng)有 218 個(gè)五花八門(mén)的設(shè)計(jì)位列 Design List 其中,很多充滿(mǎn)想象力的設(shè)計(jì)讓人嘆為觀止诬垂。

CSS zen garden 的成功劲室,讓開(kāi)發(fā)者意識(shí)到 CSS 的無(wú)限可能性,同時(shí)也激勵(lì)諸多其它語(yǔ)言嘗試相同的項(xiàng)目剥纷。也同樣影響到我,而 SwiftUI-CSS 提供了可能性呢铆;

  • 提供一套固定的編寫(xiě)了 View 結(jié)構(gòu)的文件如 html.swift晦鞋,帶樣式名但是沒(méi)有設(shè)置屬性。
  • 參與者提供對(duì)這些樣式名的實(shí)現(xiàn)文件棺克,如 style.swift悠垛,和 html.swift 一起生成不同的界面設(shè)計(jì)。
    讓我們一起探索使用 SwiftUI 可定制能力的極限娜谊。

以上方案稱(chēng) SwiftUI zen garden(待實(shí)施)确买。

設(shè)計(jì)師和程序員協(xié)作——storyboard 未盡的夙愿

xib(storyboard 前身)早在 iOS1.0 之前就被 Apple 用在 iOS 的開(kāi)發(fā)工作流中:設(shè)計(jì)師用 Interface Builder 編寫(xiě) xib 文件,之后程序員用 xcode 在 xib 的基礎(chǔ)上繼續(xù)編寫(xiě)事件纱皆、數(shù)據(jù)等湾趾,業(yè)務(wù)邏輯芭商。但是因?yàn)?xib 變更后較難 diff 和 xib 并不是程序員使用 oc 語(yǔ)言,不能無(wú)縫復(fù)用搀缠,導(dǎo)致設(shè)計(jì)師和程序員分離開(kāi)發(fā)的目的沒(méi)有實(shí)現(xiàn)铛楣。

大部分設(shè)計(jì)師用 xib 完成的 App prototype,都不能直接讓程序員繼續(xù)開(kāi)發(fā)艺普。

更多時(shí)候 xib 的工程只是為了做 App 原型簸州,程序員還需要按照 prototype,完全或者部分用代碼重寫(xiě)歧譬。

有了 SwiftUI岸浑,設(shè)計(jì)師可以使用 SwiftUI 編寫(xiě) prototype,驗(yàn)證完畢之后瑰步,程序員拿 SwiftUI 源碼繼續(xù)開(kāi)發(fā)矢洲,因?yàn)槎际?swift 文件啊面氓;設(shè)計(jì)師后續(xù)的樣式調(diào)整兵钮,可以直接修改 style.swift 文件,不需要和程序員去競(jìng)爭(zhēng) html.swift 文件使用權(quán)舌界,避免沖突掘譬。
設(shè)計(jì)師和程序員無(wú)縫協(xié)作的大和諧,在 SwiftUI 中得到實(shí)現(xiàn)呻拌!

也許你還能想到更多用法葱轩,是不是?

7. 后記

SwiftUI-CSS 1 個(gè)月前就寫(xiě)好了藐握,當(dāng)我發(fā)布到 Twitter靴拱、Hacknews 等地方,邀請(qǐng)各位大V 宣傳時(shí)猾普,并沒(méi)有激起多少浪花袜炕,我認(rèn)為它的重要性被低估了,故作此文初家。

參考

  1. https://sass-lang.com
  2. https://en.wikipedia.org/wiki/CSS_Zen_Garden
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末偎窘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子溜在,更是在濱河造成了極大的恐慌陌知,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掖肋,死亡現(xiàn)場(chǎng)離奇詭異仆葡,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)志笼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)沿盅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)把篓,“玉大人,你說(shuō)我怎么就攤上這事嗡呼≈郊螅” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵南窗,是天一觀的道長(zhǎng)揍很。 經(jīng)常有香客問(wèn)我,道長(zhǎng)万伤,這世上最難降的妖魔是什么窒悔? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮敌买,結(jié)果婚禮上简珠,老公的妹妹穿的比我還像新娘。我一直安慰自己虹钮,他們只是感情好聋庵,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著芙粱,像睡著了一般祭玉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上春畔,一...
    開(kāi)封第一講書(shū)人閱讀 49,760評(píng)論 1 289
  • 那天脱货,我揣著相機(jī)與錄音,去河邊找鬼律姨。 笑死振峻,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的择份。 我是一名探鬼主播扣孟,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼荣赶!你這毒婦竟也來(lái)了凤价?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤讯壶,失蹤者是張志新(化名)和其女友劉穎料仗,沒(méi)想到半個(gè)月后湾盗,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體伏蚊,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年格粪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了躏吊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片氛改。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖比伏,靈堂內(nèi)的尸體忽然破棺而出胜卤,到底是詐尸還是另有隱情,我是刑警寧澤赁项,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布葛躏,位于F島的核電站,受9級(jí)特大地震影響悠菜,放射性物質(zhì)發(fā)生泄漏舰攒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一悔醋、第九天 我趴在偏房一處隱蔽的房頂上張望摩窃。 院中可真熱鬧,春花似錦芬骄、人聲如沸猾愿。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蒂秘。三九已至,卻和暖如春宰僧,著一層夾襖步出監(jiān)牢的瞬間材彪,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工琴儿, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留段化,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓造成,卻偏偏與公主長(zhǎng)得像显熏,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子晒屎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類(lèi)型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,090評(píng)論 1 32
  • 平安夜喘蟆, 梧桐葉落花兒謝。 花兒謝鼓鲁, 小河低訴蕴轨, 晚風(fēng)凄切。 云遮月色千里雪骇吭, 遙聽(tīng)大漠平安樂(lè)橙弱。 平安樂(lè), 青山原...
    春江細(xì)語(yǔ)閱讀 380評(píng)論 1 13
  • 要相信: 所有的難過(guò),難是難棘脐,總會(huì)過(guò); 你只管努力斜筐,剩下的交給時(shí)間?。 撐下去蛀缝,就有后來(lái)的一切顷链!
    Jenner接納閱讀 506評(píng)論 0 0
  • 月這個(gè)周末真的很忙碌,但是很溫暖屈梁。和親人在一起的時(shí)光嗤练,滿(mǎn)滿(mǎn)的都是愛(ài)。 謝謝你如此闊綽的送給爸媽結(jié)婚紀(jì)念日禮物在讶,送完...
    萍萍淡淡閱讀 310評(píng)論 1 3
  • 去年年底我爸查出肝癌潭苞,去醫(yī)院化療了一次,由于化療的副作用太大真朗,再加上我和哥哥都在上大學(xué)此疹,家里沒(méi)有多少錢(qián)去化療,...
    懂我不言閱讀 158評(píng)論 0 1