跳到主要内容

将JSON数据转换为结构体数据

· 阅读需 2 分钟
Web developer & UI designer

问题

假设我们从服务器获取了一个 JSON 类型的数据如下:

{"name": "Jone","age": 17}

请使用 swift 将其转换为结构体类型的数据,其中年龄转换为整型数据,并打印出来。

思路

首先将此 JSON 数据定义为字符串类型的数据,将其转换成 Data 型。

然后定义一个结构体类型的数据模型,使其遵守 Codable 协议,只要遵守这些协议才能进行 json 与模型之间的编码与解码。

接下来我们就可以进行讲 json 解码并映射成模型,打印出年龄值。

解答

//将 json 数据转换为字符串类型的数据,方法是使用三个双引号包裹,属于多行字符串,引号中什么样,打印出来就是什么样,格式都不会变。
let res = """
{
"name": "Jone",
"age": 17
}
"""

//使用字符串.data()方法对字符串进行转换转换之后打印显示 32bytes
let data = res.data(using: .utf8)!

//Codable 协议其实就是遵守一个关于解码的协议和一个关于编码的协议,只要遵守这些协议才能进行 Json 与模型之间的编码与解码。

struct Student : Codable{
let name : String
let age : Int
}

//接下来我们就可以将 json 解码并映射成模型
let decoder = JSONDecoder()

//!的意思是强制解码,因为我们知道 data 中有值
let stu = try! decoder.decode(Student.self, from: data)

//可以看到,stu.age 已经成为整型。
print(stu.age)

开发一个计算器APP——Part1:界面实现

· 阅读需 3 分钟
Web developer & UI designer

问题

使用 HStack 和 VStack 来实现计算器的界面。

Docusaurus Plushie

思路

任何复杂的界面都可以将其分解为单一的 HStack 和 VStack 来实现,计算器界面也一样,先用 HStack 将横排的按钮组合,然后再将 HStack 放入到 VStack 中。

Docusaurus Plushie

步骤一:按照界面元素从上到下的顺序开始写起,使用 HStack 和 VStack 组织好界面。

步骤二:通过创建自定义视图 View 和自定义 ViewModifier 将重复的控件(Text())和修饰符合并,简化代码。其中计算器数字部分“0”的样式,通过在 ViewModifier 中设置布尔值加三元运算符的方法来实现。

步骤三:由于自定义的 ViewModifier 有三种,分别对应计算器按钮的三种不同样式,还需要进一步合并,接下来使用双重数组加 ForEach 语句,并通过定义枚举数据类型将计算器按钮数据归类来完成合并。

解答

import SwiftUI

