开发者社区> 文如秋雨> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

8个SwiftUI的小技巧让隔壁同事两眼放光,直呼太卷了

简介: 在日常的SwiftUI开发过程中,常常会出现一些“小BUG”让我们措手不及、头顶发凉。这些问题可能是由于我们自己不熟悉SwiftUI语法导致的,也有是SwiftUI本身自带的缺陷,毕竟是一个新兴语言。 那么本章就介绍一些SwiftUI开发的小技巧,帮助我们避避那些让我们头秃的坑。
+关注继续查看

1、如何在List列表视图去掉分割线LineSeparator?

SwiftUI中的List可以说是UIKit中TableView的进化版本,在UIKit中我们使用separatorColor修饰符将分割线的样式改为无。示例:

tableView.separatorColor = .clear
复制代码

SwiftUI中使用的方法类似,SwiftUI中的List的底层使用的是UITableView,我们可以调用AppearanceAPI来实现去掉分割线样式。示例:

UITableView.appearance().separatorColor = .clear
复制代码

image.png

但是,使用这种方式会导致App中所有的List,包含其他页面的的List也会自动去掉分割线,这是因为UITableViewList的底层,我们的修饰符是作用在UITableView上的。

往后我们要在其他页面,比如设置页面,要恢复分割线,我们就需要赋予分割线的样式。示例:

UITableView.appearance().separatorColor = .systemGray4
复制代码

image.png

2、如何在List列表视图隐藏箭头?

UIKit中,我们使用accessoryType修饰符来禁用disclosure指示器,也就是右侧的箭头。示例:

cell.accessoryType = .none
复制代码

SwiftUI中,非常遗憾的是,Apple没有提供专门的API来设置隐藏disclosure指示器,这会有点麻烦。

我们建立一个List列表来看看,当我们使用NavigationLink跳转到DetailView详情页时,系统就会自动展示右侧的箭头,示例:

image.png

那么我们试试自己来实现隐藏disclosure指示器。

struct ContentView: View {
    var body: some View {
        NavigationView {
            List {
                ForEach(1 ... 4, id: \.self) { index in
                    ZStack(alignment: .leading) {
                        NavigationLink(
                            destination: DetailView()) {
                        }
                        .opacity(0)
                        Text("第 \(index)页")
                    }
                }
            }.navigationTitle("列表")
        }
    }
}
复制代码

image.png

上述代码中,我们使用ZStack层叠视图将整个NavigationLink的视图包裹起来,然后使用opacity修饰符把disclosure指示器隐藏。

看起来不错!

3、如何修改整个视图的背景颜色?

List列表中,由于我们使用SwiftUI自带的列表组件,它会默认给整个视图填充一个背景颜色以凸显列表,这时我们追求页面整体性时,需要给List视图加一个背景颜色。

UIKit中,我们可以直接给视图加背景颜色,示例:

view.backgroundColor = UIColor.colorF6F7FB()
复制代码

首先,我们要去掉原有的List列表颜色,示例:

init() {
    UITableView.appearance().backgroundColor = .clear
}
复制代码

然后在业务代码中,我们可以使用ZStack层叠视图和Color的方式设置List的背景颜色,示例:

Color(red: 132.0 / 255.0, green: 161.0 / 255.0, blue: 255.0 / 255.0).edgesIgnoringSafeArea(.all)
复制代码

image.png

不错不错!

4、如何通过网络请求显示一张网络图片?

在常用的设置页面或者我的页面,会使用到用户头像等作为用户登录示例,除了使用第三方网络请求框架外,我们也可以使用SwiftUI自带的网络图片组件,示例:

AsyncImage(url: URL(string: imageURL))
    .aspectRatio(contentMode: .fit)
    .frame(minWidth: 120, maxWidth: 120, minHeight: 120, maxHeight: 120)
    .cornerRadius(8)
复制代码

image.png

