端到端的机会
虽然现在身处大公司,但是因为是内部创业团队,产品、native、前端、服务器端全部坐在一起开发,大家很容易做零距离交流,也因为最近内部有一个前端要转岗过来,于是手里的前端任务好像可以抛一大坨出去了,这个时候立刻想到了切入IOS开发!!!
事实上,前端开发做到一定时间,要进步很难了,最近几个月扑到业务上便感觉突破不了目前的瓶颈,自身的前端瓶颈主要在两方面:技术深度、技术广度
其实不论深度或者广度来说都不是简单前端能说清楚的事情,不能说了解了angularJS、react等框架技术深度就深了,因为事实上angular中包含了很多设计思想,学习他是编程思想的提升,并不单是js功力的提升。
要说自身职业规划,前端当然可以往nodeJS发展走大前端方向,但是这个真的需要项目支持,多次尝试自学nodeJS皆收效甚微,便是因为没有实际项目支持,说白了没有人带着做项目。
而团队内部有人带着做IOS开发,我居然可以从零开始自学然后参与生产项目开发,想想真的令人兴奋!!!
但是天下没有不要钱的午餐,切入IOS开发的前提是保证现有H5任务的工期以及质量,所以加班什么的在所难免,可是我怎么可能放弃这种千载难逢的好事呢?于是立马给技术老大说了愿意多承担工作的意愿,老大也很nice的答应我可以切入IOS开发,于是这一切便如此美好的开始了!所以接下来一段时间只需要fighting就够了!!!
感谢慕课网的入门教程,同样感谢网上诸多资料,特别是该园友博客:http://www.cnblogs.com/kenshincui/
如何学习新语言
今时不同往日,已经不可能有太多的空闲时间给我学习了,刚开始也想过应该系统的学习,一章一章的巩固知识,但是这样效率太低,等我学完都猴年马月了,项目早结束了
所以现在适合我的学习方法是做简单并且熟悉多项目,比如大一的C语言考试,学生管理系统
需求说明
简单设计一个学生管理系统,要求具有以下功能:
1 可以录入学生姓名,性别、课程等信息
2 可以给各门课程录入考试成绩
3 支持姓名排序,班级排序,成绩排序
因为最初做项目是为了熟悉语言,所以不需要太复杂,于是我们便开始吧!!!
学生类的设计
你要开发IOS程序,首先得有一台Mac机,其次需要安装xcode开发工具,我反正是去借了一台,然后让同事考了一个最新版的xcode,于是开始开发吧。
OC中的类
OC中的类皆继承至NSObject类,会带有一些特有并且经常会用到的方法,具体细节我们不去纠结,直接创建类吧
新建一个类会形成两个文件:file.h头文件与file.m为类的具体实现文件,我们这里新建一个Student类:
1 #import <Foundation/Foundation.h>
2
3 @interface Student : NSObject
4
5 @end
#import "Student.h" @implementation Student @end
我们这里不去吐槽OC的怪异语法,因为我们如果得去学习一个东西,就不要吐槽他,这样会分散你的注意力并且会让学习难以继续,所以回到正题
属性
OC的属性定义在头文件中,以学生来说我们规定其有以下属性,其中课程真实场景会被抽象为一个类,所以我们也这样做吧,新建Course类,并且给学生的属性如下:
1 #import <Foundation/Foundation.h>
2 #import "Course.h"
3
4 @interface Student : NSObject
5 {
6 NSString *_name;
7 int _age;
8 NSString *_sex;
9 Course *_chinese;
10 Course *_math;
11 //录入时间
12 NSDate *_dateCreate;
13 }
14 @end
课程类只具有名字与得分两个属性:
1 #import <Foundation/Foundation.h>
2
3 @interface Course : NSObject
4 {
5 NSString *_name;
6 float _score;
7 }
8 @end
其中下划线定写法为OC的规则,我们不需要知道他为什么要这样做,先做再说,后面熟悉了自然就知道了,与C#一样,属性会有getter与setter方法,OC这里提供了语法糖,我们暂不使用,老老实实的写代码,下面为两个类的具体实现:
构造函数
构造函数是每个类实例化的入口点,每一个继承至NSObject的对象都会有一个init的实例方法,这个便是其构造函数,我们这里自定义构造函数,Course与Student的构造函数
1 #import <Foundation/Foundation.h>
2 #import "Student.h"
3 #import "Course.h"
4
5 int main(int argc, const char * argv[]) {
6 @autoreleasepool {
7
8 //alloc方法创建实例空间,init初始化
9 Course *c = [[Course alloc] initWithName:@"叶小钗" andScore:90];
10
11 NSLog(@"%@, %f", c.name, c.score);
12
13 }
14 return 0;
15 }
成功打印出我们想要的代码,所以这个时候再将Student类的构造方法加上,并且给Student释放一个对外实例方法:showData
1 #import <Foundation/Foundation.h>
2 #import "Student.h"
3 #import "Course.h"
4
5 int main(int argc, const char * argv[]) {
6 @autoreleasepool {
7
8 //alloc方法创建实例空间,init初始化
9 Course *chinese = [[Course alloc] initWithName:@"语文" andScore:90];
10 Course *math = [[Course alloc] initWithName:@"数学" andScore:95];
11
12 Student *s = [[Student alloc] initWithName:@"叶小钗" andAge:27 andSex:@"男" andChinese:chinese andMath:math];
13
14 [s showData];
15
16 }
17 return 0;
18 }
2015-08-06 23:42:24.853 student[3394:246243] 姓名:叶小钗
2015-08-06 23:42:24.854 student[3394:246243] 性别:男
2015-08-06 23:42:24.854 student[3394:246243] 年龄:27
2015-08-06 23:42:24.855 student[3394:246243] 课程名:语文
2015-08-06 23:42:24.855 student[3394:246243] 课程得分:90.000000
2015-08-06 23:42:24.855 student[3394:246243] 课程名:数学
2015-08-06 23:42:24.855 student[3394:246243] 课程得分:95.000000
Program ended with exit code: 0
基本数据类型
显然,学生不只一个,我们需要一个集合来装载所有的学生,对于没有OC经验的我第一时间想到了数组,所以我们首先来简单了解下OC中的数组
OC的数组
数组属于集合大家族中的一类,简单来说有数组和字典,NSArray NSDictionary
NSArray
NSArray是一个Cocoa类,用来存储对象的有序列表,我们可以在NSArray中放入任意类型的对象:字符串、对象,基本类型等。
NSArray有两个限制,首先是只能存储OC类型的对象,同时不要在里面存储nil(对应其它语言中的NULL),我们可以使用类方法arrayWithObjects创建一个数组对象,比如:
//nil代表数组结束
NSArray *array = [NSArray arrayWithObjects:@"叶小钗", , math, nil]; //或者这样,注意这里会报错,因为NSArray只能保存对象,但23却是基本类型
//前面能处理是因为内部发生了装箱拆箱的过程
//NSArray *array2 = @[@"叶小钗", 23, math];
NSNumber *num1 = [[NSNumber alloc] initWithInt:];
NSArray *array2 = @[@"叶小钗", num1, math]; NSLog(@"%d", array[]);
NSLog(@"%d", [array2[] intValue]);
下面是数组的一些其它操作:
PS:这里插一根nslog相关的类型映射
%@ 对象
%d, %i 整数
%u 无符整形
%f 浮点/双字
%x, %X 二进制整数
%o 八进制整数
%zu size_t
%p 指针
%e 浮点/双字 (科学计算)
%g 浮点/双字
%s C 字符串
%.*s Pascal字符串
%c 字符
%C unichar
%lld 64位长整数(long long)
%llu 无符64位长整数
%Lf 64位双字
18 %i 布尔型
//nil代表数组结束
NSArray *array = [NSArray arrayWithObjects:@"叶小钗", @"", @"ddd", @"dd11", nil]; //数组遍历
//array count求得数组长度
for (int i = ; i < [array count]; i++) {
NSLog(@"%@", array[i]);
} //更好的遍历方式
for(id item in array){
NSLog(@"%@", item);
} //判断是否包含某个对象=>1
NSLog(@"%i", [array containsObject:@""]);
//判断是否包含某个对象=>0
NSLog(@"%i", [array containsObject:@"叶小钗"]); //返回第一个找到对象的索引=>2
NSLog(@"%d", [array indexOfObject:@"ddd"]); //简单排序语法糖,很实用,后面会使用这里不详说
NSArray *array1 = [array sortedArrayUsingSelector:@selector(compare:)]; for(id item in array1){
NSLog(@"%@", item);
}
这里排序后面会有更多的应用
NSMutableArray 可变数组
与NSSting一致,NSArray创建的是不可变数组,一旦创建包含特定数量的数组便不能再增减,为了弥补NSArray的不足,便有了NSMutabeArray类,通过arrayWithCapacity来创建可变数组,这里以一例子做说明:
//创建空数组
NSMutableArray *array = [[NSMutableArray alloc] init]; //插入5个数字,这里发生了装箱
for (int i = ; i < ; i++) {
NSNumber *n = [NSNumber numberWithInt:i];
[array addObject:n];
} //打印当前长度
NSLog(@"%d", [array count]); //在第二个元素后插入程咬金
[array insertObject:@"程咬金" atIndex:]; //删除第一个元素
[array removeObjectAtIndex:]; NSString *s =[array componentsJoinedByString:@"|"]; //输出字符串,|隔开
NSLog(@"%@", s); //字符串转回来
NSArray *a = [s componentsSeparatedByString:@""]; for(id item in array){
NSLog(@"%@", item);
} for(id item in a){
NSLog(@"%@", item);
}
前面简单介绍了OC中的数组,我们继续回到我们本来的需求
字符串
后面会用到字符串相关的知识点,我们这里顺便说一下OC的字符串,事实上NSString是一个类,所以我们实例化的时候是指针引用,字符串的实例化不是我们关注的重点,这次的重点放在,字符串的比较与操作,这个是我们后面项目会遇到的。
字符串长度
length可以返回字符串长度
NSString *s = @"sdsdsdds";
NSLog(@"%d", [s length]);//=>8
字符串比较
字符串比较的场景一定会碰到,OC的字符串比较
NSString *s = @"sdsdsdds";
NSString *s1 = @"sdsdsdds";
NSString *s2 = @"sdsdsdds1"; NSLog(@"%i", [s isEqualToString:s1]);//=>1
NSLog(@"%i", [s isEqualToString:s2]);//=>0
NSString *s = @"sdsdsdds";
NSString *s1 = @"1sdsdsdds";
NSString *s2 = @"2sdsdsdds1"; NSLog(@"%i", [s isEqualToString:s1]);//=>1
NSLog(@"%i", [s isEqualToString:s2]);//=>0 //NSOrderedDescending|NSOrderedAscending
//NSOrderedAscending判断两对象值的大小(按字母顺序进行比较)
BOOL result = [s1 compare:s2] == NSOrderedAscending;
NSLog(@"result:%d",result);//=>1=>true
字符串拼接
NSString *s1 = @"1sdsdsdds";
NSString *s2 = @"2sdsdsdds1"; NSLog(@"%@", [s1 stringByAppendingString:s2]);
学生集合
我们使用一个可变数组装在我们的学生,并且录入3条数据,最后以他们的总分排序,我们这里先
//创建学生集合
NSMutableArray *students = [[NSMutableArray alloc] init];
Student *student; //下面代码可能会出现警告信息,以我现在的熟悉度是肯定不知道为什么,而且我暂时也不会关注
for(int i = ; i < ; i++) {
//初始化临时学生变量,插入数组
student = [[Student alloc]
initWithName:[@"姓名_" stringByAppendingString: [NSString stringWithFormat:@"%d", i]]
andAge:( + arc4random() % )
andSex:(arc4random() % == ? @"男" : @"女")
andChinese:[[Course alloc] initWithName:@"语文" andScore:arc4random() % ]
andMath:[[Course alloc] initWithName:@"数学" andScore:arc4random() % ]];
[students addObject:student];
} for(id item in students){
[item showData];
}
这里会打印出每个学生的东西:
-- ::23.380 student[:] 姓名:姓名_0
-- ::23.382 student[:] 性别:女
-- ::23.382 student[:] 年龄:
-- ::23.387 student[:] 入学时间:-- :: +
-- ::23.387 student[:] 课程名:语文
-- ::23.388 student[:] 课程得分:59.000000
-- ::23.388 student[:] 课程名:数学
-- ::23.388 student[:] 课程得分:7.000000
-- ::23.388 student[:] 姓名:姓名_1
-- ::23.388 student[:] 性别:女
-- ::23.389 student[:] 年龄:
-- ::23.389 student[:] 入学时间:-- :: +
-- ::23.389 student[:] 课程名:语文
-- ::23.389 student[:] 课程得分:79.000000
-- ::23.389 student[:] 课程名:数学
-- ::23.390 student[:] 课程得分:13.000000
-- ::23.390 student[:] 姓名:姓名_2
-- ::23.390 student[:] 性别:女
-- ::23.390 student[:] 年龄:
-- ::23.390 student[:] 入学时间:-- :: +
-- ::23.391 student[:] 课程名:语文
-- ::23.391 student[:] 课程得分:87.000000
-- ::23.391 student[:] 课程名:数学
-- ::23.391 student[:] 课程得分:52.000000
-- ::23.391 student[:] 姓名:姓名_3
-- ::23.392 student[:] 性别:女
-- ::23.392 student[:] 年龄:
-- ::23.392 student[:] 入学时间:-- :: +
-- ::23.392 student[:] 课程名:语文
-- ::23.393 student[:] 课程得分:13.000000
-- ::23.393 student[:] 课程名:数学
-- ::23.393 student[:] 课程得分:74.000000
-- ::23.393 student[:] 姓名:姓名_4
-- ::23.393 student[:] 性别:女
-- ::23.394 student[:] 年龄:
-- ::23.394 student[:] 入学时间:-- :: +
-- ::23.394 student[:] 课程名:语文
-- ::23.394 student[:] 课程得分:77.000000
-- ::23.394 student[:] 课程名:数学
-- ::23.395 student[:] 课程得分:58.000000
Program ended with exit code:
//创建学生集合
NSMutableArray *students = [[NSMutableArray alloc] init];
Student *student; //下面代码可能会出现警告信息,以我现在的熟悉度是肯定不知道为什么,而且我暂时也不会关注
for(int i = ; i < ; i++) {
//初始化临时学生变量,插入数组
student = [[Student alloc]
initWithName:[@"姓名_" stringByAppendingString: [NSString stringWithFormat:@"%d", i]]
andAge:( + arc4random() % )
andSex:(arc4random() % == ? @"男" : @"女")
andChinese:[[Course alloc] initWithName:@"语文" andScore:arc4random() % ]
andMath:[[Course alloc] initWithName:@"数学" andScore:arc4random() % ]];
[students addObject:student];
} //这里做按考试总分排序的功能,也许是我不够熟悉,但这里真心不得不说写惯了js,尼玛OC的语法真令人蛋疼!!!
NSArray *sortArray = [students sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2){
//这里不知道为什么不能使用obj1的点语法了
if ([obj1 chinese].score + [obj1 math].score > [obj2 chinese].score + [obj2 math].score) {
return (NSComparisonResult)NSOrderedDescending;
}
if ([obj1 chinese].score + [obj1 math].score < [obj2 chinese].score + [obj2 math].score) {
return (NSComparisonResult)NSOrderedAscending;
}
return (NSComparisonResult)NSOrderedSame;
}]; for(id item in students){
[item showData];
} NSLog(@"=====排序后======\n"); for(id item in sortArray){
[item showData];
}
输出:
-- ::45.483 student[:] 姓名:姓名_0
-- ::45.484 student[:] 性别:女
-- ::45.484 student[:] 年龄:
-- ::45.485 student[:] 课程名:语文
-- ::45.485 student[:] 课程得分:54.0
-- ::45.485 student[:] 课程名:数学
-- ::45.485 student[:] 课程得分:60.0
-- ::45.485 student[:] 考试总分:114.0
-- ::45.486 student[:] -------------
-- ::45.486 student[:] 姓名:姓名_1
-- ::45.486 student[:] 性别:男
-- ::45.486 student[:] 年龄:
-- ::45.486 student[:] 课程名:语文
-- ::45.486 student[:] 课程得分:33.0
-- ::45.487 student[:] 课程名:数学
-- ::45.487 student[:] 课程得分:85.0
-- ::45.487 student[:] 考试总分:118.0
-- ::45.487 student[:] -------------
-- ::45.487 student[:] 姓名:姓名_2
-- ::45.487 student[:] 性别:女
-- ::45.540 student[:] 年龄:
-- ::45.541 student[:] 课程名:语文
-- ::45.541 student[:] 课程得分:98.0
-- ::45.541 student[:] 课程名:数学
-- ::45.541 student[:] 课程得分:37.0
-- ::45.541 student[:] 考试总分:135.0
-- ::45.542 student[:] -------------
-- ::45.542 student[:] 姓名:姓名_3
-- ::45.542 student[:] 性别:男
-- ::45.542 student[:] 年龄:
-- ::45.542 student[:] 课程名:语文
-- ::45.542 student[:] 课程得分:69.0
-- ::45.543 student[:] 课程名:数学
-- ::45.543 student[:] 课程得分:1.0
-- ::45.543 student[:] 考试总分:70.0
-- ::45.543 student[:] -------------
-- ::45.543 student[:] 姓名:姓名_4
-- ::45.543 student[:] 性别:女
-- ::45.543 student[:] 年龄:
-- ::45.544 student[:] 课程名:语文
-- ::45.544 student[:] 课程得分:88.0
-- ::45.560 student[:] 课程名:数学
-- ::45.560 student[:] 课程得分:16.0
-- ::45.561 student[:] 考试总分:104.0
-- ::45.561 student[:] -------------
-- ::45.561 student[:] =====排序后======
-- ::45.562 student[:] 姓名:姓名_3
-- ::45.562 student[:] 性别:男
-- ::45.562 student[:] 年龄:
-- ::45.563 student[:] 课程名:语文
-- ::45.563 student[:] 课程得分:69.0
-- ::45.563 student[:] 课程名:数学
-- ::45.563 student[:] 课程得分:1.0
-- ::45.564 student[:] 考试总分:70.0
-- ::45.564 student[:] -------------
-- ::45.564 student[:] 姓名:姓名_4
-- ::45.564 student[:] 性别:女
-- ::45.565 student[:] 年龄:
-- ::45.565 student[:] 课程名:语文
-- ::45.565 student[:] 课程得分:88.0
-- ::45.565 student[:] 课程名:数学
-- ::45.566 student[:] 课程得分:16.0
-- ::45.566 student[:] 考试总分:104.0
-- ::45.603 student[:] -------------
-- ::45.603 student[:] 姓名:姓名_0
-- ::45.603 student[:] 性别:女
-- ::45.603 student[:] 年龄:
-- ::45.604 student[:] 课程名:语文
-- ::45.604 student[:] 课程得分:54.0
-- ::45.604 student[:] 课程名:数学
-- ::45.604 student[:] 课程得分:60.0
-- ::45.604 student[:] 考试总分:114.0
-- ::45.605 student[:] -------------
-- ::45.605 student[:] 姓名:姓名_1
-- ::45.605 student[:] 性别:男
-- ::45.605 student[:] 年龄:
-- ::45.605 student[:] 课程名:语文
-- ::45.605 student[:] 课程得分:33.0
-- ::45.606 student[:] 课程名:数学
-- ::45.606 student[:] 课程得分:85.0
-- ::45.606 student[:] 考试总分:118.0
-- ::45.606 student[:] -------------
-- ::45.606 student[:] 姓名:姓名_2
-- ::45.606 student[:] 性别:女
-- ::45.607 student[:] 年龄:
-- ::45.607 student[:] 课程名:语文
-- ::45.626 student[:] 课程得分:98.0
-- ::45.626 student[:] 课程名:数学
-- ::45.626 student[:] 课程得分:37.0
-- ::45.627 student[:] 考试总分:135.0
-- ::45.627 student[:] -------------
Program ended with exit code:
完整的代码:
#import <Foundation/Foundation.h> @interface Course : NSObject
{
NSString *_name;
float _score;
} -(instancetype)initWithName:(NSString *)newName andScore:(float)newScore; -(void)setName: (NSString *)str;
-(NSString *)name; -(void)setScore: (float)fl;
-(float)score; -(void)showData; @end #import "Course.h" @implementation Course //自定义构造方法
-(instancetype)initWithName:(NSString *)newName andScore:(float)newScore
{
self = [super init];
if (self) {
_name = newName;
_score = newScore;
}
return self;
} -(void) setName:(NSString *)str
{
_name = str;
} -(NSString *) name
{
return _name;
} -(void) setScore:(float)fl
{
_score = fl;
} -(float) score
{
return _score;
} -(void) showData
{
NSLog(@"课程名:%@", _name);
NSLog(@"课程得分:%.1f",_score);
} @end #import <Foundation/Foundation.h>
#import "Course.h" @interface Student : NSObject
{
NSString *_name;
int _age;
NSString *_sex;
Course *_chinese;
Course *_math;
//录入时间
NSDate *_dateCreate;
} -(instancetype)initWithName:(NSString *)newName andAge:(int)newAge andSex:(NSString *)newSex andChinese:(Course *) newChinese andMath:(Course *) newMath; -(void)setName: (NSString *)str;
-(NSString *)name; -(void)setAge: (int)a;
-(int)age; -(void)setSex: (NSString *)str;
-(NSString *)sex; -(void)setChinese: (Course *)c;
-(Course *)chinese; -(void)setMath: (Course *)c;
-(Course *)math; //只暴露读取接口
-(NSDate *)dateCreate; -(void) showData; @end #import "Student.h" @implementation Student -(instancetype)initWithName:(NSString *)newName andAge:(int)newAge andSex:(NSString *)newSex andChinese:(Course *) newChinese andMath:(Course *) newMath
{
self = [super init];
if (self) {
_name = newName;
_age = newAge;
_sex = newSex;
_chinese = newChinese;
_math = newMath;
_dateCreate = [[NSDate alloc] init];
}
return self;
} -(void) setName:(NSString *)str
{
_name = str;
} -(NSString *) name
{
return _name;
} -(void)setAge: (int)a
{
_age = a;
} -(int)age
{
return _age;
} -(void)setSex: (NSString *)str
{
_sex = str;
} -(NSString *)sex
{
return _sex;
} -(void)setChinese: (Course *)c
{
_chinese = c;
} -(Course *)chinese
{
return _chinese;
} -(void)setMath: (Course *)c
{
_math = c;
} -(Course *)math
{
return _math;
} //只暴露读取接口
-(NSDate *)dateCreate
{
return _dateCreate;
} -(void) showData
{
NSLog(@"姓名:%@", _name);
NSLog(@"性别:%@", _sex);
NSLog(@"年龄:%d", _age);
//NSLog(@"入学时间:%@", _dateCreate);
[_chinese showData];
[_math showData];
NSLog(@"考试总分:%.1f", _chinese.score + _math.score);
NSLog(@"-------------\n");
} @end #import <Foundation/Foundation.h>
#import "Student.h"
#import "Course.h" int main(int argc, const char * argv[]) {
@autoreleasepool { //创建学生集合
NSMutableArray *students = [[NSMutableArray alloc] init];
Student *student; //下面代码可能会出现警告信息,以我现在的熟悉度是肯定不知道为什么,而且我暂时也不会关注
for(int i = ; i < ; i++) {
//初始化临时学生变量,插入数组
student = [[Student alloc]
initWithName:[@"姓名_" stringByAppendingString: [NSString stringWithFormat:@"%d", i]]
andAge:( + arc4random() % )
andSex:(arc4random() % == ? @"男" : @"女")
andChinese:[[Course alloc] initWithName:@"语文" andScore:arc4random() % ]
andMath:[[Course alloc] initWithName:@"数学" andScore:arc4random() % ]];
[students addObject:student];
} //这里做按考试总分排序的功能,也许是我不够熟悉,但这里真心不得不说写惯了js,尼玛OC的语法真令人蛋疼!!!
NSArray *sortArray = [students sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2){
//这里不知道为什么不能使用obj1的点语法了
if ([obj1 chinese].score + [obj1 math].score > [obj2 chinese].score + [obj2 math].score) {
return (NSComparisonResult)NSOrderedDescending;
}
if ([obj1 chinese].score + [obj1 math].score < [obj2 chinese].score + [obj2 math].score) {
return (NSComparisonResult)NSOrderedAscending;
}
return (NSComparisonResult)NSOrderedSame;
}]; for(id item in students){
[item showData];
} NSLog(@"=====排序后======\n"); for(id item in sortArray){
[item showData];
} }
return ;
}
APP开发简介
控制台输出部分完成后,我们的功能也就实现了一半,现在要做的是,如何将上述功能写到app中,意思是我们现在就要开始做app开发了,因为我没有开发者账号,只能在mac上模拟。
既然是app就应该有更加完善的功能了,这里给自己的需求是:
1 有界面录入学生信息
2 有列表可展示学生信息
3 学生信息可排序
4 可编辑、删除学生
需求不多,多了可能就做不完,于是我们便愉快的开始吧,这次新建项目会有所不同:选择的是最简单的single View application
这里取个名字student_app,完了就会在模拟器中新增一个app,瞬间觉得好牛B的样子:
然后,项目中的文件以及界面让我感觉到了陌生,这里也不一一去了解了,直接朝着需求方向进发吧。
PS:学习过程中最初会有意的忽略一些基础知识,但是这些知识是我们后面能走多远的基础,所以在快速熟悉后需要一个过渡期重新回来整理基础,否则走不远的
OC的MVC
模型-视图-控制器,是我们经常听到的mvc,为各种与界面相关的系统都会频繁使用的一种模式,其意义在于代码解耦,OC APP开发遵循这一规则
视图简单来说便是界面,比如我们后面要做的展示学生相关信息的界面
模型便是界面的数据来源
而控制器便是管理者,用于控制视图与模型之间的交互,比如新增删除什么的
于是,我们便开始了解OC中MVC是如何使用的吧,也许学过后会帮助我们更加了解web中的MVC,偶尔我仍然觉得自己了解的不够深刻
在此之前,我们先来了解几个ios开发的基本组件,否则将使我们的开发无法继续。
UI相关视图
PS:从IOS5开始进行了改进,使用“.storyboard”文件进行设计
UILabel继承至UIView,这个名字让我想起了多年前做.net2.0拖控件的时光,可能他们完成的功能也差不多,做展示性工作
这里新建一个文件:StudentViewController,继承至UIViewController,这里记得勾选also create xib file,会生成如下文件:
file.h 头文件
file.m 实现文件
file.xib xml interface build
这个xml文件有点类似与html文件,做布局用的,最初在左.net开发winform窗体软件时,也会出现类似的文件,这里点击打开,果然是一个白板窗体。
这里使用一种界面工具打开该文件(interface builder),左侧是dock,右边是画布,那坨东西与html一样,事实上是一坨代码:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="" systemVersion="14A298i" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version=""/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="StudentViewController">
<connections>
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
<rect key="frame" x="0.0" y="0.0" width="" height=""/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="" alpha="" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</objects>
</document>
placeholder为占位符对象,下面那个是view对象,虽然不知道是什么,好像很厉害的样子。
要使用UILabel,根据之前的开发经验估计会有两种:
1 自己编辑代码
2 ide会有工具箱让我们拖
果不其然,这里便出现了对象库:在工具区域打开对象库,位于编辑区的右侧,分为上下两部分,检视面板与库面板,前者负责显示编辑区域当前选择文件的各种设置;后者便是可拖拽的工具了:
因为我们建立的是sigile page application,所以上述文件不需要我们创建,系统自动为我们创建好了Main.storyboard,我们之间在这之上开发就行
我一次性拖了3个组件上去,视图效果有所不同了,可以通过检视面板调整属性,双击按钮可以编辑一些title,并可以设置居中等操作,这些需要我们慢慢熟悉
这个时候可以看到起代码(类似与html的代码)也发生了改变,我个人暂时没有意愿去读取,也希望以后都不需要去读取......
所有的xib文件都会被编译成nib文件,其体积更小,更容易解析,然后Xcode会将nib拷贝至程序包,包含可运行的所有资源,这个不是我们如今关注的重点
目录简介
在了解如何设置关联前,我们来看看代码组织,我们知道OC的入口函数为main函数,这里的main函数是:
#import <UIKit/UIKit.h>
#import "AppDelegate.h" int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
这里制造了一个内部消息循环,我猜测这里开了一个监听进程,不停的监听view的变化,应该有一个频率,但是这与我们没有一毛钱关系
这里调用了4个参数,开始两个是main函数自带的参数。
第三个参数为一个UIApplication(或子类)字符串,为nil便默认为UIApplication,这个参数干什么的也暂时不知道
最后一个参数为UIApplication的代理字符串,默认生成AppDelegate类,用于监听整个应用程序周期的各个事件,当某个系统事件触发便会执行其代理中对应方法
虽然不知道这一段代码真实做了什么事情,但可猜测是这里会根据参数3创建UIApplication对象,然后根据第一个参数创建并指定UIApplication的代理,然后UIApplication便开启消息循环直到进程被杀死,所以详细代表在AppDelegate中:
#import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; @end
#import "AppDelegate.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
} - (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
} - (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
} - (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
} - (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
} - (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
} @end
这个类中定义了应用程序生命周期中各个事件的执行方法: - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
程序启动之后执行,只有在第一次程序启动后才执行,以后不再执行; - (void)applicationWillResignActive:(UIApplication *)application;
程序将要被激活时(获得焦点)执行,程序激活用户才能操作; - (void)applicationDidEnterBackground:(UIApplication *)application;
程序进入后台后执行,注意进入后台时会先失去焦点再进入后台; - (void)applicationWillEnterForeground:(UIApplication *)application;
程序将要进入前台时执行; - (void)applicationDidBecomeActive:(UIApplication *)application;
程序被激活(获得焦点)后执行,注意程序被激活时会先进入前台再被激活; - (void)applicationWillTerminate:(UIApplication *)application;
程序在终止时执行,包括正常终止或异常终止,例如说一个应用程序在后太运行(例如音乐播放软件、社交软件等)占用太多内存这时会意外终止调用此方法;
这个有点类似与.net application的事件管道,在一条程序生命周期内,当达到某一个特定的时期便会执行相关函数,这里我们不去深入了解,事实上与我们当前需求意义不大
下面是其文件具体含义:
AppDelegate(.h/.m):应用程序代理,主要用于监听整个应用程序生命周期中各个阶段的事件;
ViewController(.h/.m):视图控制器,主要负责管理UIView的生命周期、负责UIView之间的切换、对UIView事件进行监听等;
Main.storyboard:界面布局文件,承载对应UIView的视图控件;
Images.xcassets:应用程序图像资源文件;
Info.plist:应用程序配置文件;
main.m:应用程序入口函数文件;
xxx-prefix.pch:项目公共头文件,此文件中的导入语句在编译时会应用到所有的类文件中,相当于公共引入文件(注意在Xcode6中没有提供此文件)
建立关联
以上有3个UI对象,但是是没有交互的,interface builder可以创建两种关联:
① 插座变量
一种指向对象的指针
② 动作变量
一种方法,比如点击、拖拽等事件
根据之前的经验,插座变量应该便是id相关映射,动作变量便是事件回调
我们知道关联相关的代码肯定在控制器中,这个时候便需要对控制器文件进行操作,我们首先在头文件中创建3个对象,两个插座对象,一个事件对象:
#import <UIKit/UIKit.h> @interface ViewController : UIViewController //属性简单创建的语法糖,后续需要详细了解其用法
@property (nonatomic, strong) IBOutlet UILabel *msg; @property (nonatomic, strong) IBOutlet UITextField *txt; //点击按钮后的事件回调
-(IBAction)myClick:(UIButton *)btn; @end
IBOutlet 没有实际意义,他会告诉interface builder这个属性会被关联到某个控件,代码前面也确实出现了小圆点:
所谓的关联便是在画板中将对应的控件拖向小圆点,这里OC又一次没有让我们失望,依旧那么恶心,当我得知我要拖动时,我感觉整个智商又降低了!步骤为:
点击右上方的show the assistant editor,打开控制器文件与视图文件开始拖拽吧!!!
这里只说明拖动,可关联,不要关注实际代码。下面看看改动controller代码会如何,这里增加按钮点击时的实现:
#import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} //让label显示文本框的文字
-(void) myClick:(UIButton *)btn{
_msg.text = _txt.text;
} @end
其中UI组件的具体使用我们暂时不予关注,再后面的章节中再好好巩固基础,或者后续项目中好好总结......
纯代码关联
说是使用面部做简单界面设计是可以的,也是赞成的,但是要使用拖拽的方式关联控件和事件还是算了吧,详细.net的双击按钮生成事件真心优雅多了,当然OC也是可以纯代码做这些事情的,这个留待我们下次处理,否则今天的学习任务便结束不了了。
学生系统的视图
这里先回答学生管理系统本身学生类与课程类之前已经创建结束,这里我们看界面应该如何开发其界面,由于时间关系,也不去使用什么单选框,直接全部上文本框吧,尼玛太久没写博客发现居然会有点累!!!
这里首先建立了这样的视图,并且按照之前拖拽的方式建立了管理,其中按钮只有事件关联
这里简单测试,效果还是可行的:
//这里实例化一个Student对象试试
//这里如果数字输入错误会导致解析出问题,可能会报错,不知道OC生产项目应该如何处理
Student *student = [[Student alloc]
initWithName:_stuName.text
andAge:[_stuAge.text intValue]
andSex:_stuSex.text
andChinese:[[Course alloc] initWithName:@"语文" andScore:[_stuChinese.text floatValue]]
andMath:[[Course alloc] initWithName:@"数学" andScore:[_stuMath.text floatValue]]]; [student showData];
-- ::10.273 student_app[:] 姓名:
-- ::10.274 student_app[:] 性别:男
-- ::10.275 student_app[:] 年龄:
-- ::10.275 student_app[:] 课程名:语文
-- ::10.276 student_app[:] 课程得分:33.0
-- ::10.276 student_app[:] 课程名:数学
-- ::10.276 student_app[:] 课程得分:44.0
-- ::10.277 student_app[:] 考试总分:77.0
-- ::10.277 student_app[:] -------------
于是我们回到最初的做法,每次录入皆将数据放进一个数组中,由于这个数组是固定的,这里将之作为控制器的一个属性,生产是怎么样的我们后面看看,于是在控制器上建立students的成员属性。
每次添加到数组中,然后将数组中的数组展示出来即可,这里展示数据得使用一个非常常见的列表组件:UITableView
UITableView是OC中经常使用的组件,主要用于显示列表,这个组件比较复杂真的要研究恐怕得研究1,2天,我们这边就直接看其如何使用即可,这里的目标便是将录入的数据显示在界面上,我们今天的任务便完成。
这里在控制器头文件中新增一个UITableView组件,然后尝试绑定即可,经过漫长的研究,最终成果是:
虽然有点丑,但是基本符合预期,而编辑等功能就等下次再完成了,今天没有精力了,一下是一些代码:
#import <Foundation/Foundation.h> @interface Course : NSObject
{
NSString *_name;
float _score;
} -(instancetype)initWithName:(NSString *)newName andScore:(float)newScore; -(void)setName: (NSString *)str;
-(NSString *)name; -(void)setScore: (float)fl;
-(float)score; -(void)showData; @end #import "Course.h" @implementation Course //自定义构造方法
-(instancetype)initWithName:(NSString *)newName andScore:(float)newScore
{
self = [super init];
if (self) {
_name = newName;
_score = newScore;
}
return self;
} -(void) setName:(NSString *)str
{
_name = str;
} -(NSString *) name
{
return _name;
} -(void) setScore:(float)fl
{
_score = fl;
} -(float) score
{
return _score;
} -(void) showData
{
NSLog(@"课程名:%@", _name);
NSLog(@"课程得分:%.1f",_score);
} @end #import <Foundation/Foundation.h>
#import "Course.h" @interface Student : NSObject
{
NSString *_name;
int _age;
NSString *_sex;
Course *_chinese;
Course *_math;
//录入时间
NSDate *_dateCreate;
} -(instancetype)initWithName:(NSString *)newName andAge:(int)newAge andSex:(NSString *)newSex andChinese:(Course *) newChinese andMath:(Course *) newMath; -(void)setName: (NSString *)str;
-(NSString *)name; -(void)setAge: (int)a;
-(int)age; -(void)setSex: (NSString *)str;
-(NSString *)sex; -(void)setChinese: (Course *)c;
-(Course *)chinese; -(void)setMath: (Course *)c;
-(Course *)math; //只暴露读取接口
-(NSDate *)dateCreate; -(void) showData;
-(NSString *) getData; @end #import "Student.h" @implementation Student -(instancetype)initWithName:(NSString *)newName andAge:(int)newAge andSex:(NSString *)newSex andChinese:(Course *) newChinese andMath:(Course *) newMath
{
self = [super init];
if (self) {
_name = newName;
_age = newAge;
_sex = newSex;
_chinese = newChinese;
_math = newMath;
_dateCreate = [[NSDate alloc] init];
}
return self;
} -(void) setName:(NSString *)str
{
_name = str;
} -(NSString *) name
{
return _name;
} -(void)setAge: (int)a
{
_age = a;
} -(int)age
{
return _age;
} -(void)setSex: (NSString *)str
{
_sex = str;
} -(NSString *)sex
{
return _sex;
} -(void)setChinese: (Course *)c
{
_chinese = c;
} -(Course *)chinese
{
return _chinese;
} -(void)setMath: (Course *)c
{
_math = c;
} -(Course *)math
{
return _math;
} //只暴露读取接口
-(NSDate *)dateCreate
{
return _dateCreate;
} -(void) showData
{
NSLog(@"姓名:%@", _name);
NSLog(@"性别:%@", _sex);
NSLog(@"年龄:%d", _age);
//NSLog(@"入学时间:%@", _dateCreate);
[_chinese showData];
[_math showData];
NSLog(@"考试总分:%.1f", _chinese.score + _math.score);
NSLog(@"-------------\n");
} -(NSString *) getData
{
return [[_name stringByAppendingString:@"总分 "]
stringByAppendingString: [NSString stringWithFormat:@"%.1f",_chinese.score + _math.score]];
} @end #import <UIKit/UIKit.h>
#import "Student.h" //这里需要实现一个协议,就是我们说的接口,原因后续再研究
//delegate是为了数据更新时刷新视图
@interface ViewController : UIViewController<UITableViewDataSource, UITableViewDelegate> //存储学生的集合
@property (nonatomic, strong) NSMutableArray *students; //属性简单创建的语法糖,后续需要详细了解其用法
@property (nonatomic, strong) IBOutlet UITextField *stuName; @property (nonatomic, strong) IBOutlet UITextField *stuSex; @property (nonatomic, strong) IBOutlet UITextField *stuAge; @property (nonatomic, strong) IBOutlet UITextField *stuChinese; @property (nonatomic, strong) IBOutlet UITextField *stuMath; @property (nonatomic, strong) IBOutlet UITableView *stuList; //点击按钮后的事件回调
-(IBAction)onAdd:(UIButton *)btn; //点击按钮后的事件回调
-(IBAction)onRead:(UIButton *)btn; @end #import "ViewController.h"
#import "Course.h"
#import "Student.h" @interface ViewController ()
@end @implementation ViewController ////重写初始化方法,控制器对象创建结束后会执行
//
//-(id) initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil{
//
// self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
//
// if(self) {
// self.students= [NSMutableArray alloc];
// }
//
// return self;
//} - (void)viewDidLoad {
[super viewDidLoad]; //在页面准备前对数组进行初始化
_students = [[NSMutableArray alloc] init]; // _students = [NSMutableArray arrayWithObjects:@"武汉",@"上海",@"北京",@"深圳",@"广州",@"重庆",@"香港",@"台海",@"天津", nil];
//
_stuList = [[UITableView alloc] initWithFrame:CGRectMake(, , , )]; //设置数据源,注意必须实现对应的UITableViewDataSource协议
_stuList.dataSource = self; //动态添加
[self.view addSubview:_stuList]; } - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
} -(void) onAdd:(UIButton *)btn{
//这里实例化一个Student对象试试
//这里如果数字输入错误会导致解析出问题,可能会报错,不知道OC生产项目应该如何处理
Student *student = [[Student alloc]
initWithName:_stuName.text
andAge:[_stuAge.text intValue]
andSex:_stuSex.text
andChinese:[[Course alloc] initWithName:@"语文" andScore:[_stuChinese.text floatValue]]
andMath:[[Course alloc] initWithName:@"数学" andScore:[_stuMath.text floatValue]]]; //这里每次点击,皆将结果存于全局数组中
[_students addObject:student]; //每次数据更新便将对应数据显示在UITableView中
[_stuList performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO]; } -(void) onRead:(UIButton *)btn{
for(id item in _students){
[item showData];
}
} //必须实现
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellWithIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellWithIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellWithIdentifier];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [[_students objectAtIndex:row] getData]; return cell;
} //每个section下cell的个数(必须实现)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return _students.count;
} @end
核心代码为:
#import "ViewController.h"
#import "Course.h"
#import "Student.h" @interface ViewController ()
@end @implementation ViewController ////重写初始化方法,控制器对象创建结束后会执行
//
//-(id) initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil{
//
// self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
//
// if(self) {
// self.students= [NSMutableArray alloc];
// }
//
// return self;
//} - (void)viewDidLoad {
[super viewDidLoad]; //在页面准备前对数组进行初始化
_students = [[NSMutableArray alloc] init]; // _students = [NSMutableArray arrayWithObjects:@"武汉",@"上海",@"北京",@"深圳",@"广州",@"重庆",@"香港",@"台海",@"天津", nil];
//
_stuList = [[UITableView alloc] initWithFrame:CGRectMake(, , , )]; //设置数据源,注意必须实现对应的UITableViewDataSource协议
_stuList.dataSource = self; //动态添加
[self.view addSubview:_stuList]; } - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
} -(void) onAdd:(UIButton *)btn{
//这里实例化一个Student对象试试
//这里如果数字输入错误会导致解析出问题,可能会报错,不知道OC生产项目应该如何处理
Student *student = [[Student alloc]
initWithName:_stuName.text
andAge:[_stuAge.text intValue]
andSex:_stuSex.text
andChinese:[[Course alloc] initWithName:@"语文" andScore:[_stuChinese.text floatValue]]
andMath:[[Course alloc] initWithName:@"数学" andScore:[_stuMath.text floatValue]]]; //这里每次点击,皆将结果存于全局数组中
[_students addObject:student]; //每次数据更新便将对应数据显示在UITableView中
[_stuList performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO]; } -(void) onRead:(UIButton *)btn{
for(id item in _students){
[item showData];
}
} //必须实现
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellWithIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellWithIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellWithIdentifier];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [[_students objectAtIndex:row] getData]; return cell;
} //每个section下cell的个数(必须实现)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return _students.count;
} @end
#import "ViewController.h"
#import "Course.h"
#import "Student.h" @interface ViewController ()
@end @implementation ViewController ////重写初始化方法,控制器对象创建结束后会执行
//
//-(id) initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil{
//
// self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
//
// if(self) {
// self.students= [NSMutableArray alloc];
// }
//
// return self;
//} - (void)viewDidLoad {
[super viewDidLoad]; //在页面准备前对数组进行初始化
_students = [[NSMutableArray alloc] init]; // _students = [NSMutableArray arrayWithObjects:@"武汉",@"上海",@"北京",@"深圳",@"广州",@"重庆",@"香港",@"台海",@"天津", nil];
//
_stuList = [[UITableView alloc] initWithFrame:CGRectMake(, , , )]; //设置数据源,注意必须实现对应的UITableViewDataSource协议
_stuList.dataSource = self; //动态添加
[self.view addSubview:_stuList]; } - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
} -(void) onAdd:(UIButton *)btn{
//这里实例化一个Student对象试试
//这里如果数字输入错误会导致解析出问题,可能会报错,不知道OC生产项目应该如何处理
Student *student = [[Student alloc]
initWithName:_stuName.text
andAge:[_stuAge.text intValue]
andSex:_stuSex.text
andChinese:[[Course alloc] initWithName:@"语文" andScore:[_stuChinese.text floatValue]]
andMath:[[Course alloc] initWithName:@"数学" andScore:[_stuMath.text floatValue]]]; //这里每次点击,皆将结果存于全局数组中
[_students addObject:student]; //每次数据更新便将对应数据显示在UITableView中
[_stuList performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO]; } -(void) onRead:(UIButton *)btn{
for(id item in _students){
[item showData];
}
} //必须实现
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellWithIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellWithIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellWithIdentifier];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [[_students objectAtIndex:row] getData]; return cell;
} //每个section下cell的个数(必须实现)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return _students.count;
} @end
结语
几天来,我们在没有OC的基础下搞上面那个东西出来,一路磕磕碰碰,算是有了一个开始,接下来的章节,我准备巩固下基础知识,再下周的时候考虑做一点更加实际的东西
因为我也是初学,文中肯定有很多不足,各位就不要喷了