Swift には他の言語にはない独自の構造やメソッドが多数あるため、Swift を初めて使用する開発者の多くはそれを活用できません。
1. where 条件を使用した for ループ
view.subviews
さて、途中でUIButton
何とも言えないことをしたいのですが、for ループを使用してそれを横断するにはどうすればよいでしょうか?
以下の記述方法のうち、後者の 2 つの記述方法がより推奨されます。
❌
for subView in view.subviews {
if let button = subView as? UIButton {
//不可描述的事情
}
}
✅
for case let button as UIButton in view.subviews {
//不可描述的事情
}
✅
for button in view.subviews where button is UIButton {
//不可描述的事情
}
2. 列挙型 enumerated()
Swift で for ループを実行して添え字の値を取得するには、一般的な書き方は または定义局部变量记录下标值
です遍历 0..<view.subviews.count
。実際には、次のようなより便利な書き方があります。これによりenumerated()
、添え字の値と走査された要素を一度に取得できます。
-
❌ 最初のタイプは、追加のローカル変数を定義する必要があり、エラーが発生しやすいため、絶対にお勧めできません。
-
✅ 2 番目のタイプは、添字値のみを使用する必要がある場合に使用できますが、添字値に対応する要素を使用したい場合は、再度取得する必要があり、手間がかかります
-
✅ 3 番目のタイプはより完璧で、添え字の値と要素を一度に取得できますが、必要ない場合はいずれかを使用できます。
_
❌
var index: Int = 0
for subView in view.subviews {
//不可描述的事情
index += 1
}
✅
for index in 0..<view.subviews.count {
let subView = view.subviews[index]
//不可描述的事情
}
✅
//index 和 subView 在循环体中都能使用到
for (index, subView) in view.subviews.enumerated() {
//不可描述的事情
}
//只用到 index
for (index, _) in view.subviews.enumerated() {
//不可描述的事情
}
//只用到 subView
for (_, subView) in view.subviews.enumerated() {
//不可描述的事情
}
3、最初(ここで: )
filter
これは、Swift のいくつかの高度な関数の 1 つであり、コレクション内の要素をフィルタリングする場合に非常に便利ですが、条件を満たすコレクション内の最初の要素を取得する場合など、場合によっては、より良い選択肢があることもあります。first(where: )
let article1 = ArticleModel(title: "11", content: "内容1", articleID: "11111", comments: [])
let article2 = ArticleModel(title: "11", content: "内容2", articleID: "22222", comments: [])
let article3 = ArticleModel(title: "33", content: "内容3", articleID: "3333", comments: [])
let articles = [article1, article2, article3]
❌
if let article = articles.filter({ $0.articleID == "11111" }).first {
print("\(article.title)-\(article.content)-\(article.articleID)")
}
✅
if let article = articles.first(where: {$0.articleID == "11111"}) {
print("\(article.title)-\(article.content)-\(article.articleID)") //11-内容1-11111
}
4、含む(ここで: )
これは上記とほぼ同じでfirst(where: )
、例えば記事リストにarticleID 11111の記事が含まれているかどうかを判定する場合は以下のようになります。
❌
if !articles.filter({ $0.articleID == "11111" }).isEmpty {
//不可描述的事情
}
✅
if articles.contains(where: { $0.articleID == "11111"}) {
//不可描述的事情
}
5、それぞれ
ループ本体のロジックが比較的単純な場合、forEach は for...in... よりも簡潔であることがよくあります。
func removeArticleBy(ID: String) {
//删库跑路
}
❌
for article in articles {
removeArticleBy(ID: $0.articleID)
}
✅
articles.forEach { removeArticleBy(ID: $0.articleID) }
6. 計算されたプロパティとメソッド
計算されたプロパティ自体はデータを保存せず、get で計算された値を返し、set で他のプロパティの値を設定することがわかっているため、メソッドに似ていますが、メソッドよりも簡潔です。次の例を見てみましょう。
❌
class YourManager {
static func shared() -> YourManager {
//不可描述的事情
}
}
let manager = YourManager.shared()
❌
extension Date {
func formattedString() -> String {
//不可描述的事情
}
}
let string = Date().formattedString()
✅
class YourManager {
static var shared: YourManager {
//不可描述的事情
}
}
let manager = YourManager.shared
✅
extension Date {
var formattedString: String {
//不可描述的事情
}
}
let string = Date().formattedString
复制代码
7. プロトコルとサブクラス化
継承の代わりにプロトコルを使用してみてください。クラスは同時に複数のプロトコルに準拠できるため、プロトコルを使用するとコードがより柔軟になります。
また、構造体と列挙型はサブクラス化できませんが、プロトコルに準拠することができるため、プロトコルの利点がさらに大きくなります。
8. Struct のデフォルトの初期化子を維持する
ご存知のとおり、Swift の Struct はメンバー初期化子を備えた値型です。
Struct のイニシャライザをカスタマイズする必要があり、デフォルトのイニシャライザを保持したいのに、カスタマイズ後にデフォルトのイニシャライザが消えてしまう、このような状況に遭遇したことがあるかどうかはわかりません。
まずデフォルトのイニシャライザを見てみましょう。
カスタム イニシャライザを作成すると、デフォルトのイニシャライザが表示されなくなります。
カスタムとデフォルトを同時に維持したい場合は、拡張メソッドを使用する必要があります。
構造体とクラス
可能な限り、クラスの代わりに構造体を使用してください。Struct は、マルチスレッド環境でより安全かつ高速です。
これらの主な違いは、Struct は値型であるのに対し、Classe は参照型であることです。つまり、Struct の各インスタンスは独自の一意のコピーを持ち、Class の各インスタンスはデータの単一のコピーへの参照を持ちます。
このリンクは、Struct と Class のどちらを選択するかを説明した Apple の公式ドキュメントです。 構造体とクラスの選択 | Apple 開発者ドキュメント