תכנון הנדסי וניתוח
יישום תקשורת API נינוחה ב Ios עם Alamofire
Table of Contents
להתחיל עם Alamofire
(הופנה מהדף iOS שלך, אתה יכול להוסיף את הספריה באמצעות Swift Pack Manager, CocoaPods, או Carthage. Swift Pack Manager הוא הגישה המומלצת כפי שהוא בנוי ל- Xcode.להוסיף את חבילת Alamofire על ידי naviging to FLT:0FileFLT:1 ;0.
import Alamofire
(הופנה מהדף אלמופייר:4 ; lias מספק נקודת כניסה נוחה לכל פעולות HTTP נפוצות.תחת הישות, זה משתמש ב-Apple'sFLT:5 אבל מופשט הרחק מ-Verplate כמו ניהול תור, פרמטר ואימות תגובה.זה מאפשר לך להתמקד בלוגיקה עסקית ולא בצנרת מידע נוסף על שכבת הרשת הבסיסית, מתייחס לתיעוד של LTSsion:1.
ביצוע דרישות GET
איסוף נתונים מנקודת מוצא RESTful הוא הפעולה הנפוצה ביותר. Alamofire עושה בקשות GET לזיכיון וקריאה.הדוגמה הבאה מחזירה רשימה של משתמשים מ- API היפותטי:
AF.request("https://api.example.com/users")
.validate()
.responseDecodable(of: [User].self) { response in
switch response.result {
case .success(let users):
print("Fetched \(users.count) users")
case .failure(let error):
print("Request failed with error: \(error)")
}
}
(ה) עיין בפרוטוקול (FLT 7) אשר מנף את פרוטוקול סוויפט (FLT:8 ), כדי לפצח באופן אוטומטי את JSON לתוך אובייקטים מודל. Define aFLT:9 , אשר תואם את FLT:10 (או קונסולת:11).
הוספת Query Parameters ו Headers
REST APIs רבים דורשים פרמטרים של שאילתה או ראשי HTTP מותאמים אישית. Alamofire מקבל פרמטרים כמילון ומטפל באופן אוטומטי עבור בקשות GET (פרמטרים מותאמים ל-URL).
let parameters: Parameters = ["page": 1, "limit": 20]
let headers: HTTPHeaders = [
"Authorization": "Bearer YOUR_TOKEN",
"Accept": "application/json"
]
AF.request("https://api.example.com/users",
parameters: parameters,
headers: headers)
.validate()
.responseDecodable(of: [User].self) { response in
// handle response
}
אלמופייר מקודמת באופן אוטומטי את הפרמטרים ומקשר אותם ל-URL של הבקשה.עבור קידוד מותאם אישית, ניתן לציין מקרה מפורש של FLT:14, כגון: 15.
תגובה
שיטת ה-FLT:16 בודקת באופן אוטומטי את קודי הסטטוס HTTP בטווח 200-299 ודוחה תשובות עם סוג תוכן לא-מקובל.You יכול גם להוסיף קריטריונים אימות מותאם אישית.
.validate(statusCode: [200, 201])
תקלות אימות דווחו כטעויות בטיפול התגובה, ומאפשרות לך ליישם טיפול שגיאות עקביות לאורך כל היישום שלך.
שלח מידע POST
יצירת או עדכון משאבים בדרך כלל דורש בקשה POST עם גוף בקשה. Alamofire תומך באסטרטגיות מרובות של אופטימיזציה, עם ההרחבה 18 להיות הנפוץ ביותר עבור REST APIs.הדוגמה הבאה שולח אובייקט משתמש חדש לשרת:
let newUser: [String: Any] = [
"name": "Jane Doe",
"email": "[email protected]"
]
AF.request("https://api.example.com/users",
method: .post,
parameters: newUser,
encoding: JSONEncoding.default)
.validate()
.responseDecodable(of: User.self) { response in
switch response.result {
case .success(let createdUser):
print("User created: \(createdUser)")
case .failure(let error):
print("Error creating user: \(error)")
}
}
אם ה- API צופה שנתוני טופס קודקוד של כתובת ה-URL (לדוגמה, עבור החלפת אות), השתמש ב-URL:20 במקום זאת.עבור העלאת קבצים או נתונים מעורבים, Alamofire מספק את ה-FLT:21 אשר בונה בקשה רב-חלקית.
AF.upload(multipartFormData: { multipartFormData in
multipartFormData.append(Data("Jane Doe".utf8), withName: "name")
multipartFormData.append(imageData, withName: "avatar", fileName: "avatar.jpg", mimeType: "image/jpeg")
}, to: "https://api.example.com/users")
.validate()
.responseDecodable(of: User.self) { response in
// handle response
}
עבודה עם שיטות HTTP אחרות
ממשקי API של RESTful דורשים לעתים קרובות PUT (עדכון מלא), PATCH (עדכון חלקי), ו- DELETE (removal) מבצעים את אלה עם אותה שיטה FLT:23; פשוט לשנות את פרמטר פרמטר פרמטר פרמטר ®FLT:24.
PUT ו-PATCH
כדי לעדכן משאב קיים, השתמש ב-FLT:25 או FLT:26.
let updatedFields: [String: Any] = ["name": "Jane Smith"]
AF.request("https://api.example.com/users/123",
method: .patch,
parameters: updatedFields,
encoding: JSONEncoding.default)
.validate()
.responseDecodable(of: User.self) { response in
// handle updated user
}
DELETE
קביעת משאב בדרך כלל אינה דורשת גוף בקשה.התגובה עשויה להיות ריקה או להחזיר הודעת אישור:
AF.request("https://api.example.com/users/123",
method: .delete)
.validate()
.response { response in
if let error = response.error {
print("Delete failed: \(error)")
} else {
print("User deleted successfully")
}
}
תמיד לבדוק את תיעוד ה- API עבור קודים צפויים (למשל, 204 ללא תוכן).
מעקב שגיאות מתקדם ורשת
טיפול שגיאות Robust הוא קריטי עבור חוויית משתמש חלקה. Alamofire מדווח שגיאות דרך הסוג LT:29, אשר נבדל בין שגיאות רשת (זמן, ללא קשר), שגיאות שרת (קוד מצב גרוע), וכישלונות סידוריזציה (לא חוקי JSON).
switch response.result {
case .success(let value):
// handle success
case .failure(let error):
if let afError = error.asAFError {
switch afError {
case .sessionTaskFailed(let sessionError):
print("Network issue: \(sessionError.localizedDescription)")
case .responseValidationFailed(let reason):
print("Validation failed: \(reason)")
default:
print("Other Alamofire error: \(afError.localizedDescription)")
}
}
}
רשת Reachability
לפני ביצוע בקשות, ייתכן שתרצה לבדוק זמינות רשת. Alamofire's לפקח על שינויים בקישוריות.התחל לעקוב מוקדם במחזור חיי האפליקציה שלך:
let reachabilityManager = NetworkReachabilityManager()
reachabilityManager?.startListening { status in
switch status {
case .notReachable:
print("Network is not reachable")
case .reachable(.cellular):
print("Connected via cellular")
case .reachable(.ethernetOrWiFi):
print("Connected via WiFi")
case .unknown:
print("Unknown status")
}
}
השתמש בכך כדי ליידע את המשתמש או לדחות בקשות.עבור דפוסים מתקדמים יותר, לשקול שילוב של יכולת הגעה עם מנגנון retry, כגון retrying בקשות כושלות בעת שחזור קישוריות.
Best Practices for Production-Ready Networking
לאחר דפוסים מבוססים ישמור על שכבת הרשת שלך, בטוחה, וביצוע.
1. אימוץ מודלים ניתנים להחלפה
(הופנה מהדף ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇
2. בטוח יותר Authentication וניהול Token Management
לעולם אל תקשה על מקשי API או אסימונים.לשמור ערכים רגישים ב- Keychain וצרף אותם לבקשות באמצעות ה-FLT:37 ראשי תיבות של OAuth, ליישם את יירוט הרענון של אלמופייר, פרוטוקול אלמופייר מאפשר לך לנסות מחדש בקשות לאחר קבלת דגימת טוקן חדשה.
class AuthInterceptor: RequestInterceptor {
func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
var request = urlRequest
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
completion(.success(request))
}
func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
// Check if error is 401, refresh token, then retry
completion(.retryWithDelay(1.0))
}
}
מטבע עם Async /await
אלמופייר 5 תומך באופן מלא במודל הקונפלי של סוויפט. השתמש בגרסאות של שיטות בקשה כדי לכתוב קוד נקי, ליניארי:
do {
let users = try await AF.request("https://api.example.com/users")
.serializingDecodable([User].self)
.value
print("Users: \(users)")
} catch {
print("Error: \(error)")
}
לשלב את זה עם קונפדרציה מובנה (קבוצות מיקוד, שחקנים) כדי לנהל מספר בקשות ולהימנע מגיהנום.
4.התחילה Caching
כדי להפחית את שיחות הרשת ולשפר את התמיכה הלא מקוונת, להגדיר מדיניות גירוד (אלמואש מכבדת את ה-FLT:42 (למשל, FLT:43) ניתן גם להשתמש בתכונה אישית של FLT:44 עם יכולת דיסק מתאימה:
let cache = URLCache(memoryCapacity: 10 * 1024 * 1024,
diskCapacity: 50 * 1024 * 1024,
diskPath: "networking_cache")
let session = Session(configuration: URLSessionConfiguration.default)
session.sessionConfiguration.urlCache = cache
בדוק את שכבת הרשת שלך
כתוב בדיקות יחידה עבור לקוחות ה- API שלך באמצעות נתונים לעגים.אלמופייר יכול להיות מוזרק עם פרוטוקול לעג אשר מחזיר תגובות מוגדרות מראש.חשב באמצעות ספריות כמו FLT:47 או את הפשטות המובנה (FLT:48 ). בדיקות מבטיח את הטיפול בשגיאות שלך ואת הלוגיקה parsing נכונים ללא נקודות קצה אמיתיות.
השתמש במנהל רשתות מרכזי
צור יחידה (FLT:49) אשר מגדירה מקרה אחד של FLT:50 עם כתובת בסיס, ראשי, ירוטים, ו- cache משותף.זה מונע שכפול והופך את זה קל להחליף מדיניות או ללעג את השכבה כולה.
class APIClient {
static let shared = APIClient()
private let session: Session
private init() {
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 30
config.urlCache = URLCache.shared
session = Session(configuration: config, interceptor: AuthInterceptor())
}
func fetchUsers() async throws -> [User] {
return try await session.request("\(baseURL)/users")
.serializingDecodable([User].self)
.value
}
}
לשם הבנה מקיפה של תבניות רשת, התייחס ל-FLT:0Alamofire Advanced Usage Documentssph:1 .
על ידי ביצוע ההנחיות האלה ומינוף ה- API של אלמופייר, אתה יכול לבנות שכבת רשת שהיא גם חזקה וקלה לשמור.הספריה מפשטת הרבה מההיבטים המזעזעים של טעינה תוך מתן לך שליטה מלאה כאשר אתה צריך אותה.