基於Afnetworking 網路層的封裝

来源:https://www.cnblogs.com/xujinzhong/archive/2018/02/05/8417273.html
-Advertisement-
Play Games

LSAFHTTPClient 對所有請求進行統一管理,添加了兩個隊列:一個工作隊列,一個讀寫緩存的io隊列 LSAFHTTPClient.h 代碼如下: LSAFHTTPClient.m 代碼如下: LSBaseRequest 實現網路層的統一請求,在子類請求中調用基類的請求方法。 LSBaseRe ...


LSAFHTTPClient 對所有請求進行統一管理,添加了兩個隊列:一個工作隊列,一個讀寫緩存的io隊列

LSAFHTTPClient.h 代碼如下:

 1 #import "AFNetworking.h"
 2 
 3 @interface LSAFHTTPClient : AFHTTPRequestOperationManager
 4 
 5 @property (nonatomic, strong) dispatch_queue_t workQueue;//Serail Send Request Queue
 6 @property (nonatomic, strong) dispatch_queue_t iOSerialQueue;
 7 
 8 +(LSAFHTTPClient*)shareClient;
 9 
10 typedef void (^LSRequestResultBlock)(id result, NSError *err);
11 
12 -(BOOL)isHttpQueueFinished:(NSArray*)httpUrlArray;
13 @end

 

LSAFHTTPClient.m 代碼如下:

 1 #import "LSAFHTTPClient.h"
 2 #import "LSBaseRequest.h"
 3 #import "LSHelper.h"
 4 #import "AFHTTPRequestOperation.h"
 5 #import "AFURLConnectionOperation.h"
 6 #import "LSPathMacro.h"
 7 #import <Foundation/Foundation.h>
 8 @implementation LSAFHTTPClient
 9 
10 +(LSAFHTTPClient*)shareClient
11 {
12     static LSAFHTTPClient* _shareClient;
13     static dispatch_once_t onceToken;
14     dispatch_once(&onceToken, ^{
15         _shareClient = [[LSAFHTTPClient alloc]initWithBaseURL:[NSURL URLWithString:LSURLHeadStatic]];
16         [_shareClient.requestSerializer setTimeoutInterval:15]; //網路超時時間15S
17 
18         //一個工作隊列,一個讀寫緩存的io隊列
19         _shareClient.workQueue = dispatch_queue_create("com.shareClient.workQueue", DISPATCH_QUEUE_SERIAL);
20         _shareClient.iOSerialQueue = dispatch_queue_create("com.shareClient.iOSerialQueue", DISPATCH_QUEUE_SERIAL);
21     });
22     return _shareClient;
23 }
24 
25 - (id)initWithBaseURL:(NSURL *)url
26 {
27     self = [super initWithBaseURL:url];
28 
29     if (!self) {
30         return nil;
31     }
32     return self;
33 }
34 - (void)dealloc
35 {
36    
37 }
38 -(BOOL)isHttpQueueFinished:(NSArray*)httpUrlArray
39 {
40     NSLog(@"%ld",self.operationQueue.operationCount);
41     if(self.operationQueue.operationCount==0){
42         return YES;
43     }
44 
45     //add filter urlString.length==0
46     NSMutableArray* urlArray = [NSMutableArray array];
47     for (NSString* currentUrl in httpUrlArray) {
48         if (currentUrl.length != 0) {
49             [urlArray addObject:currentUrl];
50         }
51     }
52 
53     //urlArray is empty
54     if(urlArray.count == 0){
55         return YES;
56     }
57 
58     for (AFHTTPRequestOperation* operation in self.operationQueue.operations) {
59         NSString* url = operation.request.URL.absoluteString;
60         for (NSString* baseUrl in urlArray) {
61             if ([url rangeOfString:baseUrl].location!=NSNotFound) {
62                 return NO;
63             }
64         }
65     }
66     return YES;
67 }
68 @end

 

LSBaseRequest 實現網路層的統一請求,在子類請求中調用基類的請求方法。