上述代码中,我们只需要定义一个图片的网络地址,就可以使用AsyncImage组件呈现一张图片出来,并且AsyncImageImage一样,可以使用修饰符修改大小的参数。

5、如何绘制带有边角的图形?

SwiftUI开发过程中,我们常常会看到一些带有部分圆角的形状,这又是如何实现的呢?

image.png

我们可以通过图片的方式展示,也可以自己根据形状绘制,下面我们尝试使用Shape形状来实现这个效果。示例:

struct CShape: Shape {
    func path(in rect: CGRect) -> Path {
        let path = UIBezierPath(
            roundedRect: rect,
            byRoundingCorners: [.topRight, .bottomLeft],
            cornerRadii: CGSize(width: 55, height: 55)
        )
        return Path(path.cgPath)
    }
}
复制代码

上述代码中,我们绘制了一个形状CShape结构体,在结构体中我们的定义了一个方法path,它返回一个Path路径。

我们使用贝塞尔曲线UIBezierPath进行绘制,在右上topRight和左下bottomLeft绘制曲率。

接下来我们在视图中使用,示例:

struct CShapeView: View {
    var body: some View {
       Rectangle()
            .fill(LinearGradient(gradient: Gradient(colors: [Color.blue, Color.green]), startPoint: .leading, endPoint: .trailing))
            .frame(width: 100, height: 100)
            .clipShape(CShape())
    }
}
复制代码

image.png

上述代码中,我们绘制了一个矩形Rectangle,给它填充了一个蓝色过渡到绿色的渐变色,然后设置了大小为100*100

最后我们使用clipShape修饰符切割曲线,切割方式为上面设置好的CShape

这样,我们就完成了一个类似叶子效果的带边角的形状。

6、如何绘制虚线边框?

在新版的Xcode中,我们已经不能直接使用border修饰符给按钮加边框了,那我们该如何给按钮加边框线呢?

其实很简单,我们可以使用overlay修饰符在按钮上覆盖一层边框,示例:

Text("文如秋雨")
    .font(.title)
    .foregroundColor(.blue)
    .padding()
    .overlay(
        RoundedRectangle(cornerRadius: 30)
            .stroke(Color(.systemGray5), lineWidth: 2)
    )
复制代码

image.png

上述代码中,我们使用overlay覆盖了一层圆角矩形RoundedRectangle,圆角度数为30,并且使用stroke修饰符给圆角赋予了一个灰色systemGray5,和2的线宽。

这是边框的实现方式,那么虚线边框我们使用的是Capsule容器。示例:

Text("文如秋雨")
    .font(.title)
    .foregroundColor(.blue)
    .padding()
    .overlay(
        Capsule(style: .continuous)
            .stroke(Color.blue, style: StrokeStyle(lineWidth: 2, dash: [10]))
    )
复制代码

image.png

上述代码中,我们覆盖的是Capsule容器,然后将Capsule容器的样式指定为StrokeStyleStrokeStyle样式中线宽为2,线段间距为10

如此,我们便实现了绘制一个虚线边框

7、如何分享文本和图片?

在实际的开发应用中,我们常常会在App中使用分享操作,将某一段文字或者图片分享出去,这是如何实现的呢?

首先我们先实现分享的方法,示例:

struct ShareSheet: UIViewControllerRepresentable {
    var items: [Any]
    func makeUIViewController(context: Context) -> UIActivityViewController {
        let controller = UIActivityViewController(activityItems: items, applicationActivities: nil)
        return controller
    }
    func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {
    }
}
复制代码

上述代码中,我们创建了一个ShareSheet结构体,它遵循UIViewControllerRepresentable协议。

我们声明了一个items变量是随机类型,便于后续我们存储不同类型的内容。然后定义了一个方法makeUIViewController,调用系统的UIActivityViewController视图方法,分享声明好的items内容。

接下来,我们来完成视图部分,示例:

