شروع کار با Alamofire

برای شروع ادغام Alamofire به پروژه iOS، می توانید کتابخانه را با استفاده از Swift Package Manager، CocoaPods یا Swift Package Manager به عنوان یک رویکرد توصیه شده به عنوان یک بسته اتصال به فایل AlLT اضافه کنید: اضافه کردن بسته AlLT و پیکربندی فایل (F:3).

import Alamofire

Alamofire (FLT:4) alias یک نقطه ورود مناسب برای تمام عملیات HTTP رایج را فراهم می کند. تحت کاپوت، آن را با استفاده از اپل اما Abstracts Awayplate مانند مدیریت صف، رمزگذاری پارامتر و اعتبار پاسخ، این اجازه می دهد تا شما را به تمرکز بر منطق کسب و کار به جای لوله کشی.

اجرای درخواست های GET

انتقال داده ها از نقطه انتهایی RESTful رایج ترین عملیات است. Alamofire درخواست های مختصر و قابل خواندن را می سازد. مثال زیر لیستی از کاربران را از یک 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 را به اشیاء مدل سازی تجزیه می کند، تعریف یک ساختار که مطابق با (یا [FLT 11] است.

اضافه کردن پارامترهای Query و Headers

بسیاری از API های REST نیاز به پارامترهای پرس و جو یا هدرهای 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
 }

Alamofire به طور خودکار پارامترهای را کد گذاری می کند و آنها را به URL درخواست متصل می کند.برای رمزگذاری سفارشی، می توانید یک نمونه صریح (FLT:14) مانند را مشخص کنید.

پاسخ اعتبارسنجی

روش [FLT16] به طور خودکار برای کدهای وضعیت HTTP در محدوده 200 تا 299 بررسی می شود و پاسخ ها را با یک نوع محتوای غیر قابل قبول رد می کند.شما همچنین می توانید معیارهای اعتبار سنجی سفارشی را اضافه کنید.

.validate(statusCode: [200, 201])

خرابی های معتبر به عنوان خطا در پاسخ داور گزارش شده است، به شما اجازه می دهد تا اجرای خطای ثابت در سراسر برنامه خود را.

ارسال داده های POST

ایجاد یا به روز رسانی منابع به طور معمول نیاز به درخواست POST با یک درخواست بدن دارد. Alamofire از استراتژی های رمزگذاری چندگانه پشتیبانی می کند، با رایج ترین برای 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 (به عنوان مثال برای تبادل توکن OAuth)، از [FLT 20] استفاده کنید، به جای بارگذاری فایل یا داده های مخلوط، Alfireamo (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

RESTful API ها اغلب نیاز به PUT (به روز رسانی کامل)، PATCH (به روز رسانی جزئی)، و DELETE (removal) عملیات است. Alamofire این را با همان روش مدیریت می کند؛ به سادگی تغییر (FLT:24 پارامتر.

PUT و PATCH

برای به روز رسانی یک منبع موجود، از [FLT 25] یا [FLT26] استفاده کنید.

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 محتوای بدون محتوا).

مدیریت خطای پیشرفته و نظارت شبکه

دستکاری خطای قوی برای یک تجربه کاربری یکپارچه حیاتی است. Alamofire خطاهایی را از طریق نوع [FLT 29] گزارش می دهد که بین خطاهای شبکه (timeout، بدون اتصال)، خطاهای سرور (کد وضعیت بد)، و شکست های سریال سازی (Invalid 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)")
 }
 }
}

شبکه دسترسی پذیری

قبل از درخواست، ممکن است بخواهید دسترسی به شبکه را بررسی کنید.Alamofire's [FLT 31] تغییرات اتصال را نظارت می کند.

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 مانند درخواست های شکست خورده در هنگام بازسازی اتصال.

بهترین روش برای شبکه های تولید-Ready

پس از الگوهای تثبیت شده لایه شبکه شما را حفظ، امن و اجرا کننده نگه می دارد.

۱- اتخاذ مدل های قابل اعتماد

همیشه انواع Swift را تعریف کنید که مطابق با یا برای پاسخ دادن به تجزیه و تحلیل، این حذف دستکاری JSON دستی و کاهش اشکالات استفاده از و یا سطح پایین تر [FLT36] اگر شما نیاز به محتوای پویا.

۲- اعتبار ایمن تر و مدیریت توکن

هرگز هاردکد کلیدها یا توکن ها. ذخیره مقادیر حساس در زنجیره کلید و اتصال آنها به درخواست از طریق هدر برای OAuth جریان، پیاده سازی یک ردیاب تازه توکن (FLT 38 پروتکل اجازه می دهد تا شما به طور خودکار درخواست ها را پس از به دست آوردن یک اسکلت نمونه جدید امتحان کنید:

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

Alamofire 5 به طور کامل از مدل ارزهای Swift پشتیبانی می کند.از نسخه های درخواست برای نوشتن تمیزتر و خطی استفاده کنید:

do {
 let users = try await AF.request("https://api.example.com/users")
 .serializingDecodable([User].self)
 .value
 print("Users: \(users)")
} catch {
 print("Error: \(error)")
}

این را با هم ارزی ساختار یافته (گروه های وظیفه ای، بازیگران) ترکیب کنید تا درخواست های متعدد را مدیریت کرده و از جهنم تماس بگیرید.

۴- پیاده سازی Caching

برای کاهش تماس های شبکه و بهبود حمایت آفلاین، سیاست های Caching را پیکربندی کنید. Alamofire به (به عنوان مثال، ) نیز می توانید از یک سفارشی (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:46) می توان با یک پروتکل مسخره تزریق کرد که پاسخ های پیش تعریف شده را باز می گرداند و از کتابخانه هایی مانند (FLT:47) یا Abstractin ساخته شده (FLT:48) استفاده می کنند. تست خطا و منطق تجزیه و تحلیل شما بدون ضربه زدن به نقاط پایانی واقعی صحیح است.

۶- استفاده از یک مدیر شبکه مرکزی

یک کلاس واحد (FLT 49) ایجاد کنید که یک نمونه را با URL پایه، هدر، رهگیرها و یک کش مشترک پیکربندی می کند، این مانع تکرار می شود و به سادگی می تواند سیاست ها را مبادله کند یا کل لایه را به تصویر بکشد:

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
 }
}

برای درک جامع از الگوهای شبکه، به Alamofire Advanced Use document مراجعه کنید، علاوه بر این، ]REST API آموزش در Restfulapi.net ارائه می دهد بینش ارزشمند در طراحی API قوی.

با پیروی از این دستورالعمل ها و استفاده از API بیانی آلامو آتش، می توانید یک لایه شبکه ایجاد کنید که هم قدرتمند و هم آسان برای حفظ است. کتابخانه بسیاری از جنبه های خسته کننده بارگذاری URL را دور می کند در حالی که به شما کنترل کامل زمانی که شما نیاز دارید می دهد.