LSBaseRequest.h 代碼如下:

 1 #import <Foundation/Foundation.h>
 2 #import "LSAFHTTPClient.h"
 3 #import "LSGlobal.h"
 4 #import "LSBaseState.h"
 5 #import "LSErrorState.h"
 6 #import "LSSuccessState.h"
 7 #import "AESCrypt.h"
 8 
 9 typedef enum{
10     LSREQUESTMETHODGET=0,
11     LSREQUESTMETHODPOST=1
12 }LSREQUESTMETHOD;
13 
14 @class LSBaseRequest;
15 
16 @interface LSBaseRequest : NSObject
17 
18 @property(nonatomic)         LSREQUESTMETHOD              requestMethod;    //請求方式
19 @property(nonatomic, strong) NSString                     *methodName;      //方法名
20 @property(nonatomic, strong) NSString                     *event;           //觸發事件
21 @property(nonatomic, strong) NSString                     *cache;           //是否緩存
22 @property(nonatomic)         BOOL                         isGzip;           //是否壓縮
23 @property (strong,nonatomic) id                           result;
24 @property(nonatomic, assign) long                         ret;              //標識數據否更新
25 @property (strong,nonatomic)NSMutableDictionary* parametersDic;   //參數字典     json
26 
27 /** 重覆次數 */
28 @property(nonatomic, assign) NSInteger                    numOfRepeat;//網路請求失敗後重覆的次數
29 
30 /** 
31  @brief 網路錯誤碼,通過此錯誤碼可以判斷出是否是取消請求造成網路失敗,從而不需要顯示無數據,7.11加
32  @note kCFURLErrorCancelled為取消請求
33  */
34 @property (nonatomic, assign) NSInteger network_error_code;
35 
36 - (void)setIntegerValue:(NSInteger)value forKey:(NSString *)key;
37 - (void)setDoubleValue:(double)value forKey:(NSString *)key;
38 - (void)setLongLongValue:(long long)value forKey:(NSString *)key;
39 - (void)setBOOLValue:(BOOL)value forKey:(NSString *)key;
40 - (void)setValue:(id)value forKey:(NSString *)key;
41 
42 -(void)sendRequestSuccFinishBlock:(void(^)(LSBaseRequest* request))requestFinishBlock requestFailFinishBlock:(void(^)(LSBaseRequest* request))requestFailFinishBlock;
43 -(void)sendUpdateImageRequestSuccFinishBlock:(void(^)(LSBaseRequest* request))requestFinishBlock requestFailFinishBlock:(void(^)(LSBaseRequest* request))requestFailFinishBlock withImageData:(NSData*)imgData;
44 /*
45  * @brief 伺服器返回的數據解析成功後會調用
46  * @note  可以訪問self.result得到伺服器返回的結果,一定是NSDictionary類型。
47  * @note  對網路請求的數據結果進行封裝(可選) 子類實現
48  */
49 -(id)processResultWithDic:(NSMutableDictionary*)resultDic;
50 
51 /*
52  *@brief 請使用此方法取消網路請求
53  */
54 +(void)cancelRequest;
55 
56 /**
57  *  @note 用戶初始化子類request,調用完畢self.methodName=@"xxxx"後,此getUrlName方法有效。
58  *  @note 否則返回為空字元串. @""
59  *  @note 不允許子類實現
60  */
61 +(NSString*)getUrlName;
62 /**
63  *  @brief 此方法可以根據傳入的urlArray判斷是否http已經完成
64  *  @note  don't OVERRIDE this method
65  */
66 +(BOOL)isHttpQueueFinished:(NSArray*)httpUrlArray;
67 
68 /**
69  *  @brief 此方法可以根據傳入的class類名判斷是否http已經完成
70  *  @note  don't OVERRIDE this method
71  *  @example
72         NSArray* classNameArray = @[@"LSUpdateDataRequest", @"LSSearchGoodsRequest",
73                                     @"LSGoodsListRequest", @"LSCinemaListRequest"];
74         BOOL isFinished = [LSBaseRequest isHttpQueueFinishedWithClassNameArray:classNameArray];
75  */
76 +(BOOL)isHttpQueueFinishedWithClassNameArray:(NSArray*)requestClassArray;
77 
78 @end

 

