• 【iOS逆向与安全】好用的一套 TCP 类


     初始化

    1. //页面
    2. %hook xxxxxxxViewController
    3. //- (void)viewWillAppear:(BOOL)animated{
    4. //NSLog(@"View Will Appear,再次进入刷新");
    5. - (void)viewDidLoad{
    6. //启动tcp
    7. [[Xddtcp sharedTcpManager] connectServer] ;
    8. }

     发送数据

    1. //发送数据
    2. [[Xddtcp sharedTcpManager] sendDataToServer:[@"MyiPhone" dataUsingEncoding:NSUTF8StringEncoding]] ;

    源码类

    1. //
    2. // Xddtcp.m
    3. // YFX_ScoketForClientDemo
    4. //
    5. // Created by adminxdd on 2020/8/20.
    6. // Copyright © 2020 fangxue. All rights reserved.
    7. //
    8. #import "Xddtcp.h"
    9. #define WSELF __weak typeof(self) wself = self;
    10. /** 主线程异步队列 */
    11. #define Dispatch_main_async_safe(block)\
    12. if ([NSThread isMainThread]) {\
    13. block();\
    14. } else {\
    15. dispatch_async(dispatch_get_main_queue(), block);\
    16. }
    17. //@implementation Xddtcp
    18. @interface Xddtcp() <GCDAsyncSocketDelegate>
    19. /** 心跳计时器 */
    20. @property (nonatomic, strong) NSTimer *heartBeatTimer;
    21. /** 没有网络的时候检测网络定时器 */
    22. @property(nonatomic,strong)NSTimer*netWorkTestingTimer;
    23. /** 存储要发送给服务端的数据 */
    24. @property (nonatomic, strong) NSMutableArray *sendDataArray;
    25. /** 数据请求队列(串行队列) */
    26. @property (nonatomic, strong) dispatch_queue_t queue;
    27. /** 重连时间 */
    28. @property (nonatomic, assign) NSTimeInterval reConnectTime;
    29. /** 用于判断是否主动关闭长连接,如果是主动断开连接,连接失败的代理中,就不用执行 重新连接方法 */
    30. @property (nonatomic, assign) BOOL isActivelyClose;
    31. /** 缓存区域 */
    32. @property (nonatomic, strong) NSMutableData *readBuf;
    33. @end
    34. @implementation Xddtcp
    35. #pragma mark - 🔥🔥🔥🔥🔥🔥🔥🔥
    36. #pragma mark ----单利------
    37. /** 单利 */
    38. + (instancetype)sharedTcpManager{
    39. static Xddtcp*_instace =nil;
    40. static dispatch_once_t onceToken;
    41. dispatch_once(&onceToken,^{
    42. _instace = [[self alloc]init];
    43. NSLog(@"TCP 单利实例化!");
    44. });
    45. return _instace;
    46. }
    47. #pragma mark ----初始化------
    48. /** 初始化 */
    49. - (instancetype)init{
    50. self= [super init];
    51. if(self){
    52. self.reConnectTime = 0;
    53. self.isActivelyClose = NO;
    54. self.queue = dispatch_queue_create("BF",NULL);
    55. self.sendDataArray = [[NSMutableArray alloc] init];
    56. //        self.mRecvPacket = [JHreceivePacket sharedManager];
    57. //        self.deviceListArr = [[NSMutableArray alloc] init];
    58. //        DLogInfo(@"初始化!");
    59. }
    60. return self;
    61. }
    62. #pragma mark - 🔥🔥🔥🔥🔥🔥🔥🔥
    63. #pragma mark --- 心跳计时器处理 -----
    64. /** 心跳计时器初始化 */
    65. - (void)initHeartBeat{
    66. //心跳没有被关闭
    67. if(self.heartBeatTimer)
    68. {
    69. return;
    70. }
    71. [self destoryHeartBeat];
    72. //连接成功  先发一次 心跳数据 在打开计时器
    73. //[[JHSocketData sharedManager] heartbeat];
    74. //判断是否打开
    75. if([xddTools keyGet:@"isOpenTCP"]&&[[xddTools keyGet:@"isOpenTCP"] isEqualToString:@"已打开"]){
    76. [self.asyncTcpSocket writeData:[@"MyiPhone" dataUsingEncoding:NSUTF8StringEncoding] withTimeout:30 tag:0];
    77. }
    78. WSELF
    79. Dispatch_main_async_safe(^{
    80. wself.heartBeatTimer = [NSTimer timerWithTimeInterval:30 target:wself selector:@selector(senderheartBeat) userInfo:nil repeats:true];
    81. [[NSRunLoop currentRunLoop]addTimer:wself.heartBeatTimer forMode:NSRunLoopCommonModes];
    82. });
    83. }
    84. #pragma mark --- 取消心跳 -----
    85. /** 取消心跳 */
    86. - (void)destoryHeartBeat
    87. {
    88. WSELF
    89. Dispatch_main_async_safe(^{
    90. if(wself.heartBeatTimer){
    91. [wself.heartBeatTimer invalidate];
    92. wself.heartBeatTimer =nil;
    93. }
    94. });
    95. }
    96. #pragma mark --- 没有网络的时候开始定时 -- 用于网络检测 -----
    97. /** 没有网络,进行网络监测 */
    98. - (void)noNetWorkStartTestingTimer{
    99. WSELF
    100. Dispatch_main_async_safe(^{
    101. wself.netWorkTestingTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:wself selector:@selector(noNetWorkStartTesting) userInfo:nil repeats:YES];
    102. [[NSRunLoop currentRunLoop] addTimer:wself.netWorkTestingTimer forMode:NSDefaultRunLoopMode];
    103. });
    104. }
    105. #pragma mark --- 取消网络监测 ----
    106. /** 取消网络监测 */
    107. - (void)destoryNetWorkStartTesting
    108. {
    109. WSELF
    110. Dispatch_main_async_safe(^{
    111. if(wself.netWorkTestingTimer){
    112. [wself.netWorkTestingTimer invalidate];
    113. wself.netWorkTestingTimer =nil;
    114. }
    115. });
    116. }
    117. #pragma mark - 🔥🔥🔥🔥🔥🔥🔥🔥
    118. #pragma mark --- 发送心跳 ---
    119. /** 发送心跳 */
    120. - (void)senderheartBeat{
    121. //  和服务端约定好发送什么作为心跳标识,尽可能的减小心跳包大小
    122. [self.asyncTcpSocket writeData:[@"ok" dataUsingEncoding:NSUTF8StringEncoding] withTimeout:30 tag:0];
    123. //    WSELF;
    124. //    Dispatch_main_async_safe(^{
    125. //
    126. //    });
    127. }
    128. #pragma mark --- 定时检查网络 ---
    129. /** 定时检查网络 */
    130. - (void)noNetWorkStartTesting{
    131. //有网络
    132. if(AFNetworkReachabilityManager.sharedManager.networkReachabilityStatus != AFNetworkReachabilityStatusNotReachable)
    133. {
    134. //关闭网络检测定时器
    135. [self destoryNetWorkStartTesting];
    136. //开始重连
    137. [self reConnectServer];
    138. }
    139. }
    140. #pragma mark - 🔥🔥🔥🔥🔥🔥🔥🔥
    141. #pragma mark ----建立连接------
    142. /**  建立连接 */
    143. -(void)connectServer{
    144. self.isActivelyClose = NO;
    145. NSError*error =nil;
    146. _asyncTcpSocket= [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    147. NSString* ip = [xddTools keyGet:@"TCP_IP"];
    148. NSString* port_str = [xddTools keyGet:@"TCP_Port"];
    149. if([ip isEqualToString:@""]){
    150. ip = @"192.168.1.2";
    151. [xddTools keySet:@"TCP_IP" v:ip];
    152. }
    153. if([port_str isEqualToString:@""]){
    154. port_str = @"12485";
    155. [xddTools keySet:@"TCP_Port" v:port_str];
    156. }
    157. UInt16 port = [port_str integerValue];
    158. //你的ip地址和端口号
    159. [_asyncTcpSocket connectToHost:ip onPort:port withTimeout:60 error:&error];
    160. if(error) {
    161. NSLog(@"TCP连接错误:%@", error);
    162. }
    163. [self.asyncTcpSocket readDataWithTimeout:-1 tag:0];
    164. }
    165. #pragma mark --- 重连服务器 ---
    166. /** 重连服务器 */
    167. - (void)reConnectServer{
    168. if (self.asyncTcpSocket.isConnected) {
    169. return;
    170. }
    171. if (self.reConnectTime > 10240) {
    172. self.reConnectTime = 0;
    173. return;
    174. }
    175. WSELF;
    176. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.reConnectTime *NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    177. if(wself.asyncTcpSocket.isConnected)
    178. {
    179. return;
    180. }
    181. [wself connectServer];
    182. NSLog(@"正在重连%f",wself.reConnectTime);
    183. if(wself.reConnectTime==0){ //重连时间2的指数级增长
    184. wself.reConnectTime=2;
    185. } else {
    186. wself.reConnectTime*=2;
    187. }
    188. });
    189. NSLog(@"重连服务器!");
    190. }
    191. #pragma mark ----关闭连接------
    192. /** 关闭连接 */
    193. - (void)disConnectServer {
    194. NSLog(@"dealloc");
    195. // 关闭套接字
    196. self.isActivelyClose = YES;
    197. [self.asyncTcpSocket disconnect];
    198. //关闭心跳定时器
    199. [self destoryHeartBeat];
    200. //关闭网络检测定时器
    201. [self destoryNetWorkStartTesting];
    202. self.asyncTcpSocket = nil;
    203. }
    204. #pragma mark ---代理 连接成功 ---
    205. //连接成功
    206. -(void)socket:(GCDAsyncSocket*)sock didConnectToHost:(NSString*)host port:(uint16_t)port
    207. {
    208. NSLog(@"TCP连接成功!");
    209. //    [self.asyncTcpSocket readDataWithTimeout:-1 tag:index];
    210. //      [self.asyncTcpSocket readDataWithTimeout:-1 tag:0];
    211. // 存储接收数据的缓存区,处理数据的粘包和断包
    212. self.readBuf = [[NSMutableData alloc]init];
    213. [self initHeartBeat]; //开启心跳
    214. //如果有尚未发送的数据,继续向服务端发送数据
    215. if([self.sendDataArray count] >0){
    216. [self sendeDataToServer];
    217. }
    218. }
    219. #pragma mark ---代理 连接失败 ---
    220. //连接失败 进行重连操作
    221. -(void)socketDidDisconnect:(GCDAsyncSocket*)sock withError:(NSError*)err{
    222. //用户主动断开连接,就不去进行重连
    223. if(self.isActivelyClose)
    224. {
    225. return;
    226. }
    227. [self destoryHeartBeat]; //断开连接时销毁心跳
    228. //判断网络环境
    229. if (AFNetworkReachabilityManager.sharedManager.networkReachabilityStatus == AFNetworkReachabilityStatusNotReachable) //没有网络
    230. {
    231. [self noNetWorkStartTestingTimer];//开启网络检测定时器
    232. }
    233. else//有网络
    234. {
    235. [self reConnectServer];//连接失败就重连
    236. }
    237. NSLog(@"TCP连接失败!");
    238. }
    239. #pragma mark --- 消息发送成功 ---
    240. -(void)socket:(GCDAsyncSocket*)sock didWriteDataWithTag:(long)tag{
    241. NSLog(@"TCP发送成功");
    242. }
    243. #pragma mark - 🔥🔥🔥🔥🔥🔥🔥🔥
    244. #pragma mark --- 发送数据 ---
    245. -(void)sendDataToServer:(id)data{
    246. [self.sendDataArray addObject:data];
    247. [self sendeDataToServer];
    248. //      [self.asyncTcpSocket  writeData:data withTimeout:60 tag:0];
    249. }
    250. #pragma mark --- 发送数据给服务器 详细处理 ---
    251. /** 发送数据的详细处理 */
    252. -(void)sendeDataToServer{
    253. WSELF
    254. //把数据放到一个请求队列中
    255. dispatch_async(self.queue, ^{
    256. //网络判断  没有网络的情况
    257. if (AFNetworkReachabilityManager.sharedManager.networkReachabilityStatus == AFNetworkReachabilityStatusNotReachable) {
    258. //开启网络检测定时器
    259. [wself noNetWorkStartTestingTimer];
    260. }else{ //有网络情况
    261. //判断对象是否存在
    262. if(wself.asyncTcpSocket != nil) {
    263. //判断TCP是否处于连接状态
    264. if(wself.asyncTcpSocket.isConnected) {
    265. //判断数据  是否存在
    266. if(wself.sendDataArray.count>0) {
    267. id sendData = wself.sendDataArray[0];
    268. NSLog(@"TCP发送出去的数据: %@",sendData);
    269. [self.asyncTcpSocket writeData:sendData withTimeout:30 tag:0];
    270. [wself.sendDataArray removeObjectAtIndex:0];
    271. if([wself.sendDataArray count] >0){
    272. [wself sendeDataToServer];
    273. }
    274. }
    275. }else{
    276. //TCP 处于断开状态
    277. //主动去重连服务器  连接成功后 继续发送数据
    278. [wself reConnectServer];
    279. }
    280. }else{
    281. [wself reConnectServer];
    282. }
    283. }
    284. });
    285. }
    286. #pragma mark - 🔥🔥🔥🔥🔥🔥🔥🔥
    287. #pragma mark --- 接收的数据 ---
    288. -(void)socket:(GCDAsyncSocket*)sock didReadData:(NSData*)data withTag:(long)tag
    289. {
    290. //      sleep(1);
    291. //此方法处理数据的黏包或者断包
    292. NSLog(@"原始数据%@",data);
    293. NSString*msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    294. NSLog(@"xdd接收的数据 = %@",msg);
    295. //断包处理
    296. [self didReadData:data];
    297. [self.asyncTcpSocket readDataWithTimeout:-1 tag:0];
    298. NSDictionary*retDic = [xddTools dictionaryWithJsonString:msg];
    299. if(retDic == nil || ! [retDic isKindOfClass:[NSDictionary class]]) {
    300. return ;
    301. }
    302. NSString*type_ = retDic[@"type"];
    303. NSString*data_ = retDic[@"data"];
    304. NSString*msgid_ = retDic[@"msgid"]?retDic[@"msgid"]:@"test";
    305. NSLog(@"xdd接收的数据type_=%@,type_=%@",type_,data_);
    306. //开始主线程
    307. // dispatch_async(dispatch_get_main_queue(), ^{
    308. //开始子线程
    309. dispatch_async(dispatch_get_global_queue(0, 0), ^{
    310. if(type_ && data_ && [type_ isEqualToString:@"1"]){
    311. //获取森林信息
    312. NSDictionary*dic = [xddTools getMYinfo:data_];
    313. BOOL success = [dic[@"success"] boolValue]; //是否成功
    314. NSString*resultDesc = dic[@"resultDesc"];//信息提示
    315. NSString*resultCode = dic[@"resultCode"];//返回代码
    316. NSString*currentEnergy = dic[@"treeEnergy"][@"currentEnergy"];//当前能量
    317. NSDictionary*userEnergy = dic[@"userEnergy"];
    318. NSString*loginId = userEnergy[@"loginId"];//3333@qq.com
    319. NSString*userId = userEnergy[@"userId"];//2088*****
    320. NSString*headPortrait = userEnergy[@"headPortrait"];//头像
    321. NSString*displayName = userEnergy[@"displayName"];//昵称 茶
    322. NSString*energySummation = userEnergy[@"energySummation"];//合计能量
    323. NSString*treeAmount = userEnergy[@"treeAmount"];//证书个数
    324. NSDictionary *dicRetInfo = [NSDictionary dictionaryWithObjectsAndKeys:
    325. msgid_,@"msgid"
    326. ,type_,@"type"
    327. ,resultCode,@"code"
    328. ,currentEnergy,@"current"
    329. ,energySummation,@"summation"
    330. ,userId,@"userId"
    331. ,loginId,@"loginId"
    332. ,headPortrait,@"png"
    333. ,treeAmount,@"tree"
    334. ,displayName,@"name"
    335. ,nil];
    336. NSData * jsonData = [[xddTools returnJSONStringWithDictionary:dicRetInfo] dataUsingEncoding:NSUTF8StringEncoding];
    337. //NSData * jsonData = [NSJSONSerialization dataWithJSONObject:dicRetInfo options:NSJSONWritingPrettyPrinted error:nil];
    338. [self sendDataToServer:jsonData];
    339. }else if(type_ && data_ && ( [type_ isEqualToString:@"2"] || [type_ isEqualToString:@"4"])){
    340. NSDictionary*dic;
    341. if([type_ isEqualToString:@"2"]){
    342. // 查询用户手机 昵称信息
    343. dic = [xddTools getiPhoneInfo:data_];
    344. }else if([type_ isEqualToString:@"4"]){
    345. // 查询用户ID昵称信息
    346. dic = [xddTools getuseriDInfo:data_];
    347. }
    348. NSString*account = dic[@"userAccount"];
    349. NSString*userID = dic[@"userID"];
    350. NSString*nickl = dic[@"userNicklName"];
    351. NSString*name = dic[@"userName"];
    352. NSString*status = dic[@"resultStatus"];
    353. NSString*Suffix = dic[@"userNameSuffix"];
    354. NSString*RealName = dic[@"userRealName"];
    355. NSString*gender = dic[@"gender"];
    356. //userNameSuffix 实名名字
    357. //userRealName 注册名字
    358. //gender 性别
    359. NSDictionary *dicRetInfo = [NSDictionary dictionaryWithObjectsAndKeys:
    360. msgid_,@"msgid"
    361. ,type_,@"type"
    362. ,status,@"status"
    363. ,account,@"account"
    364. ,userID,@"userID"
    365. ,nickl,@"nickl"
    366. ,name,@"name"
    367. ,Suffix,@"Suffix"
    368. ,RealName,@"RealName"
    369. ,gender,@"gender"
    370. ,nil];
    371. //625 对方账户存在异常,不能进行当前操作 100 ok
    372. NSData * jsonData = [[xddTools returnJSONStringWithDictionary:dicRetInfo] dataUsingEncoding:NSUTF8StringEncoding];
    373. //NSData * jsonData = [NSJSONSerialization dataWithJSONObject:dicRetInfo options:NSJSONWritingPrettyPrinted error:nil];
    374. [self sendDataToServer:jsonData];
    375. }else if(type_ && data_ && [type_ isEqualToString:@"3"]){
    376. //获取合种二维码信息
    377. NSDictionary*dic = [xddTools gethezhongqrCode:data_];
    378. // BOOL success = [dic[@"success"] boolValue]; //是否成功
    379. // NSString*resultDesc = dic[@"resultDesc"];//信息提示
    380. // NSString*resultCode = dic[@"resultCode"];//返回代码
    381. // 可变字典 转可变字典
    382. NSMutableDictionary *dict002 = [NSMutableDictionary dictionaryWithDictionary:dic];
    383. [dict002 setObject:msgid_ forKey:@"msgid"];
    384. [dict002 setObject:type_ forKey:@"type"];
    385. [dict002 removeObjectForKey:@"extInfo"];
    386. // NSData * jsonData = [[xddTools returnJSONStringWithDictionary:dict002] dataUsingEncoding:NSUTF8StringEncoding];
    387. NSData * jsonData = [NSJSONSerialization dataWithJSONObject:dict002 options:NSJSONWritingPrettyPrinted error:nil];
    388. [self sendDataToServer:jsonData];
    389. }
    390. else if(type_ && data_ && [type_ isEqualToString:@"5"]){
    391. //获取签名
    392. NSDictionary*dic = [xddTools getAlipaysign:retDic];
    393. NSMutableDictionary *dict002 = [NSMutableDictionary dictionaryWithDictionary:dic];
    394. [dict002 setObject:msgid_ forKey:@"msgid"];
    395. [dict002 setObject:type_ forKey:@"type"];
    396. NSData * jsonData = [[xddTools returnJSONStringWithDictionary:dict002] dataUsingEncoding:NSUTF8StringEncoding];
    397. [self sendDataToServer:jsonData];
    398. }
    399. else if(type_ && data_ && [type_ isEqualToString:@"6"]){
    400. //获取签名
    401. NSDictionary*dic = [xddTools getAlipaysignV1:retDic];
    402. NSMutableDictionary *dict002 = [NSMutableDictionary dictionaryWithDictionary:dic];
    403. [dict002 setObject:msgid_ forKey:@"msgid"];
    404. [dict002 setObject:type_ forKey:@"type"];
    405. NSData * jsonData = [[xddTools returnJSONStringWithDictionary:dict002] dataUsingEncoding:NSUTF8StringEncoding];
    406. [self sendDataToServer:jsonData];
    407. }
    408. else if(type_ && data_ && [type_ isEqualToString:@"xxx"]){
    409. }
    410. });
    411. }
    412. #pragma mark - 🔥🔥🔥🔥🔥🔥🔥🔥
    413. #pragma mark --- 黏包 断包处理 ---
    414. -(void) didReadData:(NSData*)data {
    415. //断包处理 要根据 你的 数据的 长度标识位的数据 来判断 读到什么地方 才是你完整的数据。根据协议去走
    416. _readBuf = [NSMutableData dataWithData:data];
    417. // 取出4-8位保存的数据长度,计算数据包长度
    418. while(_readBuf.length>=5) {// 头数据为5个字节
    419. // 得到数据的ID 和 整个数据的长度
    420. NSData *dataLength = [_readBuf subdataWithRange:NSMakeRange(3, 2)];
    421. Byte*ByteLength = (Byte*)[dataLength bytes];
    422. int headLen = (ByteLength[0] &0x00ff) + ((ByteLength[1] &0x00ff) <<8);
    423. NSInteger lengthInteger =0;
    424. lengthInteger = (NSInteger)headLen;
    425. NSInteger complateDataLength = lengthInteger +6;//算出一个包完整的长度(内容长度+头长度)
    426. NSLog(@"已读取数据:缓冲区长度:%ld, 接收长度:%lu  数据长度:%ld ", (long)_readBuf.length, (unsigned long)[data length], (long)complateDataLength);
    427. //        NSInteger dataLength = length + 2;
    428. if(_readBuf.length>= complateDataLength) {//如果缓存中的数据 够  一个整包的长度
    429. NSData*msgData = [_readBuf subdataWithRange:NSMakeRange(0, complateDataLength)];
    430. // 处理消息数据
    431. NSLog(@"得到完整包数据:%@",msgData);
    432. // 从缓存中截掉处理完的数据,继续循环
    433. _readBuf= [NSMutableData dataWithData:[_readBuf subdataWithRange:NSMakeRange(complateDataLength,_readBuf.length- complateDataLength)]];
    434. //            [self.asyncTcpSocket readDataWithTimeout:-1 tag:0];
    435. }else{// 断包情况,继续读取
    436. //            [self.asyncTcpSocket readDataWithTimeout:-1 tag:0];
    437. // [sock readDataWithTimeout:-1 buffer:_readBuf bufferOffset:_readBuf.length tag:0];//继续读取数据
    438. [self.asyncTcpSocket readDataWithTimeout:-1 buffer:_readBuf bufferOffset:_readBuf.length tag:0];
    439. return;
    440. }
    441. [self.asyncTcpSocket readDataWithTimeout:-1 buffer:_readBuf bufferOffset:_readBuf.length tag:0];//继续读取数据
    442. }
    443. }
    444. @end
    1. //
    2. // Xddtcp.h
    3. // YFX_ScoketForClientDemo
    4. //
    5. // Created by adminxdd on 2020/8/20.
    6. // Copyright © 2020 fangxue. All rights reserved.
    7. //
    8. #import
    9. #import "AFNetworkReachabilityManager.h"
    10. NS_ASSUME_NONNULL_BEGIN
    11. NS_ASSUME_NONNULL_END
    12. #import
    13. #import "GCDAsyncSocket.h"
    14. #import "xddTools.h"
    15. //@interface SingleTcpCase :NSObject
    16. @interface Xddtcp : NSObject
    17. @property(strong,nonatomic)GCDAsyncSocket *asyncTcpSocket;
    18. /**  单利初始化 */
    19. +(instancetype)sharedTcpManager;
    20. /**  建立连接 */
    21. -(void)connectServer;
    22. /**  关闭连接 */
    23. -(void)disConnectServer;
    24. /**  发送数据给服务器 */
    25. -(void)sendDataToServer:(id)data;
    26. @end

    配置端口

    1. UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"请输入配置信息" message:@"++++++" preferredStyle:UIAlertControllerStyleAlert];
    2. //增加取消按钮;
    3. [alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
    4. //增加确定按钮;
    5. [alertController addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
    6. //获取第1个输入框;
    7. UITextField *userNameTextField = alertController.textFields.firstObject;
    8. //获取第2个输入框;
    9. UITextField *passwordTextField = alertController.textFields.lastObject;
    10. //NSLog(@"用户名 = %@,密码 = %@",userNameTextField.text,passwordTextField.text);
    11. if(userNameTextField.text && ![userNameTextField.text isEqualToString:@""]){
    12. [xddTools keySet:@"TCP_IP" v:userNameTextField.text];
    13. }
    14. if(passwordTextField.text && ![passwordTextField.text isEqualToString:@""]){
    15. [xddTools keySet:@"TCP_Port" v:passwordTextField.text];
    16. }
    17. }]];
    18. //定义第一个输入框;
    19. [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
    20. textField.placeholder = @"请输入配置IP";
    21. textField.text = [xddTools keyGet:@"TCP_IP"];
    22. }];
    23. //定义第二个输入框;
    24. [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
    25. textField.placeholder = @"请输入配置端口";
    26. textField.text = [xddTools keyGet:@"TCP_Port"];
    27. }];
    28. [weakSelf presentViewController:alertController animated:true completion:nil];
    1. +(NSString*)keyGet:(NSString*)k
    2. {
    3. NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
    4. return [userDefault objectForKey:k]?[userDefault objectForKey:k]:@"";
    5. // - objectForKey:
    6. // - URLForKey:
    7. // - arrayForKey:
    8. // - dictionaryForKey:
    9. // - stringForKey:
    10. // - stringArrayForKey:
    11. // - dataForKey:
    12. // - boolForKey:
    13. // - integerForKey:
    14. // - floatForKey:
    15. // - doubleForKey:
    16. // - dictionaryRepresentation
    17. }
    18. +(void)keySet:(NSString*)k v:(NSString*)v
    19. {
    20. NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
    21. [userDefault setObject:v forKey:k];
    22. [userDefault synchronize];
    23. // - setObject:forKey:
    24. // - setFloat:forKey:
    25. // - setDouble:forKey:
    26. // - setInteger:forKey:
    27. // - setBool:forKey:
    28. // - setURL:forKey:
    29. }

  • 相关阅读:
    arm实验
    个人所得税赡养老人书面分摊协议
    Qt Creator实例之图标主题
    大型网站技术架构核心原理与案例分析学习笔记(理论篇)
    ICML 2020 | GCNII:简单和深度图卷积网络
    项目管理与SSM框架(二)| Spring
    EFLAGS寄存器与JCC指令
    基于C语言实现的PA4实验报告
    空域时域和频域的区别
    vr飞机驾驶舱模拟流程3D仿真演示加大航飞安全法码
  • 原文地址:https://blog.csdn.net/qq_21051503/article/details/133308094