//计算器界面的主视图。
struct ContentView: View {
var body: some View {
VStack(spacing : 20){
Text("0")
.frame(maxWidth: .infinity, maxHeight: 200, alignment: .trailing)
.padding(.trailing, 50)
//系统自带的文字大小
.font(.system(size: 60))
.foregroundColor(Color("resule_fg"))
ForEach(0..<calcu_text.count){ i in
HStack{
ForEach(0..<calcu_text[i].count){ j in
CustomButton(calcu_text[i][j])
//这里是每个按钮的视图。
}
}
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color("calc_bg"))
//注意顺序
.edgesIgnoringSafeArea(.all)
}
}


//使用View协议,生成一个CustomButton复合视图,这个视图生成了每个按钮的内容和样式。
struct CustomButton : View {

let type : CalcButtonType

init(_ type : CalcButtonType) {
self.type = type
}

var body: some View{

Text(self.type.text)
.modifier(CalcModifier(type:self.type))

}
}


//使用View协议,生成一个CalcModifier复合修饰符来修饰每个按钮。
struct CalcModifier : ViewModifier {

let type : CalcButtonType
//让结构体的类型为枚举型

func body(content: Content) -> some View {
content
.frame(width: 80,height: 80)
.font(.title)
.background(self.type.bg_color)
//从固定的样式,变为动态样式
.foregroundColor(self.type.fg_color)
.cornerRadius(40.0)
}
}


//使用枚举类型数据,对复合修饰符和内容进行操作。
enum CalcButtonType{
//因为要给按钮设置三种样式,那么将之前数组类型的数据定义为枚举型,更方便使用。

case number(_ text:String)
//number是枚举的成员,关联值是一个字符串类型
case calc_opterator(_ text:String)
case calc_s_opterator(_ text:String)

var text : String {
//定义一个属性,这个属性直接返回text.

switch self {
case let.number(text) :
return text
case let.calc_opterator(text) :
return text
case let.calc_s_opterator(text) :
return text

}

}

var fg_color : Color{

switch self {
case .number(_) :
//如果匹配number,那么返回Color("darkgrey_operator_fg")
return Color("darkgrey_operator_fg")
case .calc_opterator(_) :
return Color("yellow_operator_fg")
case .calc_s_opterator(_) :
return Color("s_operator_fg")

}

}

var bg_color : Color{

switch self {
case .number(_) :
return Color("darkgrey_operator_bg")
case .calc_opterator(_) :
return Color("yellow_operator_bg")
case .calc_s_opterator(_) :
return Color("s_operator_bg")

}

}

}

prefix operator %
prefix operator -
prefix operator +

prefix func % (right : String) -> CalcButtonType{
return .calc_s_opterator(right)

}
prefix func - (right : String) -> CalcButtonType{
return .calc_opterator(right)

}
prefix func + (right : String) -> CalcButtonType{
return .number(right)

}
//将数据定义为枚举类型。
let calcu_text : [[CalcButtonType]] = [[%"AC",%"+/-",%"%",-"+"],[+"7",+"8",+"9",-"x"],[+"4",+"5",+"6",-"2"],[+"AC",+"+/-",+"%",-"2"],[+"0",+"+/-",-"="]]


struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

33个以圆形为基础的logo设计欣赏

· 阅读需 2 分钟
Web developer & UI designer

好的 Logo 设计最重要的方面不是看视觉上多么漂亮,而在于在表意上是否足够准确和直接。准确要求抓住产品和概念的特点进行抽象和提取,而直接则要求以简单直白的方式表达,要让人能看得懂,起码稍动脑筋就能明白。

就拿下图苹果的三个应用程序的图标举例来说,这三个图标视觉上看来都非常漂亮,细节很丰富,拟真感很强,但如果从表意的角度上来看的话,Numbers 的设计要优于其它的两个图标设计。虽然其他两个图标在概念上也基本抓住了应用程序的功能诉求,但还略显模糊,尤其是 Pages 墨水和钢笔的设计。

当然,虽然我们强调第一位的表意上的准确,但是视觉上的准确和美观也并非可有可无。这篇文章里,我收集了 33 个以圆形为基础的 logo 设计,虽然并非全部了解其中所表达的含义,但是起码在视觉设计上能给大家以启发和帮助,让我们看到如何在以圆形的基础上进行 Logo 的设计创作。

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

Docusaurus Plushie

将数据传递到待办事项列表中

· 阅读需 3 分钟
Web developer & UI designer

问题

创建如下图所示的待办事项列表视图,并将标题数据传递到待办事项中。

Docusaurus Plushie

思路

每一项待办事项所包含的数据都是一样的,因此我们可以通过创建一个 class 类型的数据,其中包括字符串数据类型的标题、日期类型的时间和布尔值类型的选框,然后使用 SwiftUI 中的 ForEach 语句对数据进行遍历,从而完成数据的传递。

解答

import SwiftUI

//让类从NSObject, NSCoder继承功能,保证下次打开APP时,数据还在
class Todo : NSCoder{

//每一个事项的标题
var title : String = ""
//每一个事项的日期
var dueDate : Date = Date()
//每一个事项是否打勾
var checked : Bool = false
//i用来记录某一待办事项是列表中的第几个待办事项
var i : Int = 0

init(title: String, dueDate: Date, checked: Bool){
//self.title代表类里面的title等于初始化函数里的参数title,如果这样写就好理解很多:
//self.title = a
self.title = title
self.dueDate = dueDate
self.checked = false
}
}

//var emptyTodo : Todo = Todo(title: "", dueDate: Date())

var exampleTodos: [Todo] = [
Todo(title: "看电影", dueDate: Date(), checked: false),
Todo(title: "看话剧", dueDate: Date(), checked: false),
Todo(title: "完成swiftUI", dueDate: Date(), checked: false),
Todo(title: "完成Sketch四个界面", dueDate: Date(), checked: false),
Todo(title: "洗锅", dueDate: Date(), checked: false),
Todo(title: "画画", dueDate: Date(), checked: false)
]

NavigationView{
ScrollView{
ForEach(0..<exampleTodos.count){todoIndex in
VStack{
HStack{
Button(action: {

})
{
//左边的部分,包括蓝边、项目标题及时间
HStack{
//蓝边
VStack{
Rectangle()
.fill(Color.blue)
//frame就是元素的大小
.frame(width: 8,height: 74)
}

//项目标题及时间
VStack{

//项目标题
HStack{
Text(exampleTodos[todoIndex].title)
.font(.headline)
.foregroundColor(exampleTodos[todoIndex].checked ? .gray : .blue)
//把标题挤到左边
Spacer()
}
//时间
HStack{
Image(systemName: "clock")
.resizable()
.frame(width: 12,height: 12)
Text("2020/1/21")
.font(.subheadline)
//不设置frame,无限大,把时间挤到左边
Spacer()
}
.foregroundColor(Color.gray)
}
//padding是元素和frame之间的边距
.padding(.leading,5)

}

}
Button(action: {

})
{
VStack{
Image(systemName: exampleTodos[todoIndex].checked ? "checkmark.square" : "square")
.resizable()
.frame(width: 24, height: 24)
.foregroundColor(Color.gray)
.animation(.easeInOut)
}
.padding()
}

}
//冒号前面表示checked为真时的背景色,后面为否时的背景色
.background(Color(exampleTodos[todoIndex].checked ? "SingleItemBgChecked" : "SingleItemBg"))
.cornerRadius(10)
//元素内边距
.padding(10)
}
}
}
.navigationBarTitle("待办事项")
}

10个从图片中提取的色彩方案分析

· 阅读需 4 分钟
Web developer & UI designer

每一张图片的色彩都有自己独特的个性,即使是表现同样主题的两张图片,比如秋日里森林的早晨,虽然可能都是偏褐色色调的,但色相、纯度、明度、搭配方法还是会有很大的不同,而这正是设计中从图片中提取色彩方案的魅力所在。如果将这些色彩应用到设计中的话,那每一个设计都可以做到绝对的个性化,起码在配色方面如此。因此在这篇文章中,我挑选了10张情绪上不同的图片,提取出它们的色彩方案,并进行分析,希望对于大家在配色方面有所帮助。

一、安静、温暖

Docusaurus Plushie

使用PS中"存储为Web和设备所用格式"的方法,将图片保存为png格式,颜色选择为8种颜色得到的色彩方案。由一组不同亮度、中饱和度的黄色和一个中饱和度和亮度的黄绿色搭配而成,给人安静、温暖的心理感受。

二、柔美、春天、女性

Docusaurus Plushie

花团锦簇、春意盎然的画面由两个明度偏低的黄色和一组明度较高的紫红色组成,这种色彩方案属于跨度较大的近似色搭配,两组不同的颜色在色环上跨度越大,画面会越生动,反之会越稳重。

三、纯净、简洁

Docusaurus Plushie

冬日里的白桦林图片中提取出的色彩是由一组低纯度、甚至于接近灰色的、不同明度的蓝色组成的色彩方案。使用这样的纯冷色调的搭配做出的设计会让人感受到一阵阵的寒意,但同时也给人纯净、简洁的感觉。

四、欢乐、节日

Docusaurus Plushie

节日般欢乐的色彩方案,由一组不同层次的天蓝色加上亮度、纯度很高的红色、绿色、紫色搭配而成,属于全色相的色彩搭配方案,适合表现欢乐、愉快的气氛。

五、明亮、爽朗

Docusaurus Plushie

这个图片给人明亮、爽朗的感受,提取出的色彩是蓝色和橙色的互补色方案,蓝色由一组纯度、明度由浅到深的色彩组成,搭配纯度、明度都稍低一些的橙色和与橙色接近的红色。补色的色彩方案由于两种互补颜色的冲撞,对比单一色相的色彩方案要显得更加有活力。

六、自然、质朴

Docusaurus Plushie

图片给人自然、质朴的感受,提取出的色彩方案是一组范围从黄色到绿色的近似色,黄色纯度偏低,绿色纯度偏高,因此绿色要更显眼一些。由于色相上的接近,这组色彩方案感觉平稳紧凑,反之色相上越跳跃,会加强冲突分离。

七、安静、神秘

Docusaurus Plushie

即将坠入黑夜的湖面景色透露出安静、神秘的气氛。一组不同明度的紫色、一组不同明度的红色加上一个浓浓的黑色构成了这幅图片的配色方案,值得注意的是,无论是哪种色彩,在自然界中很少有100%纯度的,就像这张图片一样,色彩的纯度都在中间甚至偏低一点的范围内,这也正是为什么过高纯度的色彩我们会觉得不舒服的原因。

八、平稳、柔和

Docusaurus Plushie

此插画的色彩方案以白色为背景色,采用了黄色和绿色的近似色搭配,色彩饱和度偏低,整体上给人平稳、柔和的感受。

九、忧郁、复古

Docusaurus Plushie

偏橙的红色和偏黄的绿色的配色方案,由于色彩的饱和度偏低,好似褪色的感觉,绿色的明度较低,感觉比较阴郁,整体上画面体现出一种忧郁和复古的味道。

十、清新、富有生机

Docusaurus Plushie

不同明度的黄绿色组成的一组色彩,属于同一色相的配色方案,给人清新、富有生机的心理感受。

制作开发APP点餐列表

· 阅读需 2 分钟
Web developer & UI designer

问题

使用 SwiftUI 制作开发如下图的点餐列表。

Docusaurus Plushie

思路

使用 SwiftUI 中 TextField、Stepper、Picker 控件设计界面,结合自定义类数据将数据传入控件,完成开发。

解答(XCode11.4)

import SwiftUI

//ObservableObject使得Order成为被监听的对象

class Order : ObservableObject{
//在添加ObservableObject协议的基础上,要改变值的变量必须加@Published
let types : Array = ["香草","巧克力","芒果","草莓"]
var type : Int = 0
//@Published和@State的作用一样,当变量的值改变,视图中也会同步改变
@Published var number : Int = 0
@Published var text : String = "Name"
}

struct ContentView: View {
//在结构体内容声明一个变量的类型为Order类,这样就可以用到外部的自定义数据类型
@ObservedObject var order = Order()
var body: some View{
NavigationView{
Form{
TextField("name", text: $order.text)
//Stepper是一个函数,其中的参数value必须要绑定一个值,rang给定一个范围.,访问变量值的时候不用加$,但是绑定,也就是改变的时候要加$,无论加不加$,它们的值都是一个值,所以这里前面加,后面不加。
Stepper("数量:\(order.number)", value: $order.number, in: 010)
//selection表示已经选择的口味,
Picker("请选择口味", selection: $order.type){
// ForEach部分表示选择的范围,这其中的order.types只是将值传进去,而不会变化,因此不需要加$符号,从这里开始,是点击进入之后的内容
ForEach(0..<order.types.count){i in
Text(self.order.types[i])
}
}
}
.navigationBarTitle("CupcakeCorner")
}
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

如何在SwiftUI创建选项卡栏

· 阅读需 2 分钟
Web developer & UI designer

在SwiftUI中创建Tab Bar非常简单——以下是如何来做。

选项卡栏(在UIKit中称为UITabBars)非常适合为用户提供在不同视图之间快速切换的能力。以下是如何在你的SwiftUI应用程序中创建选项卡栏。

第一步:将包含子视图的整个视图封装到TabView中,这样会自动为我们创建一个具有完整功能的选项卡条。

第二步:将子视图放入到Tab View中。这将自动为TabBar中的每个子视图创建一个“槽”。

第三步:通过添加.tabItem修饰符为每个子视图创建一个Tab选项。你可以为每个选项卡选择任何图标和标签,SwiftUI会知道每个对象应该拥有哪个索引,并根据当前的选择更新状态!然后,您可以使用状态值,就像是我们对显示选定颜色的文本所做的操作一样。

struct ContentView: View {
var body: some View {
//1. 创建一个TabView
TabView {
//2. 将子视图放入TabView中
Text("Home View")
//3. 为每一个子视图创建一个tab bar
.tabItem {
Image(systemName: "house")
Text("Home")
}
Text("Settings View")
.tabItem {
Image(systemName: "gear")
Text("Settings")
}
}
}
}

在Xcode中创建单一待办事项视图

· 阅读需 1 分钟
Web developer & UI designer

问题

创建一个如下图的待办事项视图。

Docusaurus Plushie

思路

使用 SwiftUI 中的 HStack 和 VStack 来实现此视图,需要对扩张性控件和收缩性控件熟练把握。

解答

HStack{
Button(action: {})
{
//左边的部分,包括蓝边、项目标题及时间
HStack{
//蓝边
VStack{
Rectangle()
.fill(Color.blue)
//frame就是元素的大小
.frame(width: 8,height: 74)
}
//项目标题及时间
VStack{
//项目标题
HStack{
Text("看话剧")
.font(.headline)
//把标题挤到左边
Spacer()
}
//时间
HStack{
Image(systemName: "clock")
.resizable()
.frame(width: 12,height: 12)
Text("1月18日")
.font(.subheadline)
//不设置frame,无限大,把时间挤到左边
Spacer()
}
.foregroundColor(Color.gray)
}
//padding是元素和frame之间的边距
.padding(.leading,5)
}
}
Button(action: {})
{
VStack{
Image(systemName: "square")
.resizable()
.frame(width: 24, height: 24)
.foregroundColor(Color.gray)
}
.padding()
}
}
.background(Color("SingleItemBg"))
.cornerRadius(10)
//元素内边距
.padding(20)

SwiftUI—如何构建一个图像

· 阅读需 1 分钟
Web developer & UI designer

Docusaurus Plushie

想知道如何在 SwiftUI 中正确地构建图像吗?这就是你要的!

第一步:将.resizable 修饰符应用于图像对象上,此修饰符将调整图像的大小和 frame 到合适的大小。

第二步::当你改变图像的大小时,通常需要保持原来的尺寸。为此,添加.aspectRatio 修饰符。你可以选择.fill 内容模式,让整个 frame 被图像填满,而.fit 内容模式确保整个图像在 frame 内。

第三步:现在您可以声明图像的 frame 修饰符。

第四步:增加.clipped 修饰符,以确保你的图像超过 frame 的任何部分被切断。

import SwiftUI
struct ContentView : View {
var body: some View {
Image("dog")
//Enable size editing for the Image
.resizable()
//Define which method to use to keep the original dimensions when resizing
.aspectRatio(contentMode: .fill)
//Declare the frame for your image
.frame(width: 380, height: 280)
//Cut out the exceeding parts of the image
.clipped()
}
}

成为IOS开发人员的7个步骤

· 阅读需 3 分钟
Web developer & UI designer

第1步:买一个Mac电脑并下载Xcode

Docusaurus Plushie

首先,为自己准备一个MacOS系统(万一你还没有)。您的设备至少应该能够运行MacOS Catalina。然后下载来自AppStore的Xcode,它是免费的。Xcode是开发iOS应用程序最关键的软件!

第2步:了解Xcode的基本知识

Docusaurus Plushie

下载Xcode之后,是时候了解它的基本结构和概念了。检查本教程,以了解开始使用Xcode所需的所有知识。我们将建造我们的第一个迷你“你好世界”,帮助您决定使用UIKit和SwiftUI(iOS开发的两种不同方法),并学习Xcode的基本界面。

第3步:学习SWIFT编程的基础知识

Docusaurus Plushie

在你了解了Xcode的基本知识之后,现在是学习Swift的时候了。Swift是最常用的编程语言,尤其对于初学者来说。我们已经为此创建了一个免费的电子书,您可以下载免费的!

第4步:通过教程构建Apps

Docusaurus Plushie

开始用教程构建基本的应用程序,教程非常多!我们创建了一系列的SwiftUI教程让你开始从头学起!我们建议你先从本教程开始。之后,您可以继续学习这些教程。

虽然我们免费教程几乎涵盖了所有学习iOS开发需要了解的东西,你也许还想看看我们的全面掌握SwiftUI手册。在这本书中,我们将手把手的教你关于使用SwiftUI开发应用程序所需要知道的一切。

第5步:加深对IOS SDK和框架的了解

Docusaurus Plushie

一旦你完成了一些教程,在你感兴趣的话题上加深你的知识,你想学更多。在IOS开发中,有太多的框架需要掌握。例如,如果你对增强现实应用感兴趣,可以学习谷歌“ARKit教程”。你有很多选择!

第6步:加深你的Swift知识

Docusaurus Plushie

你对iOS应用程序开发了解的越多,就需要更多的Swift技能和概念。如果你不了解一些更高级的Swift概念,可以在官方网站上查一查Swift语言文档(这是一个非常好的来源)或在某个地方搜索或者提问,例如通过StackOverflow或给我们写条消息!

第7步:开发自己的定制应用程序

要真正成为iOS开发人员,关键是要尽快开始开发自己的定制应用程序。这会极大地提高了你的学习曲线和编程技能。