### Create and Execute a GET Request Source: https://context7.com/kanyun-inc/ytknetwork/llms.txt Define a custom request class by subclassing YTKRequest and execute it using completion blocks. ```objectivec // GetUserInfoApi.h #import "YTKRequest.h" @interface GetUserInfoApi : YTKRequest - (instancetype)initWithUserId:(NSString *)userId; @end // GetUserInfoApi.m #import "GetUserInfoApi.h" @implementation GetUserInfoApi { NSString *_userId; } - (instancetype)initWithUserId:(NSString *)userId { self = [super init]; if (self) { _userId = userId; } return self; } - (NSString *)requestUrl { return @"/api/users"; } - (id)requestArgument { return @{ @"id": _userId }; } // Optional: Validate JSON response structure - (id)jsonValidator { return @{ @"nick": [NSString class], @"level": [NSNumber class] }; } @end // Usage in ViewController - (void)fetchUserInfo { GetUserInfoApi *api = [[GetUserInfoApi alloc] initWithUserId:@"12345"]; [api startWithCompletionBlockWithSuccess:^(YTKBaseRequest *request) { NSDictionary *userInfo = request.responseJSONObject; NSLog(@"User: %@, Level: %@", userInfo[@"nick"], userInfo[@"level"]); } failure:^(YTKBaseRequest *request) { NSLog(@"Error: %@", request.error.localizedDescription); }]; } ``` -------------------------------- ### Implement Resumable File Download in Objective-C Source: https://context7.com/kanyun-inc/ytknetwork/llms.txt Override resumableDownloadPath to enable automatic download resumption. Includes an example of tracking download progress. ```objectivec // DownloadFileApi.h #import "YTKRequest.h" @interface DownloadFileApi : YTKRequest - (instancetype)initWithFileId:(NSString *)fileId; @end // DownloadFileApi.m @implementation DownloadFileApi { NSString *_fileId; } - (instancetype)initWithFileId:(NSString *)fileId { self = [super init]; if (self) { _fileId = fileId; } return self; } - (NSString *)requestUrl { return [NSString stringWithFormat:@"/api/files/%@", _fileId]; } // Use CDN for downloads - (BOOL)useCDN { return YES; } // Enable resumable download by specifying save path - (NSString *)resumableDownloadPath { NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]; return [cachePath stringByAppendingPathComponent:_fileId]; } @end // Usage with download progress - (void)downloadFile:(NSString *)fileId { DownloadFileApi *api = [[DownloadFileApi alloc] initWithFileId:fileId]; // Track download progress api.resumableDownloadProgressBlock = ^(NSProgress *progress) { CGFloat percentage = progress.fractionCompleted * 100; NSLog(@"Download progress: %.1f%% (%lld / %lld bytes)", percentage, progress.completedUnitCount, progress.totalUnitCount); }; [api startWithCompletionBlockWithSuccess:^(YTKBaseRequest *request) { NSURL *fileURL = request.responseObject; // Path to downloaded file NSLog(@"File downloaded to: %@", fileURL.path); } failure:^(YTKBaseRequest *request) { NSLog(@"Download failed: %@", request.error); }]; } ``` -------------------------------- ### Get User Info API Implementation Source: https://github.com/kanyun-inc/ytknetwork/blob/master/Docs/BasicGuide_en.md A complete implementation of a GetUserInfoApi that fetches user data, including request URL, arguments, and JSON validation for 'nick' and 'level' fields. ```objectivec // GetUserInfoApi.h #import "YTKRequest.h" @interface GetUserInfoApi : YTKRequest - (id)initWithUserId:(NSString *)userId; @end // GetUserInfoApi.m #import "GetUserInfoApi.h" @implementation GetUserInfoApi { NSString *_userId; } - (id)initWithUserId:(NSString *)userId { self = [super init]; if (self) { _userId = userId; } return self; } - (NSString *)requestUrl { return @"/iphone/users"; } - (id)requestArgument { return @{ @"id": _userId }; } - (id)jsonValidator { return @{ @"nick": [NSString class], @"level": [NSNumber class] }; } @end ``` -------------------------------- ### Implement Multipart File Upload in Objective-C Source: https://context7.com/kanyun-inc/ytknetwork/llms.txt Use constructingBodyBlock to access AFNetworking's multipart form data builder for file uploads. Includes an example of tracking upload progress. ```objectivec // UploadImageApi.h #import "YTKRequest.h" #import @interface UploadImageApi : YTKRequest - (instancetype)initWithImage:(UIImage *)image; - (NSString *)responseImageId; @end // UploadImageApi.m #import "UploadImageApi.h" #import @implementation UploadImageApi { UIImage *_image; } - (instancetype)initWithImage:(UIImage *)image { self = [super init]; if (self) { _image = image; } return self; } - (YTKRequestMethod)requestMethod { return YTKRequestMethodPOST; } - (NSString *)requestUrl { return @"/api/images/upload"; } - (AFConstructingBlock)constructingBodyBlock { return ^(id formData) { NSData *imageData = UIImageJPEGRepresentation(_image, 0.9); [formData appendPartWithFileData:imageData name:@"image" fileName:@"photo.jpg" mimeType:@"image/jpeg"]; }; } - (id)jsonValidator { return @{ @"imageId": [NSString class] }; } - (NSString *)responseImageId { return self.responseJSONObject[@"imageId"]; } @end // Usage with upload progress - (void)uploadImage:(UIImage *)image { UploadImageApi *api = [[UploadImageApi alloc] initWithImage:image]; // Track upload progress api.uploadProgressBlock = ^(NSProgress *progress) { CGFloat percentage = progress.fractionCompleted * 100; NSLog(@"Upload progress: %.1f%%", percentage); }; [api startWithCompletionBlockWithSuccess:^(YTKBaseRequest *request) { UploadImageApi *result = (UploadImageApi *)request; NSLog(@"Image uploaded! ID: %@", [result responseImageId]); } failure:^(YTKBaseRequest *request) { NSLog(@"Upload failed: %@", request.error); }]; } ``` -------------------------------- ### Configure YTKNetwork global settings Source: https://github.com/kanyun-inc/ytknetwork/blob/master/Docs/BasicGuide_en.md Set the base URL and CDN URL during application startup to avoid repeating host addresses. ```objectivec - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { YTKNetworkConfig *config = [YTKNetworkConfig sharedConfig]; config.baseUrl = @"http://yuantiku.com"; config.cdnUrl = @"http://fen.bi"; } ``` -------------------------------- ### Configure Global Network Settings Source: https://context7.com/kanyun-inc/ytknetwork/llms.txt Initialize base URLs and debug settings using YTKNetworkConfig in the application delegate. ```objectivec // AppDelegate.m #import "YTKNetworkConfig.h" - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Configure global network settings YTKNetworkConfig *config = [YTKNetworkConfig sharedConfig]; config.baseUrl = @"https://api.example.com"; config.cdnUrl = @"https://cdn.example.com"; config.debugLogEnabled = YES; // Optional: Configure security policy // config.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate]; // Optional: Configure session // config.sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; return YES; } ``` -------------------------------- ### Call RegisterApi with Delegate Source: https://github.com/kanyun-inc/ytknetwork/blob/master/Docs/BasicGuide_en.md Initiates a registration API call with username and password, handling responses through delegate methods. Ensure the delegate conforms to the appropriate YTKRequest delegate protocols. ```objectivec - (void)loginButtonPressed:(id)sender { NSString *username = self.UserNameTextField.text; NSString *password = self.PasswordTextField.text; if (username.length > 0 && password.length > 0) { RegisterApi *api = [[RegisterApi alloc] initWithUsername:username password:password]; api.delegate = self; [api start]; } } - (void)requestFinished:(YTKBaseRequest *)request { NSLog(@"succeed"); } - (void)requestFailed:(YTKBaseRequest *)request { NSLog(@"failed"); } ``` -------------------------------- ### Call RegisterApi with Completion Block Source: https://github.com/kanyun-inc/ytknetwork/blob/master/Docs/BasicGuide_en.md Initiates a registration API call with username and password, handling success and failure via completion blocks. Retain cycles are avoided as blocks are nilled after completion. ```objectivec - (void)loginButtonPressed:(id)sender { NSString *username = self.UserNameTextField.text; NSString *password = self.PasswordTextField.text; if (username.length > 0 && password.length > 0) { RegisterApi *api = [[RegisterApi alloc] initWithUsername:username password:password]; [api startWithCompletionBlockWithSuccess:^(YTKBaseRequest *request) { // you can use self here, retain cycle won't happen NSLog(@"succeed"); } failure:^(YTKBaseRequest *request) { // you can use self here, retain cycle won't happen NSLog(@"failed"); }]; } } ``` -------------------------------- ### Implement Delegate-Based Callbacks for Network Requests Source: https://context7.com/kanyun-inc/ytknetwork/llms.txt Use the `YTKRequestDelegate` protocol for handling network request callbacks, which is beneficial for managing multiple requests or avoiding retain cycles. Assign the delegate and use tags to identify specific requests. ```objectivec // ViewController.m @interface MyViewController () @property (nonatomic, strong) GetUserInfoApi *userApi; @end @implementation MyViewController - (void)viewDidLoad { [super viewDidLoad]; [self loadUserData]; } - (void)loadUserData { self.userApi = [[GetUserInfoApi alloc] initWithUserId:@"12345"]; self.userApi.delegate = self; self.userApi.tag = 100; // Use tag to identify requests [self.userApi start]; } #pragma mark - YTKRequestDelegate - (void)requestFinished:(YTKBaseRequest *)request { if (request.tag == 100) { NSDictionary *userInfo = request.responseJSONObject; NSLog(@"User loaded: %@", userInfo[@"nick"]); // Update UI } } - (void)requestFailed:(YTKBaseRequest *)request { NSLog(@"Request failed: %@", request.error.localizedDescription); // Show error UI } @end ``` -------------------------------- ### Implement YTKRequestAccessory for Loading Indicators Source: https://context7.com/kanyun-inc/ytknetwork/llms.txt Create a custom accessory class conforming to YTKRequestAccessory to trigger UI updates during request lifecycle events. ```objectivec // YTKAnimatingRequestAccessory.h #import "YTKBaseRequest.h" @interface YTKAnimatingRequestAccessory : NSObject @property (nonatomic, weak) UIView *animatingView; - (instancetype)initWithAnimatingView:(UIView *)view; @end // YTKAnimatingRequestAccessory.m @implementation YTKAnimatingRequestAccessory - (instancetype)initWithAnimatingView:(UIView *)view { self = [super init]; if (self) { _animatingView = view; } return self; } - (void)requestWillStart:(id)request { dispatch_async(dispatch_get_main_queue(), ^{ [self showLoadingOnView:self.animatingView]; }); } - (void)requestWillStop:(id)request { // Called before completion block } - (void)requestDidStop:(id)request { dispatch_async(dispatch_get_main_queue(), ^{ [self hideLoadingOnView:self.animatingView]; }); } - (void)showLoadingOnView:(UIView *)view { // Show HUD or spinner } - (void)hideLoadingOnView:(UIView *)view { // Hide HUD or spinner } @end // Usage - (void)fetchDataWithLoading { GetUserInfoApi *api = [[GetUserInfoApi alloc] initWithUserId:@"12345"]; // Add loading indicator accessory YTKAnimatingRequestAccessory *loadingAccessory = [[YTKAnimatingRequestAccessory alloc] initWithAnimatingView:self.view]; [api addAccessory:loadingAccessory]; [api startWithCompletionBlockWithSuccess:^(YTKBaseRequest *request) { // Loading indicator hidden automatically NSLog(@"Data loaded: %@", request.responseJSONObject); } failure:^(YTKBaseRequest *request) { // Loading indicator hidden automatically NSLog(@"Error: %@", request.error); }]; } ``` -------------------------------- ### Create POST Request with Arguments Source: https://context7.com/kanyun-inc/ytknetwork/llms.txt Override `requestMethod` to POST and provide arguments via `requestArgument`. Arguments are serialized and sent as the request body. Includes response JSON validation. ```objectivec // RegisterApi.h #import "YTKRequest.h" @interface RegisterApi : YTKRequest - (instancetype)initWithUsername:(NSString *)username password:(NSString *)password; - (NSString *)userId; @end ``` ```objectivec // RegisterApi.m #import "RegisterApi.h" @implementation RegisterApi { NSString *_username; NSString *_password; } - (instancetype)initWithUsername:(NSString *)username password:(NSString *)password { self = [super init]; if (self) { _username = username; _password = password; } return self; } - (NSString *)requestUrl { return @"/api/register"; } - (YTKRequestMethod)requestMethod { return YTKRequestMethodPOST; } - (id)requestArgument { return @{ @"username": _username, @"password": _password }; } - (id)jsonValidator { return @{ @"userId": [NSNumber class], @"nick": [NSString class], @"level": [NSNumber class] }; } - (NSString *)userId { return [[[self responseJSONObject] objectForKey:@"userId"] stringValue]; } @end ``` ```objectivec // Usage - (void)registerUser { RegisterApi *api = [[RegisterApi alloc] initWithUsername:@"john_doe" password:@"securePass123"]; [api startWithCompletionBlockWithSuccess:^(YTKBaseRequest *request) { RegisterApi *result = (RegisterApi *)request; NSLog(@"Registration successful! User ID: %@", [result userId]); } failure:^(YTKBaseRequest *request) { NSLog(@"Registration failed: %@", request.error.localizedDescription); }]; } ``` -------------------------------- ### Add Custom HTTP Headers and Basic Authentication Source: https://context7.com/kanyun-inc/ytknetwork/llms.txt Override `requestHeaderFieldValueDictionary` for custom headers or `requestAuthorizationHeaderFieldArray` for HTTP Basic Authentication. Ensure the `authToken` method correctly retrieves the authentication token. ```objectivec // AuthenticatedApi.m @implementation AuthenticatedApi - (NSString *)requestUrl { return @"/api/secure/data"; } // Add custom HTTP headers - (NSDictionary *)requestHeaderFieldValueDictionary { return @{ @"Authorization": [NSString stringWithFormat:@"Bearer %@", [self authToken]], @"X-Client-Version": @"2.0.0", @"Accept-Language": @"en-US" }; } // Or use HTTP Basic Auth - (NSArray *)requestAuthorizationHeaderFieldArray { return @[@"username", @"password"]; // Will set Authorization: Basic base64(username:password) } - (NSString *)authToken { return [[NSUserDefaults standardUserDefaults] stringForKey:@"auth_token"]; } @end ``` -------------------------------- ### Enable Resumable Downloading in YTKNetwork Source: https://github.com/kanyun-inc/ytknetwork/blob/master/Docs/BasicGuide_en.md Overwrite the `resumableDownloadPath` method to specify where downloaded files should be saved. The file will be automatically stored at the provided path. ```objectivec @implementation GetImageApi { NSString *_imageId; } - (id)initWithImageId:(NSString *)imageId { self = [super init]; if (self) { _imageId = imageId; } return self; } - (NSString *)requestUrl { return [NSString stringWithFormat:@"/iphone/images/%@", _imageId]; } - (BOOL)useCDN { return YES; } - (NSString *)resumableDownloadPath { NSString *libPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSString *cachePath = [libPath stringByAppendingPathComponent:@"Caches"]; NSString *filePath = [cachePath stringByAppendingPathComponent:_imageId]; return filePath; } @end ``` -------------------------------- ### Execute Dependent Requests Sequentially with YTKChainRequest Source: https://context7.com/kanyun-inc/ytknetwork/llms.txt Use YTKChainRequest to execute requests in a specific order, where each request can depend on the response of the previous one. Implement YTKChainRequestDelegate to handle success and failure callbacks for the entire chain. ```objectivec #import "YTKChainRequest.h" #import "RegisterApi.h" #import "GetUserInfoApi.h" @interface MyViewController () @end @implementation MyViewController - (void)registerAndFetchProfile { RegisterApi *registerApi = [[RegisterApi alloc] initWithUsername:@"john_doe" password:@"securePass123"]; YTKChainRequest *chainRequest = [[YTKChainRequest alloc] init]; // First request: Register user [chainRequest addRequest:registerApi callback:^(YTKChainRequest *chain, YTKBaseRequest *baseRequest) { RegisterApi *result = (RegisterApi *)baseRequest; NSString *userId = [result userId]; NSLog(@"Registration successful, user ID: %@", userId); // Second request: Fetch user profile using the returned user ID GetUserInfoApi *profileApi = [[GetUserInfoApi alloc] initWithUserId:userId]; [chain addRequest:profileApi callback:^(YTKChainRequest *chain, YTKBaseRequest *baseRequest) { GetUserInfoApi *profile = (GetUserInfoApi *)baseRequest; NSLog(@"Profile loaded: %@", profile.responseJSONObject); // Can add more dependent requests here }]; }]; chainRequest.delegate = self; [chainRequest start]; } #pragma mark - YTKChainRequestDelegate - (void)chainRequestFinished:(YTKChainRequest *)chainRequest { NSLog(@"All chained requests completed successfully!"); NSArray *allRequests = [chainRequest requestArray]; // Process final results } - (void)chainRequestFailed:(YTKChainRequest *)chainRequest failedBaseRequest:(YTKBaseRequest *)request { NSLog(@"Chain failed at request: %@, error: %@", request.requestUrl, request.error); } @end ``` -------------------------------- ### Define a custom network request class Source: https://github.com/kanyun-inc/ytknetwork/blob/master/Docs/BasicGuide_en.md Create a subclass of YTKRequest and override methods like requestUrl, requestMethod, and requestArgument to define specific API interactions. ```objectivec // RegisterApi.h #import "YTKRequest.h" @interface RegisterApi : YTKRequest - (id)initWithUsername:(NSString *)username password:(NSString *)password; @end // RegisterApi.m #import "RegisterApi.h" @implementation RegisterApi { NSString *_username; NSString *_password; } - (id)initWithUsername:(NSString *)username password:(NSString *)password { self = [super init]; if (self) { _username = username; _password = password; } return self; } - (NSString *)requestUrl { // “http://www.yuantiku.com” is set in YTKNetworkConfig, so we ignore it return @"/iphone/register"; } - (YTKRequestMethod)requestMethod { return YTKRequestMethodPOST; } - (id)requestArgument { return @{ @"username": _username, @"password": _password }; } @end ``` -------------------------------- ### Build Custom NSURLRequest in Objective-C Source: https://context7.com/kanyun-inc/ytknetwork/llms.txt Override buildCustomUrlRequest to manually configure request headers, methods, and body content. ```objectivec // GzipUploadApi.m - (NSURLRequest *)buildCustomUrlRequest { // Convert data to gzipped format NSData *rawData = [[_events jsonString] dataUsingEncoding:NSUTF8StringEncoding]; NSData *gzippedData = [rawData gzippedData]; // Using a gzip library // Build custom request NSURL *url = [NSURL URLWithString:[self.baseUrl stringByAppendingString:@"/api/events"]]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request addValue:@"application/json;charset=UTF-8" forHTTPHeaderField:@"Content-Type"]; [request addValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"]; [request setHTTPBody:gzippedData]; return request; } ``` -------------------------------- ### Use CDN Address for Requests Source: https://github.com/kanyun-inc/ytknetwork/blob/master/Docs/BasicGuide_en.md Enables the use of a Content Delivery Network (CDN) for requests by overriding the `useCDN` method and returning YES. This is useful for assets like images. ```objectivec // GetImageApi.h #import "YTKRequest.h" @interface GetImageApi : YTKRequest - (id)initWithImageId:(NSString *)imageId; @end // GetImageApi.m #import "GetImageApi.h" @implementation GetImageApi { NSString *_imageId; } - (id)initWithImageId:(NSString *)imageId { self = [super init]; if (self) { _imageId = imageId; } return self; } - (NSString *)requestUrl { return [NSString stringWithFormat:@"/iphone/images/%@", _imageId]; } - (BOOL)useCDN { return YES; } @end ``` -------------------------------- ### Implement Response Caching Source: https://context7.com/kanyun-inc/ytknetwork/llms.txt Enable automatic response caching by overriding `cacheTimeInSeconds`. Cached responses are served until expiration. Supports version-based invalidation and additional cache sensitivity data. ```objectivec // CachedUserInfoApi.m @implementation CachedUserInfoApi { NSString *_userId; } - (instancetype)initWithUserId:(NSString *)userId { self = [super init]; if (self) { _userId = userId; } return self; } - (NSString *)requestUrl { return @"/api/users"; } - (id)requestArgument { return @{ @"id": _userId }; } // Cache for 3 minutes (180 seconds) - (NSInteger)cacheTimeInSeconds { return 60 * 3; } // Optional: Version-based cache invalidation - (long long)cacheVersion { return 1; } // Optional: Additional cache sensitivity data - (id)cacheSensitiveData { return @{ @"appVersion": @"2.0" }; } @end ``` ```objectivec // Usage: Load cached data first, then refresh - (void)loadUserWithCache { CachedUserInfoApi *api = [[CachedUserInfoApi alloc] initWithUserId:@"12345"]; // Try to load from cache first if ([api loadCacheWithError:nil]) { NSDictionary *cachedData = [api responseJSONObject]; NSLog(@"Showing cached data: %@", cachedData); // Update UI with cached data immediately } // Then fetch fresh data [api startWithCompletionBlockWithSuccess:^(YTKBaseRequest *request) { if ([request isDataFromCache]) { NSLog(@"Data served from cache"); } else { NSLog(@"Fresh data received"); // Update UI with new data } } failure:^(YTKBaseRequest *request) { NSLog(@"Request failed: %@", request.error); }]; } ``` ```objectivec // Force refresh without using cache - (void)forceRefreshUser { CachedUserInfoApi *api = [[CachedUserInfoApi alloc] initWithUserId:@"12345"]; api.ignoreCache = YES; // Or use [api startWithoutCache]; [api start]; } ``` -------------------------------- ### Add Common Parameters to All Requests with YTKUrlArgumentsFilter Source: https://context7.com/kanyun-inc/ytknetwork/llms.txt Use YTKUrlArgumentsFilter to append common query parameters like version numbers or device IDs to all outgoing requests. Ensure YTKNetworkConfig is set up with this filter. ```objectivec // YTKUrlArgumentsFilter.h #import #import "YTKNetworkConfig.h" @interface YTKUrlArgumentsFilter : NSObject + (instancetype)filterWithArguments:(NSDictionary *)arguments; @end // YTKUrlArgumentsFilter.m @implementation YTKUrlArgumentsFilter { NSDictionary *_arguments; } + (instancetype)filterWithArguments:(NSDictionary *)arguments { return [[self alloc] initWithArguments:arguments]; } - (instancetype)initWithArguments:(NSDictionary *)arguments { self = [super init]; if (self) { _arguments = arguments; } return self; } - (NSString *)filterUrl:(NSString *)originUrl withRequest:(YTKBaseRequest *)request { // Append query parameters to URL NSMutableString *filteredUrl = [originUrl mutableCopy]; NSString *separator = [originUrl containsString:@"?"] ? @"&" : @"?"; for (NSString *key in _arguments) { [filteredUrl appendFormat:@"%@%@=%@", separator, key, _arguments[key]]; separator = @"&"; } return filteredUrl; } @end // Setup in AppDelegate - (void)setupRequestFilters { YTKNetworkConfig *config = [YTKNetworkConfig sharedConfig]; // Add app version to all requests NSString *appVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; NSString *deviceId = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; YTKUrlArgumentsFilter *filter = [YTKUrlArgumentsFilter filterWithArguments:@{ @"version": appVersion, @"platform": @"ios", @"device_id": deviceId }]; [config addUrlFilter:filter]; } ``` -------------------------------- ### Execute Multiple Requests in Parallel with YTKBatchRequest Source: https://context7.com/kanyun-inc/ytknetwork/llms.txt Use YTKBatchRequest to send multiple independent requests concurrently. The success callback is invoked only if all requests in the batch complete successfully. Access individual results from the batch's requestArray. ```objectivec #import "YTKBatchRequest.h" #import "GetUserInfoApi.h" #import "DownloadFileApi.h" - (void)loadDashboardData { // Create multiple independent requests GetUserInfoApi *userApi = [[GetUserInfoApi alloc] initWithUserId:@"12345"]; DownloadFileApi *avatarApi = [[DownloadFileApi alloc] initWithFileId:@"avatar.jpg"]; DownloadFileApi *bannerApi = [[DownloadFileApi alloc] initWithFileId:@"banner.jpg"]; GetUserInfoApi *friendApi = [[GetUserInfoApi alloc] initWithUserId:@"67890"]; // Batch them together YTKBatchRequest *batchRequest = [[YTKBatchRequest alloc] initWithRequestArray:@[ userApi, avatarApi, bannerApi, friendApi ]]; [batchRequest startWithCompletionBlockWithSuccess:^(YTKBatchRequest *batch) { NSLog(@"All requests completed successfully!"); // Access individual results NSArray *requests = batch.requestArray; GetUserInfoApi *user = (GetUserInfoApi *)requests[0]; DownloadFileApi *avatar = (DownloadFileApi *)requests[1]; DownloadFileApi *banner = (DownloadFileApi *)requests[2]; GetUserInfoApi *friend = (GetUserInfoApi *)requests[3]; NSLog(@"User: %@", user.responseJSONObject); NSLog(@"Avatar path: %@", avatar.responseObject); NSLog(@"Banner path: %@", banner.responseObject); NSLog(@"Friend: %@", friend.responseJSONObject); // Check if data came from cache if ([batch isDataFromCache]) { NSLog(@"All data served from cache"); } } failure:^(YTKBatchRequest *batch) { YTKRequest *failedRequest = batch.failedRequest; NSLog(@"Batch failed. First failing request: %@", failedRequest.error); }]; } ``` -------------------------------- ### Define JSON Response Structure for Validation Source: https://context7.com/kanyun-inc/ytknetwork/llms.txt Implement the `jsonValidator` method to define the expected structure and types of a JSON response. Requests will automatically fail if the response does not conform to the specified validator. ```objectivec // ComplexValidationApi.m - (id)jsonValidator { // Validate complex nested structure return @[@{ @"id": [NSNumber class], @"imageId": [NSString class], @"time": [NSNumber class], @"status": [NSNumber class], @"question": @{ @"id": [NSNumber class], @"content": [NSString class], @"contentType": [NSNumber class] } }]; } // Simple array of strings validation - (id)jsonValidatorForStringArray { return @[ [NSString class] ]; } // Simple object validation - (id)jsonValidatorForUserObject { return @{ @"nick": [NSString class], @"level": [NSNumber class], @"email": [NSString class] }; } ``` -------------------------------- ### Cache API Response Data in YTKNetwork Source: https://github.com/kanyun-inc/ytknetwork/blob/master/Docs/BasicGuide_en.md Overwrite the `cacheTimeInSeconds` method to enable automatic caching of API responses. If cached data is valid, API calls will return cached results without network traffic. ```objectivec @implementation GetUserInfoApi { NSString *_userId; } - (id)initWithUserId:(NSString *)userId { self = [super init]; if (self) { _userId = userId; } return self; } - (NSString *)requestUrl { return @"/iphone/users"; } - (id)requestArgument { return @{ @"id": _userId }; } - (id)jsonValidator { return @{ @"nick": [NSString class], @"level": [NSNumber class] }; } - (NSInteger)cacheTimeInSeconds { // cache 3 minutes, which is 60 * 3 = 180 seconds return 60 * 3; } @end ``` -------------------------------- ### Validate JSON Response Structure Source: https://github.com/kanyun-inc/ytknetwork/blob/master/Docs/BasicGuide_en.md Ensures the response JSON adheres to a specific structure and data types for keys like 'nick' (NSString) and 'level' (NSNumber). This prevents client crashes due to faulty server data. ```objectivec - (id)jsonValidator { return @{ @"nick": [NSString class], @"level": [NSNumber class] }; } ``` -------------------------------- ### Validate String Array Response Source: https://github.com/kanyun-inc/ytknetwork/blob/master/Docs/BasicGuide_en.md Specifies that the expected JSON response should be an array of strings. ```objectivec - (id)jsonValidator { return @[ [NSString class] ]; } ``` -------------------------------- ### Validate Complex Nested JSON Structure Source: https://github.com/kanyun-inc/ytknetwork/blob/master/Docs/BasicGuide_en.md Validates a complex JSON structure with nested objects and arrays, ensuring specific data types for each field. ```objectivec - (id)jsonValidator { return @[@{ @"id": [NSNumber class], @"imageId": [NSString class], @"time": [NSNumber class], @"status": [NSNumber class], @"question": @{ @"id": [NSNumber class], @"content": [NSString class], @"contentType": [NSNumber class] } }]; } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.