IOS开发笔记(二)—— UI编程,网络访问,本地存储

中山大学数据科学与计算机学院本科生实验报告

(2019年春季学期)

课程名称 IOS开发 任课老师 郑贵锋
年级 16 专业(方向) 软件工程(计算机应用方向)
学号 16340132 姓名 梁颖霖
电话 13680473185 Email [email protected]
开始日期 2019/3/25 完成日期 2019/3/27

一、实验题目

IOS UI编程

IOS 网络访问

IOS 本地存储


二、实现内容

  • 认识UI控件
  • iOS绘图
  • UITableView介绍
  • UIViewController介绍
  • 上机练习《文件浏览器》
  • 网络访问
  • 本地存储

三、实验结果

a. UI控件

1.文本框——UILabel

  • 通过text属性等修改文字内容。
  • 还可以调节不同的字体大小,颜色。类比Android中的TextView

2.静态图——UIImageView

  • 导入外部的图片资源
  • 调整图片的加载方式,完全填充还是等比例填充。类比Android中的ImageView

3.动态图——UIImageView

  • 与静态图不同点在于加入了animation动画这一属性

4.按键——UIButton

  • 设置文本,颜色,背景
  • 添加点击事件 addTarget。类比Android中的Button

5.切换按钮——UISwitch

6.单行输入框——UITextField

  • 调整提示,输入文本大小,键盘类型
  • 类比Android中的EditText

7.多行输入框——UITextView

  • 是否允许滚动

b. UITableView介绍

UITableView是一个列表控件,广泛运用于App的各个界面。

两种风格

  • UITableViewStylePlain
  • UITableViewStyleGrouped

结构包括(见图)

IOS开发笔记(二)—— UI编程,网络访问,本地存储

  • TableHeader(绿色区域)
  • Section 分组
    • Header 头部
    • Row 行内容
    • Footer 尾部
  • Section 分组
    • Header
    • Row 行内容
    • Footer
  • TableFooter (蓝色区域)

步骤:

  • 创建一个tableview对象
    • 这里还可以通过UITableViewCell来调整列表的样式,例如显示图片+文字
  • 设置dataSource,负责数据源提供和编辑相关改变
  • 设置delegate,负责布局相关和交互行为

c. UIViewController介绍

ViewController是iOS应用程序中重要的部分,是应用程序数据和视图之间的重要桥梁,ViewController管理应用中的众多视图。

  • 代码创建

    UIViewController *controller = [[UIViewController alloc] init];
    
  • StoryBoard创建

利用StoryBoard还可以创建TabBar,可以直接用拖动操作

d.利用NSURLSession进行网络访问

注意点:要打开IOS9 的HTPP请求限制,不然会出现访问出错的情况

Get请求

发起一个Get请求需要以下几个步骤

  • 构建Request对象。
  • 创建Session。
  • 创建NSURLSessionDataTask。
  • 执⾏Task
  • Response处理。
-(void) sendHTTPGet
{
    NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
    
    // 创建Session。
    NSURLSession *delegateFreeSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];
    
    NSURL * url = [NSURL URLWithString:@"http://127.0.0.1:18081/user?id=1"];
	// 构建Request对象。
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    // 创建NSURLSessionDataTask。
    NSURLSessionDataTask * dataTask = [delegateFreeSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        // 执⾏Task
        if(error == nil)
        {
            NSString * text = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
            NSLog(@"Data = %@",text);
        }
        
    }];
    
    [dataTask resume];
}

Post请求

发起一个Post请求需要以下几个步骤

  • 构建可变的Request对象。
  • 设置请求⽅法为POST,设置请求体数据
  • 创建Session。
  • 创建NSURLSessionDataTask。
  • 执⾏Task
  • Response处理。
-(void) sendHTTPPost
{
    NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
    // 创建Session。
    NSURLSession *delegateFreeSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];

    NSURL * url = [NSURL URLWithString:@"http://127.0.0.1:18081/edit"];
    // 构建可变的Request对象。
    NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:url];
    NSString * params =@"id=1&name=Test&age=50";
    // 设置请求⽅法为POST,设置请求体数据。
    [urlRequest setHTTPMethod:@"POST"];
    [urlRequest setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];
    // 执⾏Task
    NSURLSessionDataTask * dataTask = [delegateFreeSession dataTaskWithRequest:urlRequest];
    [dataTask resume];
    
}