struct ShareLinkView: View {
    let items = ["https://juejin.cn/user/3897092103223517"]
    @State var showingSheet: Bool = false
    var body: some View {
        HStack {
            Image(systemName: "square.and.arrow.up")
            Text("分享")
        }
        .onTapGesture {
            showingSheet.toggle()
        }
        .sheet(isPresented: $showingSheet) {
            ShareSheet(items: items)
        }
    }
}
复制代码

image.png

上述代码中,我们声明了一个常量,存储我们的网站地址,然后使用ImageText创建了一个分享的样式,调用sheet弹窗方法打开弹窗,弹窗的内容为我们声明好的ShareSheet视图,然后将声明好的内容传入进行分享。效果如下:

image.png

8、如何在按钮点击时有震动反馈?

iOS很突出的一点是它的线性马达所带来的反馈体验,让我们在点击屏幕某些操作时能够接收到App提供的反馈信息。

如果我们需要给App的某些操作加入一些震动反馈,该如何实现?

我们可以使用UINotificationFeedbackGenerator来实现震动反馈的效果,示例:

struct Haptics {
    static func hapticSuccess() {
        let generator = UINotificationFeedbackGenerator()
        generator.notificationOccurred(.success)
    }
    static func hapticWarning() {
        let generator = UINotificationFeedbackGenerator()
        generator.notificationOccurred(.warning)
    }
}
复制代码

上述代码中,我们创建了一个结构体Haptics,在Haptics中定义了2个震动反馈效果,一个时成功反馈,一个是失败反馈。

然后我们在实际业务视图中使用它,示例:

struct HapticsView: View {
    var body: some View {
        VStack(spacing:40) {
            Text("成功时的反馈")
                .padding()
                .foregroundColor(.white)
                .background(Color.green)
                .cornerRadius(5)
                .onTapGesture {
                    Haptics.hapticSuccess()
                }
            Text("失败时的反馈")
                .padding()
                .foregroundColor(.white)
                .background(Color.gray)
                .cornerRadius(5)
                .onTapGesture {
                    Haptics.hapticWarning()
                }
        }
    }
}
复制代码

image.png

上述代码中,我们创建了2个按钮,分别赋予了不同的样式,当我们点击按钮时,会调用震动反馈的方法,从而实现让用户有点击的效果。

震动反馈常用在长按或者一些警告业务场景中,可以视情况而使用。

小结

好啦!这就是本章的所有内容,是不是有点眼前一亮呢?

你还知道有哪些SwiftUI小技巧,不妨分享一下。


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
干掉 XML Mapper,新出的 Fluent Mybatis 真香!
干掉 XML Mapper,新出的 Fluent Mybatis 真香!
209 0
启明云端分享:S系列1.54寸串口屏重磅来袭
方案采用1.54寸IPS彩屏,分辨率240×240 ,开发板结构采用最小尺寸多种定位固定方式,支持WIFI,用户可以通过对开发板的扩展接口进行串口通讯、按键、usb摄像头等功能的开发调试,极大缩短用户产品开发周期。
63 0
读写锁分离的循环队列
在很多需要高性能的场合下,锁的设计一直是一个比较关键的问题。无锁队列、读写锁分离的队列在业界以及学术界都已经有很成熟的研究。在网上也有很多资料,但其实有很多实现都是错误的。最近在工作中帮忙追查一个线上问题时,就发现实现一个正确的版本是比较困难的事情。
698 0
读写锁分离的循环队列
在很多需要高性能的场合下,锁的设计一直是一个比较关键的问题。无锁队列、读写锁分离的队列在业界以及学术界都已经有很成熟的研究。在网上也有很多资料,但其实有很多实现都是错误的。最近在工作中帮忙追查一个线上问题时,就发现实现一个正确的版本是比较困难的事情。
817 0
QTQuick控件基础(2)
import QtQuick 2.2import QtQuick.Controls 1.2import QtQuick.Window 2.1ApplicationWindow {    visible: true    width: 640    height: 480    title: qsTr...
877 0
+关注
文如秋雨
一只默默努力变优秀的产品汪......
102
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载