LSBaseRequest.m 代碼如下:

  1 #import <objc/objc.h>
  2 #import <objc/runtime.h>
  3 #import "LSBaseRequest.h"
  4 #import "LSDesUtil.h"
  5 #import "AFHTTPRequestOperation.h"
  6 #import "LSCacheFile.h"
  7 #import "LSServerResult.h"
  8 #import "NSString+LSAdditional.h"
  9 
 10 #define LSBASEREQUEST_METHODNAME_KEY @"LSBASEREQUEST_METHODNAME_KEY"
 11 //uncomment folling line if you need to test request performance
 12 //#define ENABLE_LSBASEREQUEST_LOG
 13 
 14 #ifdef ENABLE_LSBASEREQUEST_LOG
 15 #define RequestLog(fmt, ...) NSLog((@"%s [Line %d] %@ " fmt), __PRETTY_FUNCTION__, __LINE__,self, ##__VA_ARGS__)
 16 #else
 17 #define RequestLog(fmt, ...)
 18 #endif
 19 
 20 @interface LSBaseRequest ()
 21 {
 22     void(^_requestSuccFinishBlock)(LSBaseRequest*);
 23     void(^_requestFailFinishBlock)(LSBaseRequest*);
 24 
 25     NSMutableDictionary* _httpBodyDic;
 26     NSString           * _key;
 27     NSString           * _webtime;
 28 
 29     BOOL                _isResetBlock;//是否進行複位block
 30     NSInteger           _internalRet;//內部使用的ret
 31     BOOL                _isFailBlockFinish;
 32     
 33 }
 34 
 35 @end
 36 
 37 @implementation LSBaseRequest
 38 
 39 -(id)init
 40 {
 41     self = [super init];
 42     if (self){
 43         _requestMethod = LSREQUESTMETHODPOST;
 44         _parametersDic = [[NSMutableDictionary alloc] init];
 45         _httpBodyDic   = [[NSMutableDictionary alloc] init];
 46         self.numOfRepeat = 1;        //預設網路請求失敗請求3次
 47     }
 48     return self;
 49 }
 50 
 51 -(void)setMethodName:(NSString *)methodName
 52 {
 53     objc_setAssociatedObject([self class], LSBASEREQUEST_METHODNAME_KEY, methodName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
 54     _methodName = methodName;
 55 }
 56 - (void)setIntegerValue:(NSInteger)value forKey:(NSString *)key
 57 {
 58     [self setValue:[NSString stringWithFormat:@"%ld", value] forKey:key];
 59 }
 60 - (void)setDoubleValue:(double)value forKey:(NSString *)key
 61 {
 62     [self setValue:[NSString stringWithFormat:@"%f", value] forKey:key];
 63 }
 64 - (void)setLongLongValue:(long long)value forKey:(NSString *)key
 65 {
 66     [self setValue:[NSString stringWithFormat:@"%lld", value] forKey:key];
 67 }
 68 - (void)setBOOLValue:(BOOL)value forKey:(NSString *)key
 69 {
 70     [self setValue:[NSString stringWithFormat:@"%d", value] forKey:key];
 71 }
 72 - (void)setValue:(id)value forKey:(NSString *)key
 73 {
 74     //value只能是字元串,如果不是字元串類型,[LSHelper getSignParam]會crash,暫時未做處理。
 75     if(!value){
 76         value = @"";
 77     }
 78     [_parametersDic setValue:value forKey:key];
 79 }
 80 
 81 
 82 -(void)sendRequestSuccFinishBlock:(void(^)(LSBaseRequest* request))requestFinishBlock requestFailFinishBlock:(void(^)(LSBaseRequest* request))requestFailFinishBlock
 83 {
 84     _requestFailFinishBlock = requestFailFinishBlock;
 85     _requestSuccFinishBlock = requestFinishBlock;
 86     _isResetBlock = NO;
 87     _isFailBlockFinish = NO;
 88     self.result = nil;
 89     //serail send request
 90 //    RequestLog(@"in MainThread begin send request");
 91     dispatch_async([LSAFHTTPClient shareClient].workQueue, ^{
 92 //        RequestLog(@"serial send request");
 93         if (_requestMethod == LSREQUESTMETHODGET) {
 94             [self doGetRequest];
 95         }else if(_requestMethod == LSREQUESTMETHODPOST){
 96             [self doPostRequest];
 97         }
 98     });
 99 }
100 
101 -(void)sendUpdateImageRequestSuccFinishBlock:(void(^)(LSBaseRequest* request))requestFinishBlock requestFailFinishBlock:(void(^)(LSBaseRequest* request))requestFailFinishBlock withImageData:(NSData*)imgData
102 {
103     _requestFailFinishBlock = requestFailFinishBlock;
104     _requestSuccFinishBlock = requestFinishBlock;
105     _isResetBlock = NO;
106     _isFailBlockFinish = NO;
107     self.result = nil;
108     //serail send request
109 //    RequestLog(@"in MainThread begin send request");
110     dispatch_async([LSAFHTTPClient shareClient].workQueue, ^{
111 //        RequestLog(@"serial send request");
112         if (_requestMethod == LSREQUESTMETHODGET) {
113             [self doGetRequest];
114         }else if(_requestMethod == LSREQUESTMETHODPOST){
115             [self sendUpdateImageRequestWithData:imgData];
116         }
117     });
118 }
119 #pragma mark 發起Get或Post請求
120 -(void)doGetRequest
121 {
122     LSAFHTTPClient *httpClient = [LSAFHTTPClient shareClient];
123     [self setparamesDic];
124      httpClient.responseSerializer = [AFImageResponseSerializer serializer];
125     [httpClient GET:_methodName parameters:_httpBodyDic success:^(AFHTTPRequestOperation *operation, id responseObject) {
126                 self.result = responseObject;
127                 _requestSuccFinishBlock(self);
128     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
129          [self handlerErrorResponse:error];
130     }];
131     
132 }
133 
134 -(void)doPostRequest
135 {
136     [self sendDataNumOfRepeat:self.numOfRepeat];
137     //equestLog(@"serial postPath End");
138 }
139 
140 -(void)sendDataNumOfRepeat:(NSInteger)numOfRepeat{
141     
142     LSAFHTTPClient *httpClient = [LSAFHTTPClient shareClient];
143     NSLog(@"%@", [httpClient.baseURL host]);
144     [self setparamesDic];
145 
146      httpClient.responseSerializer = [AFJSONResponseSerializer serializer];
147 //    [httpClient.requestSerializer setTimeoutInterval:15];
148     [httpClient POST:_methodName parameters:_httpBodyDic success:^(AFHTTPRequestOperation *operation, id responseObject) {
149         //concurrent deal block
150         //RequestLog(@"concurrent deal block Success");
151         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
152             [self hanleSuccessResponseWithOperation:operation response:responseObject];
153         });
154   
155     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
156         //RequestLog(@"concurrent deal block Fail");
157         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
158             if (numOfRepeat <= 1){
159                 [self handlerErrorResponse:error];
160             }else{
161                 dispatch_async([LSAFHTTPClient shareClient].workQueue, ^{
162                     [self sendDataNumOfRepeat:numOfRepeat -1];
163                 });
164             }
165         });
166 
167     }];
168 }
169 
170 - (void)sendUpdateImageRequestWithData:(NSData*)imgData
171 {
172     LSAFHTTPClient *httpClient = [LSAFHTTPClient shareClient];
173     [self setparamesDic];
174     [httpClient POST:@"member/upimg" parameters:_httpBodyDic constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
175         NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
176         // 設置時間格式
177         formatter.dateFormat = @"yyyyMMddHHmmss";
178         NSString *str = [formatter stringFromDate:[NSDate date]];
179         NSString *fileName = [NSString stringWithFormat:@"%@.jpg", str];
180         [formData appendPartWithFileData:imgData name:@"img" fileName:fileName mimeType:@"image/jpeg"];
181     } success:^(AFHTTPRequestOperation *operation, id responseObject) {
182         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
183             [self hanleSuccessResponseWithOperation:operation response:responseObject];
184         });
185     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
186          [self handlerErrorResponse:error];
187     }];
188     
189 }
190 
191 
192 - (void)sendImagData:(NSData*)imageData
193 {
194     
195     LSAFHTTPClient *httpClient = [LSAFHTTPClient shareClient];
196     [self setparamesDic];
197 
198    [httpClient POST:@"member/upimg" parameters:_httpBodyDic constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
199         [formData appendPartWithFileData:imageData name:@"img" fileName:@"ios_header_img.jpg" mimeType:@"image/jpeg"];
200     } success:^(AFHTTPRequestOperation *operation, id responseObject) {
201         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
202             [self hanleSuccessResponseWithOperation:operation response:responseObject];
203         });
204     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
205         [self handlerErrorResponse:error];
206     }];
207     
208     
209 }
210 
211 
212 -(void)setparamesDic
213 {
214     /*
215      body: params, time, sign, token
216      */
217   
218     NSString *device_name = [LSHelper deviceType];
219     NSString *system_version = [LSHelper iOSVersion];
220     NSString *timestamp = [LSHelper getTimeStamp];
221     NSString *device_id = [LSHelper getCurrentDeviceUDID];
222     NSString *device_type = @"ios";
223     NSString *version_no =  kSoftwareVersion;
224     NSString *token = [LSGlobal sharedGlobal].token;
225     NSString *channel_id = @"10000";
226 
227     [_httpBodyDic setValue:device_name forKey:@"device_name"];
228     [_httpBodyDic setValue:system_version forKey:@"system_version"];
229     [_httpBodyDic setValue:timestamp forKey:@"timestamp"];
230     [_httpBodyDic setValue:token forKey:@"token"];
231     [_httpBodyDic setValue:device_id forKey:@"device_id"];
232     [_httpBodyDic setValue:device_type forKey:@"device_type"];
233     [_httpBodyDic setValue:version_no forKey:@"version_no"];
234     [_httpBodyDic setValue:channel_id forKey:@"channel_id"];
235     [_httpBodyDic addEntriesFromDictionary:_parametersDic];
236     
237     //添加加密欄位
238     [_httpBodyDic setValue:[NSString getSignPara:_httpBodyDic andTime:nil] forKey:@"security"];
239 }
240 #pragma mark 讀取寫入緩存
241 -(void)readCacheFile
242 {
243     //sync read for webtime and serverKey
244     NSString *md5file_token = [self mdt5FileName:@"token"];
245     NSDictionary *dic = [LSCacheFile readFileName:md5file_token];
246     if (dic) {
247         _webtime = [dic objectForKey:@"webtime"];
248         _key     = [dic objectForKey:@"serverkey"];
249     }
250 
251     //async read for local content
252     dispatch_async([LSAFHTTPClient shareClient].iOSerialQueue, ^{
253         NSString *md5file_local = [self mdt5FileName:@"local"];
254         NSMutableDictionary* resultDic = [LSCacheFile readFileName:md5file_local];
255         if(resultDic){
256             [self handlerSuccFinishResponseWithDic:resultDic isWeb:NO serverResult:nil];
257         }
258     });
259 }
260 
261 -(void)writeCacheFileWithKey:(NSString *)serverkey webtime:(NSString *)webtime resultDic:(id)resultDic
262 {
263     //async write to local and token file
264     dispatch_async([LSAFHTTPClient shareClient].iOSerialQueue, ^{
265         if (!serverkey || !webtime) {
266             DLog(@"%@, ERROR:serverkey or webtime is nil, write to cache failed", self);
267             return ;
268         }
269         NSString *md5file_token = [self mdt5FileName:@"token"];
270         NSDictionary *dic = @{@"webtime":webtime,@"serverkey":serverkey};
271         [LSCacheFile writeFileName:md5file_token data:dic];
272         NSString *md5file_local = [self mdt5FileName:@"local"];
273         [LSCacheFile writeFileName:md5file_local data:resultDic];
274     });
275 }
276 #pragma mark 處理返回的結果
277 -(void)hanleSuccessResponseWithOperation:(AFHTTPRequestOperation *)operation response:(id)responseObject
278 {
279     [self handlerResponse:responseObject serverKey:nil  des:nil webtime:nil];
280 }
281 -(void)handlerResponse:(id)responseObject serverKey:(NSString *)serverkey des:(NSString *)des webtime:(NSString *)webtime
282 {
283     LSServerResult *serverResult = [[LSServerResult alloc] init];
284     serverResult.serverKey = serverkey;
285     serverResult.webTime = webtime;
286     
287     NSData* clearData =  responseObject;
288     NSError *error = nil;
289     NSMutableDictionary* resultDic = (NSMutableDictionary*)clearData;
290 //    if (clearData) {
291 //        resultDic = [LSHelper parserJsonData:clearData];
292 //        if(![resultDic isKindOfClass:[NSDictionary class]])
293 //        {
294 //            resultDic = nil;
295 //        }
296 //    }
297     if (clearData  && !error)
298     {
299         if ([_cache isEqualToString:@"true"]) {
300             _internalRet = [[resultDic objectForKey:@"ret"] longValue];
301             if (_internalRet != kNetRetFlag) {
302                 serverResult.resultDic = resultDic;
303                 [self handlerSuccFinishResponseWithDic:resultDic isWeb:YES serverResult:serverResult];
304             }
305             else{
306                 //需要處理清空finishblock的情況。同時還註意不要將緩存清掉。
307                 [self handlerSuccFinishResponseWithNetFlag];
308             }
309         }else{
310             [self handlerSuccFinishResponseWithDic:resultDic isWeb:YES serverResult:serverResult];
311         }
312     }else{
313         //數據不是json格式
314         [self handlerErrorResponse:nil];
315     }
316 }
317 
318 /** 如果緩存先返回,而且設置了resetBlock標記,網路返回99999時候進行reset。 */
319 -(void)handlerSuccFinishResponseWithNetFlag
320 {
321     dispatch_async(dispatch_get_main_queue(), ^{
322         if(_isResetBlock){
323             [self resetFinishBlock];
324         }
325
              
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 索引: 使用索引可快速訪問資料庫表中的特定信息。索引是對資料庫表中一列或多列的值進行排序的一種結構,例如 employee 表的姓(name)列。如果要按姓查找特定職員,與必須搜索表中的所有行相比,索引會幫助您更快地獲得該信息。 索引是一個單獨的、物理的資料庫結構,它是某個表中一列或若幹列值的集合和 ...
  • https://github.com/mono/old-code https://wiki.scn.sap.com/wiki/display/SQLANY/SQL+Anywhere+and+Microsoft+.NET http://www.mono-project.com/docs/databas ...
  • DML和DQL 增刪改查 SELECT * FROM grade --新增 insert -- 向年級表中新增3條數據INSERT INTO grade(gradeID,gradeName) VALUES(4,'4年級');INSERT INTO grade(gradeID,gradeName) V ...
  • 一,iOS設備中的蜂窩網路通信棧運行在專門的晶元上,這個晶元就是數字基帶處理器。 參考資料:《黑客攻防技術寶典-iOS實戰篇》 ...
  • 尊重勞動成果,轉載請標明出處:http://www.cnblogs.com/tangZH/p/8419053.html 在做項目的過程中,遇到了一個奇怪的現象,我設置RelativeLayout為的寬度為wrap_content,而且RelativeLayout裡面的組件也設置了固定大小,可是Rel ...
  • 尊重勞動成果,轉載請標明出處:http://www.cnblogs.com/tangZH/p/8419010.html 我們在項目中經常需在一個listview中展示不一樣的佈局,我們可以在adapter的getView()中根據position來決定該展示哪些佈局。 我在項目中便是如此,第一個it ...
  • 前言:圖片選擇器基本上是每個App必備的東西,用公認好的第三方也可以,但是自己寫的改起來方便,用起來順手,而且這東西想想可能沒動手之前想想比較難,實際操作起來就很簡單了,這次先主要寫流程,具體優化的細節以後在寫。 難點:動手之前最困惑的問題就是怎麼獲取到手機里所有的圖片,獲取到之後,顯示出來,處理邏 ...
  • 前段時間弄了一款安卓電視盒子的遠程遙控輸入法APP:TVRemoteIME,此APP實現了遠程跨屏的輸入、遙控和應用管理功能。 最近發現盒子上要播放電影資源除了買APP會員之外,能直接免費播放電影的第三方APP越來越少了,要麼更新不及時要麼電影資源非常的少或者廣告繁多。而在電腦上要找一部電影播放還是... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...