下载文件

  • 构建Request对象。
  • 创建Session。
  • 创建NSURLSessionDownloadTask。
  • 执⾏Task
  • Response处理。

这与get请求类似,只不过这里创建的是NSURLSessionDownloadTask,要稍微注意下其中的参数设置

-(void)downloadFile
{
	// 设置url
    NSURL * url = [NSURL URLWithString:@"http://127.0.0.1:18081/download/test.txt"];
    // 创建Session。
    NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject
                                                                 delegate:self
                                                            delegateQueue: [NSOperationQueue mainQueue]];
    // 创建NSURLSessionDownloadTask。
    NSURLSessionDownloadTask * downloadTask =[ defaultSession downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error)
	  {
	  	  // 处理Response
	      if(error == nil)
	      {
	          NSLog(@"Temporary file =%@",location);

	          NSError *err = nil;
	          NSFileManager *fileManager = [NSFileManager defaultManager];
	          NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];


	          NSURL *docsDirURL = [NSURL fileURLWithPath:[docsDir stringByAppendingPathComponent:@"out.zip"]];
	          if ([fileManager moveItemAtURL:location
	                                   toURL:docsDirURL
	                                   error: &err])
	          {
	              NSLog(@"File is saved to =%@",docsDir);
	          }
	          else
	          {
	              NSLog(@"failed to move: %@",[err userInfo]);
	          }
	      }
	  }];
    [downloadTask resume];
}

这节课还提到了一个轻量级⽹络请求开源框架AFNetworking,使用这个框架提供的API可以轻松的进行网络访问,这里先记住这个框架,在初始的学习的阶段还是先用原生的练练手,熟悉后再去学习这个框架的使用

e. 本地存储

IOS 沙盒:每⼀个App都有⼀个存储空间。iOS系统为每个应⽤程序创建⾃⼰的⽬录,每个应⽤程序只能访问⾃⼰的⽬录,不能相互通。

目录结构如下所示:

  • Documents: 保存应⽤运⾏时⽣成的需要持久化的数据,iTunes会⾃动备份该⽬录。苹果建议将在应⽤程序中浏览到的⽂件数据保存在该⽬录下。
  • Library:
  • Caches:⼀般存储的是缓存⽂件,例如图⽚视频等,此⽬录下的⽂件不会再应⽤程序退出时删除。在⼿机备份的时候,iTunes不会备份该⽬录。例如⾳频,视频等⽂件存放其中
  • Preferences:保存应⽤程序的所有偏好设置iOS的Settings(设置),我们不应该直接在这创建⽂件,⽽是需要通过NSUserDefault这个类来访问应⽤程序的偏好设置。iTunes会⾃动备份该⽂件⽬录下的内容。⽐如说:是否允许访问图⽚,是否允许访问地理位置…
  • tmp:临时⽂件⽬录,在程序重新运⾏的时候,和开机的时候,会清空tmp⽂件夹。

获取目录的代码

- (void)viewDidLoad {
    [super viewDidLoad];

    // 获取document目录
    NSArray *documentPaths = NSSearchPathForDirectoriesInDomains
        (NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentPath = [documentPaths objectAtIndex:0];

    // 获取Cache目录
    NSArray *cachePaths = NSSearchPathForDirectoriesInDomains
        (NSCachesDirectory, NSUserDomainMask, YES);
    NSString *cachePath = [cachePaths objectAtIndex:0];

    // 获取Library目录
    NSArray *libraryPaths = NSSearchPathForDirectoriesInDomains
        (NSLibraryDirectory, NSUserDomainMask, YES);
    NSString *libraryPath = [libraryPaths objectAtIndex:0];

    // 获取Tmp目录
    NSString *tmpPath = NSTemporaryDirectory();

    _label.text = [NSString stringWithFormat:@"Document: %@\nCache: %@\nLibrary: %@\nTmp: %@", documentPath, cachePath, libraryPath, tmpPath];
}

文件操作

文件操作这里要用到NSFileManager这个类

首先要创建fileManager对象,并且判断文件是否存在

// 判断文件是否存在
NSFileManager *fileManager = [NSFileManager defaultManager];

NSString *document = NSSearchPathForDirectoriesInDomains
    (NSDocumentDirectory, NSUserDomainMask, YES).firstObject;

NSString *filePath = [document stringByAppendingPathComponent:@"test.txt"];

if ([fileManager fileExistsAtPath:filePath]) {
    NSLog(@"test.txt exists");
}

BOOL isDirectory;
if ([fileManager fileExistsAtPath:filePath isDirectory:&isDirectory]) {

}

创建目录

// 创建目录
NSString *testDir = [document stringByAppendingPathComponent:@"test"];
// 存放创建失败的错误,方便后面来进行判断操作
NSError *error;

[fileManager createDirectoryAtPath:testDir withIntermediateDirectories:YES attributes:nil error:&error];

创建文件

// 创建文件
NSString *testTxt = [testDir stringByAppendingPathComponent:@"test.txt"];
NSData *data = [@"Hello world!" dataUsingEncoding:NSUTF8StringEncoding];
[fileManager createFileAtPath:testTxt contents:data attributes:nil];

删除文件

// 删除文件
[fileManager removeItemAtPath:testTxt error:nil];

文件读写

写文件

- (IBAction)write:(id)sender {
    // 文件父目录
    NSString *document = NSSearchPathForDirectoriesInDomains
        (NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
	// 文件目录
    NSString *filePath = [document stringByAppendingPathComponent:@"text.txt"];
	// 写入的内容
    NSString *contents = @"Hello world!";
    // 调用writeToFile
    [contents writeToFile:filePath atomically:YES 
     encoding:NSUTF8StringEncoding error:nil];
}

读文件

- (IBAction)read:(id)sender {
    // 文件父目录
    NSString *document = NSSearchPathForDirectoriesInDomains
        (NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
	// 文件目录
    NSString *filePath = [document 
                          stringByAppendingPathComponent:@"text.txt"];
	// 将文件内容读入字符串
    NSString *content = [NSString stringWithContentsOfFile:filePath 
                         encoding:NSUTF8StringEncoding error:nil];
    
    NSLog(@"content %@", content);
}

NSUserDefaults

  • NSUserDefaults⽤来存储 ⽤户设置 系统配置等⼀些⼩的数据。
    • 因为数据是明⽂存储在 plist ⽂件中,不安全,即使只是修改⼀个 key 都会 load 整个⽂件,数据多加载慢(IO 内存),不适合存储⼤量数据。
    • 它是单例的,也是线程安全的,是以键值对 key-value 的形式保存在沙盒中
    • 存储路径为:沙盒路径的Library——>Preferences⽂件夹中
  • ⽀持的数据类型有NSString、 NSNumber、NSDate、 NSArray、NSDictionary、BOOL、
    NSInteger、NSFloat等系统定义的数据类型,如果要存放其他数据类型或者⾃定义的对象
    (如⾃定义的类对象),则必须将其转换成NSData存储。
    • 即使对象是NSArray或NSDictionary,他们存储的类型也应该是以上范围包括的

读取代码

// read
NSInteger x = [[NSUserDefaults standardUserDefaults] 
               integerForKey:@"x"];
NSString *name = [[NSUserDefaults standardUserDefaults] 
                  stringForKey:@"name"];
NSDictionary *dict = [[NSUserDefaults standardUserDefaults] 
                      objectForKey:@"button"];
data = [[NSUserDefaults standardUserDefaults] dataForKey:@"user"];
user = [NSKeyedUnarchiver unarchivedObjectOfClass:[User class] 
        fromData:data error:nil];

写入代码

// save
[[NSUserDefaults standardUserDefaults] setInteger:1024 forKey:@"x"];
[[NSUserDefaults standardUserDefaults] setObject:@"Tom" forKey:@"name"];
[[NSUserDefaults standardUserDefaults] setObject:@{
    @"text": @"Cancel",
    @"color": @"#ff0000",
} forKey:@"button"];

User *user = [[User alloc] init];
user.userId = 123;
user.nickname = @"Tom";
user.isVip = YES;

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:user requiringSecureCoding:YES error:nil];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"user"];