• 触控(Touch) 、 布局(Layout)


    1 使用触控实现一个简易的画板

    1.1 问题

    触控(Touch)是一个UITouch类型的对象,当用户触摸了屏幕上的视图时自动被创建,通常使用触控实现绘图、涂鸦、手写等功能。本案例使用触控实现一个简易的画板,可以在画板上勾画出一条线,如图-1所示:

    图-1

    1.2 方案

    首先在创建好的SingleViewApplication项目中创建一个画板类TRDrawView,继承至UIView,该类有一个NSMutableArray类型的属性points,用于存储手指触摸的轨迹也就是点。

    其次在Stroyboard的场景中拖放一个View控件,和屏幕一样大小,然后将View的类型修改为TRDrawView。

    然后在TRDrawView类中通过touchesBegan:、touchesMoved:方法获取到手指的触摸点,将点存储到points数组中。

    最后在TRDrawView类中重写drawRect方法,该方法中根据手指的触摸轨迹points进行屏幕绘制。切记要在touchesMoved方法中调用setNeedDisplay刷新界面。

    1.3 步骤

    实现此案例需要按照如下步骤进行。

    步骤一:创建项目和画板类

    首先在创建好的SingleViewApplication项目中创建一个画板类TRDrawView,继承至UIView,该类有一个NSMutableArray类型的属性points,用于存储手指触摸的轨迹也就是点,代码如下所示:

     
    1. @interface TRDrawView ()
    2. @property (strong, nonatomic) NSMutableArray *points;
    3. @end

    然后从对象库中拖放一个View控件到Storyboard场景中,View控件的大小和屏幕一样。在右边栏的检查器三将View的类型设置为TRDrawView,如图-2所示:

    图-2

    步骤二:在TRDawView中获取手指触摸轨迹

    在TRDrawView类中首先重写touchesBegan:,在该方法将points属性进行初始化,并获取当前手指的触摸点,存储到points数组中,代码如下所示:

     
    1. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    2. {
    3. //初始化数组
    4. self.points = [@[]mutableCopy];
    5. //获取当前触摸点
    6. UITouch *touch = [touches anyObject];
    7. CGPoint point = [touch locationInView:self];
    8. //将点放进数组中
    9. NSValue *value = [NSValue valueWithCGPoint:point];
    10. [self.points addObject:value];
    11. }

    然后再重写touchesMove:方法,在该方法中继续获取手指的当前触摸点,并将触摸点存储到points数组中,代码如下所示:

     
    1. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
    2. {
    3. //获取当前触摸点
    4. UITouch *touch = [touches anyObject];
    5. CGPoint point = [touch locationInView:self];
    6. //将点放进数组中
    7. NSValue *value = [NSValue valueWithCGPoint:point];
    8. [self.points addObject:value];
    9. }

    步骤三:重写drawRect方法,进行屏幕绘制

    在TRDrawView类中重写drawRect方法,该方法中根据手指的触摸轨迹points进行屏幕绘制,代码如下所示:

     
    1. - (void)drawRect:(CGRect)rect
    2. {
    3. UIBezierPath *path = [UIBezierPath bezierPath];
    4. NSValue *value = [self.points firstObject];
    5. [path moveToPoint:[value CGPointValue]];
    6. for (NSValue *value in self.points) {
    7. [path addLineToPoint:[value CGPointValue]];
    8. }
    9. path.lineWidth = 4;
    10. [[UIColor redColor]setStroke];
    11. [path stroke];
    12. }

    最后要在touchesMoved:和touchesEnded:方法中调用setNeedDisplay刷新界面,代码如下所示:

     
    1. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
    2. {
    3. //获取当前触摸点
    4. UITouch *touch = [touches anyObject];
    5. CGPoint point = [touch locationInView:self];
    6. //将点放进数组中
    7. NSValue *value = [NSValue valueWithCGPoint:point];
    8. [self.points addObject:value];
    9. //刷新界面
    10. [self setNeedsDisplay];
    11. }
    12. - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    13. {
    14. [self setNeedsDisplay];
    15. }

    1.4 完整代码

    本案例中,TRDrawView.m文件中的完整代码如下所示:

    2 使用纯代码进行界面布局

    2.1 问题

    纯代码布局就是重写布局方法viewDidLayoutSubviews,在该方法内部计算每个子视图的frame属性。本案例将学习如何使用纯代码进行布局,使界面上的Button和Label控件始终保持在固定的位置,如图-3、图-4所示:

    图-3

    图-4

    2.2 方案

    首先创建一个SingleViewApplication项目,将自动布局功能关闭。

    在Stroyboard的场景中拖放两个Button控件和一个Label控件,Button放置在屏幕的上方,并且大小一样,Label控件放置在屏幕的右下角。

    然后在TRViewController类中重写布局方法viewDidLayoutSubviews,在该方法中根据父视图的bounds计算Button和Label的frame。

    2.3 步骤

    实现此案例需要按照如下步骤进行。

    步骤一:创建项目,添加控件

    首先创建一个SingleViewApplication项目,在右边栏的检查器一中将自动布局功能关闭,如图-5所示:

    图-5

    在Stroyboard的场景中拖放两个Button控件和一个Label控件,Button放置在屏幕的上方,并且大小一样,Label控件放置在屏幕的右下角,如图-6所示:

    图-6

    步骤二:重写布局方法viewDidLayoutSubviews,进行界面布局

    将Storyboard中的Button控件和Label控件关联成TRViewController的私有属性,代码如下所示:

     
    1. @interface TRViewController ()
    2. @property (weak, nonatomic) IBOutlet UIButton *button1;
    3. @property (weak, nonatomic) IBOutlet UIButton *button2;
    4. @property (weak, nonatomic) IBOutlet UILabel *label;
    5. @end

    在TRViewController类中重写布局方法viewDidLayoutSubviews,在该方法中根据父视图的bounds计算Button和Label的frame,代码如下所示:

     
    1. - (void)viewDidLayoutSubviews
    2. {
    3. [super viewDidLayoutSubviews];
    4. CGFloat buttonWidth = (self.view.bounds.size.width - 20 - 20 - 10) * 0.5;
    5. CGRect frame = CGRectMake(20, self.button1.frame.origin.y, buttonWidth, 40);
    6. self.button1.frame = frame;
    7. frame = CGRectMake(self.button1.frame.size.width+30, self.button2.frame.origin.y, buttonWidth, 40);
    8. self.button2.frame = frame;
    9. frame = self.label.frame;
    10. self.label.frame = CGRectMake(self.view.bounds.size.width-20-frame.size.width, self.view.bounds.size.height-20-frame.size.height, frame.size.width, frame.size.height);
    11. }

    2.4 完整代码

    本案例中,TRViewController.m文件中的完整代码如下所示:

     
    1. #import "TRViewController.h"
    2. @interface TRViewController ()
    3. @property (weak, nonatomic) IBOutlet UIButton *button1;
    4. @property (weak, nonatomic) IBOutlet UIButton *button2;
    5. @property (weak, nonatomic) IBOutlet UILabel *label;
    6. @end
    7. @implementation TRViewController
    8. - (void)viewDidLayoutSubviews
    9. {
    10. [super viewDidLayoutSubviews];
    11. CGFloat buttonWidth = (self.view.bounds.size.width - 20 - 20 - 10) * 0.5;
    12. CGRect frame = CGRectMake(20, self.button1.frame.origin.y, buttonWidth, 40);
    13. self.button1.frame = frame;
    14. frame = CGRectMake(self.button1.frame.size.width+30, self.button2.frame.origin.y, buttonWidth, 40);
    15. self.button2.frame = frame;
    16. frame = self.label.frame;
    17. self.label.frame = CGRectMake(self.view.bounds.size.width-20-frame.size.width, self.view.bounds.size.height-20-frame.size.height, frame.size.width, frame.size.height);
    18. }
    19. @end
     

    3 根据上边栏和下边栏的高度进行布局

    3.1 问题

    从iOS7开始,视图控制器会渗透到各种Bar下面,包括:NavigationBar、ToolBar、TabBar、StatusBar等;这些Bar会挤占视图的空间,在布局时就需要根据各种Bar所挤占的空间大小来计算控件的frame,本案例直接在上一个案例的基础上实现,根据上边栏和下边栏的高度对界面进行布局,如图-7、图-8所示:

    图-7

    图-8

    3.2 方案

    首先在上一个案例的基础上增加一个NavigationController和TabBarController,在界面的中间拖放一个Button控件,标题设置为“隐藏NavigationBar”,并将Button控件关联成TRViewController的私有方法hideNavigationBar。

    然后在TRViewController类中重写布局方法viewDidLayoutSubviews,在该方法中根据父视图的bounds和上下边栏的高度计算Button和Label的frame。

    3.3 步骤

    实现此案例需要按照如下步骤进行。

    步骤一:创建项目,添加按钮控件

    在上一个案例的基础上增加一个NavigationController和TabBarController,在界面的中间拖放一个Button控件,标题设置为“隐藏NavigationBar”,如图-9所示:

    图-9

    然后将Button控件关联成TRViewController的私有方法hideNavigationBar,该方法的功能是将导航栏隐藏或显示,代码如下所示:

     
    1. - (IBAction)hideNavigationBar
    2. {
    3. self.navigationController.navigationBarHidden = !self.navigationController.navigationBarHidden;
    4. }

    步骤二:重写布局方法viewDidLayoutSubviews,进行界面布局

    在TRViewController类中重写布局方法viewDidLayoutSubviews,在该方法中根据先通过属性self.topLayoutGuide.length和self.bottomLayoutGuide.length获取到上下边栏的高度,然后再通过父视图的bounds和上下边栏的高度计算出Button和Label的frame,代码如下所示:

     
    1. - (void)viewDidLayoutSubviews
    2. {
    3. [super viewDidLayoutSubviews];
    4. CGFloat buttonWidth = (self.view.bounds.size.width - 20 - 20 - 10) * 0.5;
    5. //从iOS7开始,可以随时知道VC的上面和下面被各种Bar占据了多少的空间
    6. CGFloat top = self.topLayoutGuide.length;
    7. CGRect frame = CGRectMake(20, top+10, buttonWidth, 40);
    8. self.button1.frame = frame;
    9. frame.origin.x += buttonWidth + 10;
    10. self.button2.frame = frame;
    11. //下面的各种Bar(TabBar或ToolBar)占了VC多高的空间
    12. CGFloat bottom = self.bottomLayoutGuide.length;
    13. frame = self.label.frame;
    14. frame = CGRectMake(self.view.bounds.size.width - 20 - frame.size.width , self.view.bounds.size.height - 10 - frame.size.height - bottom, frame.size.width, frame.size.height);
    15. self.label.frame = frame;
    16. frame = self.hideButton.frame;
    17. frame.origin.x = self.view.bounds.size.width * 0.5 - frame.size.width * 0.5;
    18. frame.origin.y = self.view.bounds.size.height * 0.5 - frame.size.height * 0.5;
    19. self.hideButton.frame = frame;
    20. }

    3.4 完整代码

    本案例中,TRViewController.m文件中的完整代码如下所示:

     
    1. #import "TRViewController.h"
    2. @interface TRViewController ()
    3. @property (weak, nonatomic) IBOutlet UIButton *button1;
    4. @property (weak, nonatomic) IBOutlet UIButton *button2;
    5. @property (weak, nonatomic) IBOutlet UILabel *label;
    6. @property (weak, nonatomic) IBOutlet UIButton *hideButton;
    7. @end
    8. @implementation TRViewController
    9. - (IBAction)hideNavigationBar
    10. {
    11. self.navigationController.navigationBarHidden = !self.navigationController.navigationBarHidden;
    12. }
    13. - (void)viewDidLayoutSubviews
    14. {
    15. [super viewDidLayoutSubviews];
    16. CGFloat buttonWidth = (self.view.bounds.size.width - 20 - 20 - 10) * 0.5;
    17. //从iOS7开始,可以随时知道VC的上面和下面被各种Bar占据了多少的空间
    18. CGFloat top = self.topLayoutGuide.length;
    19. CGRect frame = CGRectMake(20, top+10, buttonWidth, 40);
    20. self.button1.frame = frame;
    21. frame.origin.x += buttonWidth + 10;
    22. self.button2.frame = frame;
    23. //下面的各种Bar(TabBar或ToolBar)占了VC多高的空间
    24. CGFloat bottom = self.bottomLayoutGuide.length;
    25. frame = self.label.frame;
    26. frame = CGRectMake(self.view.bounds.size.width - 20 - frame.size.width , self.view.bounds.size.height - 10 - frame.size.height - bottom, frame.size.width, frame.size.height);
    27. self.label.frame = frame;
    28. frame = self.hideButton.frame;
    29. frame.origin.x = self.view.bounds.size.width * 0.5 - frame.size.width * 0.5;
    30. frame.origin.y = self.view.bounds.size.height * 0.5 - frame.size.height * 0.5;
    31. self.hideButton.frame = frame;
    32. }
    33. @end

    4 演示绘制图形的布局

    4.1 问题

    使用纯代码布局并且AutoLayout关闭的状态下,在drawRect方法中绘制的图形,在视图大小发生变化时图形会失真,本案例学习绘制图形的布局如图-10,图-11所示:

    图-10

    图-11

    4.2 方案

    首先在创建好的项目中将自动布局功能关闭,再创建一个TRView类,继承至UIView。

    其次在Stroyboard的场景中拖放一个View控件,和屏幕一样大小,然后将View的类型修改为TRView。

    然后在TRView类中重写drawRect方法,在屏幕左上方绘制一个三角形。

    最后将TRView的contentMode属性设置成Redraw,即可实现绘制的布局,屏幕切换或者变化绘制的图形也不会失真。

    4.3 步骤

    实现此案例需要按照如下步骤进行。

    步骤一:创建TRView类,绘制图像

    首先在创建好的项目中将自动布局功能关闭,创建一个TRView类,继承至UIView,用于绘制图形。在Storyboard中拖放一个View控件,和屏幕同等大小,并将View的类型修改为TRView,如图-12所示:

    图-12

    然后将View控件关联成TRViewController的私有属性myView,代码如下所示:

     
    1. @interface TRViewController ()
    2. @property (weak, nonatomic) IBOutlet TRView *myView;
    3. @end

    最后在TRView类中重写drawRect方法,在屏幕左上方绘制一个三角形,代码如下所示:

     
    1. - (void)drawRect:(CGRect)rect
    2. {
    3. UIBezierPath *path = [UIBezierPath bezierPath];
    4. [path moveToPoint:CGPointMake(20, 20)];
    5. [path addLineToPoint:CGPointMake(20, 120)];
    6. [path addLineToPoint:CGPointMake(120, 20)];
    7. [path closePath];
    8. path.lineWidth = 4;
    9. [[UIColor redColor] setStroke];
    10. [path stroke];
    11. }

    步骤二:进行绘制布局

    完成绘制代码,运行程序可见屏幕左上方有一个三角形,但是当切换成横屏时发现三角形失真,如图-13所示:

    图-13

    解决的办法是,当视图大小发生变化时,进行重新绘制图形,即在布局方法viewDidLayoutSubviews里面调用setNeedDisplay方法即可,代码如下所示:

     
    1. - (void)viewDidLayoutSubviews
    2. {
    3. [super viewDidLayoutSubviews];
    4. [self.myView setNeedsDisplay];
    5. }

    但是通常直接将myView的contentMode属性设置为Redraw即可实现绘制布局,相当于调用了上面的代码,将myView的contentMode属性设置为Redraw有两个方法,第一种可以直接通过代码设置,代码如下所示:

    1. - (void)viewDidLoad
    2. {
    3. [super viewDidLoad];
    4. self.myView.contentMode = UIViewContentModeRedraw;
    5. }

    第二种方法可以直接在Stroyboard中设置,右边栏的检查器四中将Mode选项设置为Redraw即可,如图-14所示:

    图-14

    将contentMode设置为Redraw之后就不需要再写布局代码,此时切换屏幕绘制图形就不会失真了。

    4.4 完整代码

    本案例中,TRViewController.m文件中的完整代码如下所示:

     
    1. #import "TRViewController.h"
    2. #import "TRView.h"
    3. @interface TRViewController ()
    4. @property (weak, nonatomic) IBOutlet TRView *myView;
    5. @end
    6. @implementation TRViewController
    7. - (void)viewDidLoad
    8. {
    9. [super viewDidLoad];
    10. self.myView.contentMode = UIViewContentModeRedraw;
    11. }
    12. //- (void)viewDidLayoutSubviews
    13. //{
    14. // [super viewDidLayoutSubviews];
    15. // [self.myView setNeedsDisplay];
    16. //}
    17. @end
     

    本案例中,TRView.m文件中的完整代码如下所示:

     
    1. #import "TRView.h"
    2. @implementation TRView
    3. - (void)drawRect:(CGRect)rect
    4. {
    5. UIBezierPath *path = [UIBezierPath bezierPath];
    6. [path moveToPoint:CGPointMake(20, 20)];
    7. [path addLineToPoint:CGPointMake(20, 120)];
    8. [path addLineToPoint:CGPointMake(120, 20)];
    9. [path closePath];
    10. path.lineWidth = 4;
    11. [[UIColor redColor] setStroke];
    12. [path stroke];
    13. }
    14. @end
     

    5 对乐库项目的播放列表单元格进行布局

    5.1 问题

    视图自身也可以使用布局方法layoutSubviews对自己的子视图进行布局,本案例使用视图的layoutSubviews方法给乐库项目的播放列表单元格进行布局,如图-15所示:

    图-15

    5.2 方案

    首先创建一个SingleViewApplication项目,将Xcode自带的TRViewController类删除,创建一个TRMusicsTableViewController类,继承至UITableViewController,该类有一个NSArray类型的属性musics用于存储歌曲数据源。

    再将Storyboard中自带的场景删除,拖放一个TableViewController到界面中,嵌入一个NavigaitionController。在右边栏的检查器中将TableViewController设置为动态表视图,并和TRMusicsTableViewController类进行绑定。

    其次创建一个带有xib的TRMusicCell类,继承至UITableViewCell,在xib文件中进行自定义cell,往cell的contentView视图上拖放所需要的控件。

    首先在cell的上方拖放一个Label控件,用于显示歌曲的名字。在cell的下方依次拖放两个ImageView控件和两个Label控件,两个ImageView控件分别用于表示歌曲是否为本地歌曲和是否高清。两个Label控件分别用于显示歌曲的信息和时长。

    调整好cell上面各个控件的大小,将个控件关联为TRMusicCell的属性musicNameLabel、albumAndArtistLabel、durationLabel、downloadedImageView以及hdImageView。

    然后再创建一个TRMusic类用于存储歌曲的相关信息,该类继承至NSObject,有五个属性,分别为:

    NSString类型的name,用于记录歌曲名称;

    NSString类型的album,用于记录歌曲所属专辑;

    NSString类型的artist,用于记录歌曲的演唱者;

    NSString类型的duration,用于记录歌曲的时长;

    BOOL类型的highQuality和downloaded,分别用于记录是否高清和是否本地下载。

    我们创建一个TRMusicGroup类,用于生成一组模拟的歌曲数据。

    最后在TRMusicCell类中定义一个TRMusic类型属性music,用于存储单元格需要展示的歌曲。重写layoutSubviews方法,进行cell的界面布局,该方法中会根据每首歌曲的信息,计算子视图的frame进行布局。

    在TRMusicTableViewController类注册Cell,回答三问给表视图加载歌曲数据。

    5.3 步骤

    实现此案例需要按照如下步骤进行。

    步骤一:创建播放列表项目

    首先创建一个SingleViewApplication项目,将Xcode自带的TRViewController类删除,创建一个TRMusicsTableViewController类,继承至UITableViewController,该类有一个NSArray类型的属性musics用于存储歌曲数据源,代码如下所示:

    1. @interface TRMusicTableViewController : UITableViewController
    2. @property (strong, nonatomic) NSArray *musics;
    3. @end

    然后将Storyboard中自带的场景删除,拖放一个TableViewController到界面中,嵌入一个NavigaitionController。在右边栏的检查器中将TableViewController设置为动态表视图,并和TRMusicsTableViewController类进行绑定,如图-16所示:

    图-16

    为了能更灵活的使用自定义cell,由于本案例使用xib的方式进行自定义cell,所以将Storyboard中表视图自带的cell对象删除,如图-17所示:

    图-17

    步骤二:创建TRMusicCell类,自定义Cell

    首先创建一个带有xib的TRMusicCell类,继承至UITableViewCell,在xib文件中进行自定义cell,往cell的contentView视图上拖放所需要的控件。

    先在cell的上方拖放一个Label控件,用于显示歌曲的名字。

    再在cell的下方依次拖放两个ImageView控件和两个Label控件,两个ImageView控件分别用于表示歌曲是否为本地歌曲和是否高清。两个Label控件分别用于显示歌曲的信息和时长。

    设置好cell上面各个控件的大小和属性,如图-18所示:

    图-18

    最后将cell上的各个控件关联为TRMusicCell的属性musicNameLabel、albumAndArtistLabel、durationLabel、downloadedImageView以及hdImageView,代码如下所示:

     
    1. @interface TRMusicCell ()
    2. @property (weak, nonatomic) IBOutlet UILabel *musicNameLabel;
    3. @property (weak, nonatomic) IBOutlet UILabel *albumAndArtistLabel;
    4. @property (weak, nonatomic) IBOutlet UILabel *durationLabel;
    5. @property (weak, nonatomic) IBOutlet UIImageView *downloadedImageView;
    6. @property (weak, nonatomic) IBOutlet UIImageView *hdImageView;
    7. @end

    步骤三:创建TRMusic类和歌曲模拟数据

    首先创建一个TRMusic类用于存储歌曲的相关信息,该类继承至NSObject,有五个属性,分别为:

    NSString类型的name,用于记录歌曲名称;

    NSString类型的album,用于记录歌曲所属专辑;

    NSString类型的artist,用于记录歌曲的演唱者;

    NSString类型的duration,用于记录歌曲的时长;

    BOOL类型的highQuality和downloaded,分别用于记录是否高清和是否本地下载。

    代码如下所示:

     
    1. @interface TRMusic : NSObject
    2. @property (nonatomic, copy) NSString * name;
    3. @property (nonatomic, copy) NSString * album;
    4. @property (nonatomic, copy) NSString * artist;
    5. @property (nonatomic) NSTimeInterval duration;
    6. @property (nonatomic) BOOL highQuality;
    7. @property (nonatomic) BOOL downloaded;
    8. @end

    然后再创建一个TRMusicGroup类,该类提供一个静态方法fakeData,用于生成一组模拟的歌曲数据,代码如下所示:

     
    1. + (NSArray *) fakeData
    2. {
    3. NSMutableArray * musics = nil;
    4. TRMusic * music = nil;
    5. musics = [NSMutableArray array];
    6. music = [[TRMusic alloc] init];
    7. music.name = @"Burn";
    8. music.album = @"Burn - Single";
    9. music.artist = @"Ellie Goulding";
    10. music.duration = [self durationWithMinutes:3 andSeconds:51];
    11. music.downloaded = YES;
    12. music.highQuality = NO;
    13. [musics addObject:music];
    14. music = [[TRMusic alloc] init];
    15. music.name = @"Summertime Sadness (Cedric Gervais Remix)";
    16. music.album = @"Summertime Sadness (Cedric Gervais Remix) - Single";
    17. music.artist = @"Lana Del Rey";
    18. music.duration = [self durationWithMinutes:6 andSeconds:52];
    19. music.downloaded = YES;
    20. music.highQuality = YES;
    21. [musics addObject:music];
    22. music = [[TRMusic alloc] init];
    23. music.name = @"Spectrum";
    24. music.album = @"Clarity";
    25. music.artist = @"Zedd";
    26. music.duration = [self durationWithMinutes:4 andSeconds:3];
    27. music.downloaded = YES;
    28. music.highQuality = YES;
    29. [musics addObject:music];
    30. music = [[TRMusic alloc] init];
    31. music.name = @"It's Time";
    32. music.album = @"It’s Time";
    33. music.artist = @"Imagine Dragons";
    34. music.duration = [self durationWithMinutes:4 andSeconds:0];
    35. music.downloaded = NO;
    36. music.highQuality = YES;
    37. [musics addObject:music];
    38. music = [[TRMusic alloc] init];
    39. music.name = @"Dancing in The Moonlight";
    40. music.album = @"Dancing In The Moonlight: The Best Of Toploader";
    41. music.artist = @"Toploader";
    42. music.duration = [self durationWithMinutes:3 andSeconds:53];
    43. music.downloaded = YES;
    44. music.highQuality = YES;
    45. [musics addObject:music];
    46. music = [[TRMusic alloc] init];
    47. music.name = @"Thinking About You (feat. Ayah Marar)";
    48. music.album = @"18 Months (Deluxe Edition)";
    49. music.artist = @"Calvin Harris";
    50. music.duration = [self durationWithMinutes:4 andSeconds:8];
    51. music.downloaded = YES;
    52. music.highQuality = YES;
    53. [musics addObject:music];
    54. music = [[TRMusic alloc] init];
    55. music.name = @"You Make Me (feat. Salem Al Fakir)";
    56. music.album = @"True";
    57. music.artist = @"Avicii";
    58. music.duration = [self durationWithMinutes:3 andSeconds:51];
    59. music.downloaded = YES;
    60. music.highQuality = NO;
    61. [musics addObject:music];
    62. music = [[TRMusic alloc] init];
    63. music.name = @"Safe and Sound";
    64. music.album = @"Capital Cities EP";
    65. music.artist = @"Capital Cities";
    66. music.duration = [self durationWithMinutes:3 andSeconds:51];
    67. music.downloaded = YES;
    68. music.highQuality = NO;
    69. [musics addObject:music];
    70. music = [[TRMusic alloc] init];
    71. music.name = @"Reaching Out";
    72. music.album = @"Welcome Reality (Deluxe Version)";
    73. music.artist = @"nero";
    74. music.duration = [self durationWithMinutes:3 andSeconds:51];
    75. music.downloaded = YES;
    76. music.highQuality = NO;
    77. [musics addObject:music];
    78. music = [[TRMusic alloc] init];
    79. music.name = @"Recover";
    80. music.album = @"Recover - EP";
    81. music.artist = @"CHVRCHES";
    82. music.duration = [self durationWithMinutes:3 andSeconds:51];
    83. music.downloaded = YES;
    84. music.highQuality = NO;
    85. [musics addObject:music];
    86. music = [[TRMusic alloc] init];
    87. music.name = @"Hold On, We're Going Home (feat. Majid Jordan)";
    88. music.album = @"Hold On, We're Going Home (feat. Majid Jordan) - Single";
    89. music.artist = @"Drake";
    90. music.duration = [self durationWithMinutes:3 andSeconds:51];
    91. music.downloaded = YES;
    92. music.highQuality = NO;
    93. [musics addObject:music];
    94. music = [[TRMusic alloc] init];
    95. music.name = @"The Mother We Share";
    96. music.album = @"The Mother We Share - Single";
    97. music.artist = @"CHVRCHES";
    98. music.duration = [self durationWithMinutes:3 andSeconds:51];
    99. music.downloaded = YES;
    100. music.highQuality = NO;
    101. [musics addObject:music];
    102. music = [[TRMusic alloc] init];
    103. music.name = @"Promises";
    104. music.album = @"nero";
    105. music.artist = @"Promises - EP";
    106. music.duration = [self durationWithMinutes:3 andSeconds:51];
    107. music.downloaded = YES;
    108. music.highQuality = NO;
    109. [musics addObject:music];
    110. music = [[TRMusic alloc] init];
    111. music.name = @"Alone Together";
    112. music.album = @"Save Rock and Roll";
    113. music.artist = @"Fall Out Boy";
    114. music.duration = [self durationWithMinutes:3 andSeconds:51];
    115. music.downloaded = YES;
    116. music.highQuality = NO;
    117. [musics addObject:music];
    118. music = [[TRMusic alloc] init];
    119. music.name = @"Reload (Radio Edit)";
    120. music.album = @"Reload (Radio Edit) - Single";
    121. music.artist = @"Sebastian Ingrosso";
    122. music.duration = [self durationWithMinutes:3 andSeconds:51];
    123. music.downloaded = YES;
    124. music.highQuality = NO;
    125. [musics addObject:music];
    126. music = [[TRMusic alloc] init];
    127. music.name = @"I Love It (feat. Charli XCX)";
    128. music.album = @"Iconic";
    129. music.artist = @"Icona Pop";
    130. music.duration = [self durationWithMinutes:3 andSeconds:51];
    131. music.downloaded = YES;
    132. music.highQuality = NO;
    133. [musics addObject:music];
    134. music = [[TRMusic alloc] init];
    135. music.name = @"Feel the Love";
    136. music.album = @"Feel the Love (feat. John Newman) [Remixes] - EP";
    137. music.artist = @"Rudimental";
    138. music.duration = [self durationWithMinutes:3 andSeconds:51];
    139. music.downloaded = YES;
    140. music.highQuality = NO;
    141. [musics addObject:music];
    142. music = [[TRMusic alloc] init];
    143. music.name = @"Goin' Crazy (feat. Robbie Williams)";
    144. music.album = @"Goin' Crazy (feat. Robbie Williams) - Single";
    145. music.artist = @"Dizzee Rascal";
    146. music.duration = [self durationWithMinutes:3 andSeconds:51];
    147. music.downloaded = YES;
    148. music.highQuality = NO;
    149. [musics addObject:music];
    150. music = [[TRMusic alloc] init];
    151. music.name = @"Still Into You";
    152. music.album = @"Paramore";
    153. music.artist = @"Paramore";
    154. music.duration = [self durationWithMinutes:3 andSeconds:51];
    155. music.downloaded = YES;
    156. music.highQuality = NO;
    157. [musics addObject:music];
    158. music = [[TRMusic alloc] init];
    159. music.name = @"Heart Attack";
    160. music.album = @"Demi";
    161. music.artist = @"Demi Lovato";
    162. music.duration = [self durationWithMinutes:3 andSeconds:51];
    163. music.downloaded = YES;
    164. music.highQuality = NO;
    165. [musics addObject:music];
    166. music = [[TRMusic alloc] init];
    167. music.name = @"Explosions";
    168. music.album = @"Halcyon (Deluxe Edition)";
    169. music.artist = @"Ellie Goulding";
    170. music.duration = [self durationWithMinutes:3 andSeconds:51];
    171. music.downloaded = YES;
    172. music.highQuality = NO;
    173. [musics addObject:music];
    174. music = [[TRMusic alloc] init];
    175. music.name = @"I Need Your Love (feat. Ellie Goulding)";
    176. music.album = @"I Need Your Love";
    177. music.artist = @"Calvin Harris";
    178. music.duration = [self durationWithMinutes:3 andSeconds:51];
    179. music.downloaded = YES;
    180. music.highQuality = NO;
    181. [musics addObject:music];
    182. music = [[TRMusic alloc] init];
    183. music.name = @"Starry Eyed";
    184. music.album = @"Bright Lights";
    185. music.artist = @"Ellie Goulding";
    186. music.duration = [self durationWithMinutes:3 andSeconds:51];
    187. music.downloaded = YES;
    188. music.highQuality = NO;
    189. [musics addObject:music];
    190. music = [[TRMusic alloc] init];
    191. music.name = @"Lights (Single Version)";
    192. music.album = @"Bright Lights";
    193. music.artist = @"Ellie Goulding";
    194. music.duration = [self durationWithMinutes:3 andSeconds:51];
    195. music.downloaded = YES;
    196. music.highQuality = NO;
    197. [musics addObject:music];
    198. music = [[TRMusic alloc] init];
    199. music.name = @"Who's That Chick?";
    200. music.album = @"Who's That Chick - Single";
    201. music.artist = @"David Guetta";
    202. music.duration = [self durationWithMinutes:2 andSeconds:47];
    203. music.downloaded = YES;
    204. music.highQuality = NO;
    205. [musics addObject:music];
    206. TRMusicGroup * g1 = [[TRMusicGroup alloc] init];
    207. g1.name = @"国外单曲";
    208. g1.musics = [musics copy];
    209. g1.state = TRMusicGroupStateDownloaded;
    210. musics = [NSMutableArray array];
    211. music = [[TRMusic alloc] init];
    212. music.name = @"致青春";
    213. music.album = @"致青春";
    214. music.artist = @"王菲";
    215. music.duration = [self durationWithMinutes:3 andSeconds:18];
    216. music.downloaded = NO;
    217. music.highQuality = NO;
    218. [musics addObject:music];
    219. music = [[TRMusic alloc] init];
    220. music.name = @"好汉歌";
    221. music.album = @"六十年代生人";
    222. music.artist = @"刘欢";
    223. music.duration = [self durationWithMinutes:3 andSeconds:41];
    224. music.downloaded = NO;
    225. music.highQuality = YES;
    226. [musics addObject:music];
    227. music = [[TRMusic alloc] init];
    228. music.name = @"忐忑";
    229. music.album = @"自由鸟";
    230. music.artist = @"龚琳娜";
    231. music.duration = [self durationWithMinutes:4 andSeconds:03];
    232. music.downloaded = NO;
    233. music.highQuality = YES;
    234. [musics addObject:music];
    235. music = [[TRMusic alloc] init];
    236. music.name = @"爱情买卖";
    237. music.album = @"我们的爱我不放手";
    238. music.artist = @"慕容晓晓";
    239. music.duration = [self durationWithMinutes:3 andSeconds:31];
    240. music.downloaded = NO;
    241. music.highQuality = YES;
    242. [musics addObject:music];
    243. music = [[TRMusic alloc] init];
    244. music.name = @"法海你不懂爱";
    245. music.album = @"法海你不懂爱 - 单曲";
    246. music.artist = @"龚琳娜";
    247. music.duration = [self durationWithMinutes:3 andSeconds:33];
    248. music.downloaded = NO;
    249. music.highQuality = NO;
    250. [musics addObject:music];
    251. music = [[TRMusic alloc] init];
    252. music.name = @"最炫民族风";
    253. music.album = @"我们的爱我不放手";
    254. music.artist = @"凤凰传奇";
    255. music.duration = [self durationWithMinutes:4 andSeconds:46];
    256. music.downloaded = NO;
    257. music.highQuality = YES;
    258. [musics addObject:music];
    259. music = [[TRMusic alloc] init];
    260. music.name = @"金箍棒";
    261. music.album = @"金箍棒 - 单曲";
    262. music.artist = @"龚琳娜";
    263. music.duration = [self durationWithMinutes:2 andSeconds:52];
    264. music.downloaded = NO;
    265. music.highQuality = NO;
    266. [musics addObject:music];
    267. TRMusicGroup * g2 = [[TRMusicGroup alloc] init];
    268. g2.name = @"国内神曲";
    269. g2.musics = [musics copy];
    270. g2.state = TRMusicGroupStateNormal;
    271. TRMusicGroup * g3 = [[TRMusicGroup alloc] init];
    272. g3.name = @"Calvin Harris 专辑";
    273. g3.musics = @[];
    274. g3.state = TRMusicGroupStateNormal;
    275. TRMusicGroup * g4 = [[TRMusicGroup alloc] init];
    276. g4.name = @"Ellie Gounding 专辑";
    277. g4.musics = @[];
    278. g4.state = TRMusicGroupStateNormal;
    279. return @[g1, g2, g3, g4];
    280. }

    步骤四:进行自定义cell布局

    首先在TRMusicTableViewController类注册Cell,并在TRAppDelegate中对属性musics进行初始化,获取到模拟的歌曲数据,代码如下所示:

    1. //在TRAppDelegate中进行musics属性的初始化
    2. -(BOOL)application:(UIApplication *)application
    3. didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    4. {
    5. NSArray *musicGroups = [TRMusicGroup fakeData];
    6. TRMusicGroup *group = musicGroups[0];
    7. UINavigationController *navi = (UINavigationController *)self.window.rootViewController;
    8. TRMusicTableViewController *musicTVC = (TRMusicTableViewController *) navi.topViewController;
    9. musicTVC.musics = group.musics;
    10. return YES;
    11. }
    12. //在TRMusicsTableViewController中注册cell
    13. - (void)viewDidLoad
    14. {
    15. [super viewDidLoad];
    16. [self.tableView registerNib:[UINib nibWithNibName: @"TRMusicCell" bundle:nil] forCellReuseIdentifier:musicCellIdentifier];
    17. }

    然后在TRMusicCell类中定义一个TRMusic类型属性music,用于存储单元格需要展示的歌曲,代码如下所示:

    1. //TRMusicCell.h文件中定义属性music
    2. @interface TRMusicCell : UITableViewCell
    3. @property (strong, nonatomic) TRMusic *music;
    4. @end

    在TRMusicCell重写layoutSubviews方法,进行cell的界面布局,该方法中会根据每首歌曲的信息,计算子视图的frame进行布局,代码如下所示:

     
    1. - (void)layoutSubviews
    2. {
    3. [super layoutSubviews];
    4. CGFloat x = self.downloadedImageView.frame.origin.x;
    5. if (self.music.downloaded){
    6. x += 20;
    7. }
    8. if (self.music.highQuality) {
    9. CGRect frame = self.hdImageView.frame;
    10. frame.origin.x = x;
    11. self.hdImageView.frame = frame;
    12. x += 20;
    13. }
    14. CGRect frame = self.albumAndArtistLabel.frame;
    15. frame.origin.x = x;
    16. self.albumAndArtistLabel.frame = frame;
    17. }

    歌曲的高清和下载图标需要根据歌曲的相关信息进行显示,可以将此部分功能通过重写music的setter方法来实现,代码如下所示:

     
    1. //TRMusicCell.m文件候中重写music的setter方法
    2. - (void)setMusic:(TRMusic *)music
    3. {
    4. _music = music;
    5. self.musicNameLabel.text = music.name;
    6. self.albumAndArtistLabel.text = [NSString stringWithFormat:@"%@ - %@", music.album, music.artist];
    7. self.durationLabel.text = [NSString stringWithFormat:@"%d:%02d", (int)music.duration/60, (int)music.duration%60];
    8. self.downloadedImageView.hidden = !music.downloaded;
    9. self.hdImageView.hidden = !music.highQuality;
    10. //根据是否高清或下载状态,需要重新布局
    11. [self setNeedsLayout];
    12. }

    最后在TRMusicsTableViewController类中回答三问给表视图加载歌曲数据,并将单元格的行高设置为50,代码如下所示:

    1. -(NSInteger)tableView:(UITableView *)tableView
    2. numberOfRowsInSection:(NSInteger)section
    3. {
    4. return self.musics.count;
    5. }
    6. -(UITableViewCell *)tableView:(UITableView *)tableView
    7. cellForRowAtIndexPath:(NSIndexPath *)indexPath
    8. {
    9. TRMusicCell *cell = [tableView dequeueReusableCellWithIdentifier:musicCellIdentifier forIndexPath:indexPath];
    10. cell.music = self.musics[indexPath.row];
    11. return cell;
    12. }
    13. -(CGFloat)tableView:(UITableView *)tableView
    14. heightForRowAtIndexPath:(NSIndexPath *)indexPath
    15. {
    16. return 50;
    17. }

    5.4 完整代码

    本案例中,TRAppDelegate.m文件中的完整代码如下所示:

     
    1. #import "TRAppDelegate.h"
    2. #import "TRMusicGroup.h"
    3. #import "TRMusicTableViewController.h"
    4. @implementation TRAppDelegate
    5. -(BOOL)application:(UIApplication *)application
    6. didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    7. {
    8. NSArray *musicGroups = [TRMusicGroup fakeData];
    9. TRMusicGroup *group = musicGroups[0];
    10. UINavigationController *navi = (UINavigationController *)self.window.rootViewController;
    11. TRMusicTableViewController *musicTVC = (TRMusicTableViewController *) navi.topViewController;
    12. musicTVC.musics = group.musics;
    13. return YES;
    14. }
    15. @end
     

    本案例中,TRMusicTableViewController.h文件中的完整代码如下所示:

     
    1. #import <UIKit/UIKit.h>
    2. @interface TRMusicTableViewController : UITableViewController
    3. @property (strong, nonatomic) NSArray *musics;
    4. @end
     

    本案例中,TRMusicCell.h文件中的完整代码如下所示:

     
    1. #import <UIKit/UIKit.h>
    2. #import "TRMusic.h"
    3. @interface TRMusicCell : UITableViewCell
    4. @property (strong, nonatomic) TRMusic *music;
    5. @end
     

    本案例中,TRMusicCell.m文件中的完整代码如下所示:

     
    1. #import "TRMusicCell.h
    2. @interface TRMusicCell ()
    3. @property (weak, nonatomic) IBOutlet UILabel *musicNameLabel;
    4. @property (weak, nonatomic) IBOutlet UILabel *albumAndArtistLabel;
    5. @property (weak, nonatomic) IBOutlet UILabel *durationLabel;
    6. @property (weak, nonatomic) IBOutlet UIImageView *downloadedImageView;
    7. @property (weak, nonatomic) IBOutlet UIImageView *hdImageView;
    8. @end
    9. @implementation TRMusicCell
    10. - (void)setMusic:(TRMusic *)music
    11. {
    12. _music = music;
    13. self.musicNameLabel.text = music.name;
    14. self.albumAndArtistLabel.text = [NSString stringWithFormat:@"%@ - %@", music.album, music.artist];
    15. self.durationLabel.text = [NSString stringWithFormat:@"%d:%02d", (int)music.duration/60, (int)music.duration%60];
    16. self.downloadedImageView.hidden = !music.downloaded;
    17. self.hdImageView.hidden = !music.highQuality;
    18. [self setNeedsLayout];//需要重新布局
    19. }
    20. //当当前视图的大小发生变化时调用
    21. - (void)layoutSubviews
    22. {
    23. [super layoutSubviews];
    24. CGFloat x = self.downloadedImageView.frame.origin.x;
    25. if (self.music.downloaded){
    26. x += 20;
    27. }
    28. if (self.music.highQuality) {
    29. CGRect frame = self.hdImageView.frame;
    30. frame.origin.x = x;
    31. self.hdImageView.frame = frame;
    32. x += 20;
    33. }
    34. CGRect frame = self.albumAndArtistLabel.frame;
    35. frame.origin.x = x;
    36. self.albumAndArtistLabel.frame = frame;
    37. }
    38. @end
     

    本案例中,TRMusic.h文件中的完整代码如下所示:

    1. #import <Foundation/Foundation.h>
    2. @interface TRMusic : NSObject
    3. @property (nonatomic, copy) NSString * name;
    4. @property (nonatomic, copy) NSString * album;
    5. @property (nonatomic, copy) NSString * artist;
    6. @property (nonatomic) NSTimeInterval duration;
    7. @property (nonatomic) BOOL highQuality;
    8. @property (nonatomic) BOOL downloaded;
    9. @end
     

    本案例中,TRMusicGroup.h文件中的完整代码如下所示:

     
    1. #import <Foundation/Foundation.h>
    2. #import "TRMusic.h"
    3. typedef NS_ENUM(NSInteger, TRMusicGroupState) {
    4. TRMusicGroupStateNormal,    
    5. TRMusicGroupStateDownloading,        
    6. TRMusicGroupStateDownloaded
    7. };
    8. @interface TRMusicGroup : NSObject
    9. @property (nonatomic, copy) NSString * name;
    10. @property (nonatomic, strong) NSArray * musics;
    11. @property (nonatomic) TRMusicGroupState state;
    12. + (NSArray *) fakeData;
    13. @end
     

    本案例中,TRMusicGroup.m文件中的完整代码如下所示:

     
    1. #import "TRMusicGroup.h"
    2. @implementation TRMusicGroup
    3. + (NSArray *) fakeData
    4. {
    5. NSMutableArray * musics = nil;
    6. TRMusic * music = nil;
    7. musics = [NSMutableArray array];
    8. music = [[TRMusic alloc] init];
    9. music.name = @"Burn";
    10. music.album = @"Burn - Single";
    11. music.artist = @"Ellie Goulding";
    12. music.duration = [self durationWithMinutes:3 andSeconds:51];
    13. music.downloaded = YES;
    14. music.highQuality = NO;
    15. [musics addObject:music];
    16. music = [[TRMusic alloc] init];
    17. music.name = @"Summertime Sadness (Cedric Gervais Remix)";
    18. music.album = @"Summertime Sadness (Cedric Gervais Remix) - Single";
    19. music.artist = @"Lana Del Rey";
    20. music.duration = [self durationWithMinutes:6 andSeconds:52];
    21. music.downloaded = YES;
    22. music.highQuality = YES;
    23. [musics addObject:music];
    24. music = [[TRMusic alloc] init];
    25. music.name = @"Spectrum";
    26. music.album = @"Clarity";
    27. music.artist = @"Zedd";
    28. music.duration = [self durationWithMinutes:4 andSeconds:3];
    29. music.downloaded = YES;
    30. music.highQuality = YES;
    31. [musics addObject:music];
    32. music = [[TRMusic alloc] init];
    33. music.name = @"It's Time";
    34. music.album = @"It’s Time";
    35. music.artist = @"Imagine Dragons";
    36. music.duration = [self durationWithMinutes:4 andSeconds:0];
    37. music.downloaded = NO;
    38. music.highQuality = YES;
    39. [musics addObject:music];
    40. music = [[TRMusic alloc] init];
    41. music.name = @"Dancing in The Moonlight";
    42. music.album = @"Dancing In The Moonlight: The Best Of Toploader";
    43. music.artist = @"Toploader";
    44. music.duration = [self durationWithMinutes:3 andSeconds:53];
    45. music.downloaded = YES;
    46. music.highQuality = YES;
    47. [musics addObject:music];
    48. music = [[TRMusic alloc] init];
    49. music.name = @"Thinking About You (feat. Ayah Marar)";
    50. music.album = @"18 Months (Deluxe Edition)";
    51. music.artist = @"Calvin Harris";
    52. music.duration = [self durationWithMinutes:4 andSeconds:8];
    53. music.downloaded = YES;
    54. music.highQuality = YES;
    55. [musics addObject:music];
    56. music = [[TRMusic alloc] init];
    57. music.name = @"You Make Me (feat. Salem Al Fakir)";
    58. music.album = @"True";
    59. music.artist = @"Avicii";
    60. music.duration = [self durationWithMinutes:3 andSeconds:51];
    61. music.downloaded = YES;
    62. music.highQuality = NO;
    63. [musics addObject:music];
    64. music = [[TRMusic alloc] init];
    65. music.name = @"Safe and Sound";
    66. music.album = @"Capital Cities EP";
    67. music.artist = @"Capital Cities";
    68. music.duration = [self durationWithMinutes:3 andSeconds:51];
    69. music.downloaded = YES;
    70. music.highQuality = NO;
    71. [musics addObject:music];
    72. music = [[TRMusic alloc] init];
    73. music.name = @"Reaching Out";
    74. music.album = @"Welcome Reality (Deluxe Version)";
    75. music.artist = @"nero";
    76. music.duration = [self durationWithMinutes:3 andSeconds:51];
    77. music.downloaded = YES;
    78. music.highQuality = NO;
    79. [musics addObject:music];
    80. music = [[TRMusic alloc] init];
    81. music.name = @"Recover";
    82. music.album = @"Recover - EP";
    83. music.artist = @"CHVRCHES";
    84. music.duration = [self durationWithMinutes:3 andSeconds:51];
    85. music.downloaded = YES;
    86. music.highQuality = NO;
    87. [musics addObject:music];
    88. music = [[TRMusic alloc] init];
    89. music.name = @"Hold On, We're Going Home (feat. Majid Jordan)";
    90. music.album = @"Hold On, We're Going Home (feat. Majid Jordan) - Single";
    91. music.artist = @"Drake";
    92. music.duration = [self durationWithMinutes:3 andSeconds:51];
    93. music.downloaded = YES;
    94. music.highQuality = NO;
    95. [musics addObject:music];
    96. music = [[TRMusic alloc] init];
    97. music.name = @"The Mother We Share";
    98. music.album = @"The Mother We Share - Single";
    99. music.artist = @"CHVRCHES";
    100. music.duration = [self durationWithMinutes:3 andSeconds:51];
    101. music.downloaded = YES;
    102. music.highQuality = NO;
    103. [musics addObject:music];
    104. music = [[TRMusic alloc] init];
    105. music.name = @"Promises";
    106. music.album = @"nero";
    107. music.artist = @"Promises - EP";
    108. music.duration = [self durationWithMinutes:3 andSeconds:51];
    109. music.downloaded = YES;
    110. music.highQuality = NO;
    111. [musics addObject:music];
    112. music = [[TRMusic alloc] init];
    113. music.name = @"Alone Together";
    114. music.album = @"Save Rock and Roll";
    115. music.artist = @"Fall Out Boy";
    116. music.duration = [self durationWithMinutes:3 andSeconds:51];
    117. music.downloaded = YES;
    118. music.highQuality = NO;
    119. [musics addObject:music];
    120. music = [[TRMusic alloc] init];
    121. music.name = @"Reload (Radio Edit)";
    122. music.album = @"Reload (Radio Edit) - Single";
    123. music.artist = @"Sebastian Ingrosso";
    124. music.duration = [self durationWithMinutes:3 andSeconds:51];
    125. music.downloaded = YES;
    126. music.highQuality = NO;
    127. [musics addObject:music];
    128. music = [[TRMusic alloc] init];
    129. music.name = @"I Love It (feat. Charli XCX)";
    130. music.album = @"Iconic";
    131. music.artist = @"Icona Pop";
    132. music.duration = [self durationWithMinutes:3 andSeconds:51];
    133. music.downloaded = YES;
    134. music.highQuality = NO;
    135. [musics addObject:music];
    136. music = [[TRMusic alloc] init];
    137. music.name = @"Feel the Love";
    138. music.album = @"Feel the Love (feat. John Newman) [Remixes] - EP";
    139. music.artist = @"Rudimental";
    140. music.duration = [self durationWithMinutes:3 andSeconds:51];
    141. music.downloaded = YES;
    142. music.highQuality = NO;
    143. [musics addObject:music];
    144. music = [[TRMusic alloc] init];
    145. music.name = @"Goin' Crazy (feat. Robbie Williams)";
    146. music.album = @"Goin' Crazy (feat. Robbie Williams) - Single";
    147. music.artist = @"Dizzee Rascal";
    148. music.duration = [self durationWithMinutes:3 andSeconds:51];
    149. music.downloaded = YES;
    150. music.highQuality = NO;
    151. [musics addObject:music];
    152. music = [[TRMusic alloc] init];
    153. music.name = @"Still Into You";
    154. music.album = @"Paramore";
    155. music.artist = @"Paramore";
    156. music.duration = [self durationWithMinutes:3 andSeconds:51];
    157. music.downloaded = YES;
    158. music.highQuality = NO;
    159. [musics addObject:music];
    160. music = [[TRMusic alloc] init];
    161. music.name = @"Heart Attack";
    162. music.album = @"Demi";
    163. music.artist = @"Demi Lovato";
    164. music.duration = [self durationWithMinutes:3 andSeconds:51];
    165. music.downloaded = YES;
    166. music.highQuality = NO;
    167. [musics addObject:music];
    168. music = [[TRMusic alloc] init];
    169. music.name = @"Explosions";
    170. music.album = @"Halcyon (Deluxe Edition)";
    171. music.artist = @"Ellie Goulding";
    172. music.duration = [self durationWithMinutes:3 andSeconds:51];
    173. music.downloaded = YES;
    174. music.highQuality = NO;
    175. [musics addObject:music];
    176. music = [[TRMusic alloc] init];
    177. music.name = @"I Need Your Love (feat. Ellie Goulding)";
    178. music.album = @"I Need Your Love";
    179. music.artist = @"Calvin Harris";
    180. music.duration = [self durationWithMinutes:3 andSeconds:51];
    181. music.downloaded = YES;
    182. music.highQuality = NO;
    183. [musics addObject:music];
    184. music = [[TRMusic alloc] init];
    185. music.name = @"Starry Eyed";
    186. music.album = @"Bright Lights";
    187. music.artist = @"Ellie Goulding";
    188. music.duration = [self durationWithMinutes:3 andSeconds:51];
    189. music.downloaded = YES;
    190. music.highQuality = NO;
    191. [musics addObject:music];
    192. music = [[TRMusic alloc] init];
    193. music.name = @"Lights (Single Version)";
    194. music.album = @"Bright Lights";
    195. music.artist = @"Ellie Goulding";
    196. music.duration = [self durationWithMinutes:3 andSeconds:51];
    197. music.downloaded = YES;
    198. music.highQuality = NO;
    199. [musics addObject:music];
    200. music = [[TRMusic alloc] init];
    201. music.name = @"Who's That Chick?";
    202. music.album = @"Who's That Chick - Single";
    203. music.artist = @"David Guetta";
    204. music.duration = [self durationWithMinutes:2 andSeconds:47];
    205. music.downloaded = YES;
    206. music.highQuality = NO;
    207. [musics addObject:music];
    208. TRMusicGroup * g1 = [[TRMusicGroup alloc] init];
    209. g1.name = @"国外单曲";
    210. g1.musics = [musics copy];
    211. g1.state = TRMusicGroupStateDownloaded;
    212. musics = [NSMutableArray array];
    213. music = [[TRMusic alloc] init];
    214. music.name = @"致青春";
    215. music.album = @"致青春";
    216. music.artist = @"王菲";
    217. music.duration = [self durationWithMinutes:3 andSeconds:18];
    218. music.downloaded = NO;
    219. music.highQuality = NO;
    220. [musics addObject:music];
    221. music = [[TRMusic alloc] init];
    222. music.name = @"好汉歌";
    223. music.album = @"六十年代生人";
    224. music.artist = @"刘欢";
    225. music.duration = [self durationWithMinutes:3 andSeconds:41];
    226. music.downloaded = NO;
    227. music.highQuality = YES;
    228. [musics addObject:music];
    229. music = [[TRMusic alloc] init];
    230. music.name = @"忐忑";
    231. music.album = @"自由鸟";
    232. music.artist = @"龚琳娜";
    233. music.duration = [self durationWithMinutes:4 andSeconds:03];
    234. music.downloaded = NO;
    235. music.highQuality = YES;
    236. [musics addObject:music];
    237. music = [[TRMusic alloc] init];
    238. music.name = @"爱情买卖";
    239. music.album = @"我们的爱我不放手";
    240. music.artist = @"慕容晓晓";
    241. music.duration = [self durationWithMinutes:3 andSeconds:31];
    242. music.downloaded = NO;
    243. music.highQuality = YES;
    244. [musics addObject:music];
    245. music = [[TRMusic alloc] init];
    246. music.name = @"法海你不懂爱";
    247. music.album = @"法海你不懂爱 - 单曲";
    248. music.artist = @"龚琳娜";
    249. music.duration = [self durationWithMinutes:3 andSeconds:33];
    250. music.downloaded = NO;
    251. music.highQuality = NO;
    252. [musics addObject:music];
    253. music = [[TRMusic alloc] init];
    254. music.name = @"最炫民族风";
    255. music.album = @"我们的爱我不放手";
    256. music.artist = @"凤凰传奇";
    257. music.duration = [self durationWithMinutes:4 andSeconds:46];
    258. music.downloaded = NO;
    259. music.highQuality = YES;
    260. [musics addObject:music];
    261. music = [[TRMusic alloc] init];
    262. music.name = @"金箍棒";
    263. music.album = @"金箍棒 - 单曲";
    264. music.artist = @"龚琳娜";
    265. music.duration = [self durationWithMinutes:2 andSeconds:52];
    266. music.downloaded = NO;
    267. music.highQuality = NO;
    268. [musics addObject:music];
    269. TRMusicGroup * g2 = [[TRMusicGroup alloc] init];
    270. g2.name = @"国内神曲";
    271. g2.musics = [musics copy];
    272. g2.state = TRMusicGroupStateNormal;
    273. TRMusicGroup * g3 = [[TRMusicGroup alloc] init];
    274. g3.name = @"Calvin Harris 专辑";
    275. g3.musics = @[];
    276. g3.state = TRMusicGroupStateNormal;
    277. TRMusicGroup * g4 = [[TRMusicGroup alloc] init];
    278. g4.name = @"Ellie Gounding 专辑";
    279. g4.musics = @[];
    280. g4.state = TRMusicGroupStateNormal;
    281. return @[g1, g2, g3, g4];
    282. }
    283. + (NSTimeInterval) durationWithMinutes:(int)minutes andSeconds:(int)seconds
    284. {
    285. return minutes * 60 + seconds;
    286. }
    287. @end
  • 相关阅读:
    Nginx实战系列之功能篇----后端节点健康检查
    nginx大量TIME_WAIT的解决办法
    Nginx 获取真实 IP 方案
    Redis基本操作——List
    redis-cli 命令总结
    redis 学习笔记-cluster集群搭建
    redis集群部署及常用的操作命令_01
    redis配置文件参数详解
    Redis 主从配置和参数详解
    Tomcat源码分析-开篇(Tomcat源码部署运行 Maven方式)
  • 原文地址:https://www.cnblogs.com/52190112cn/p/5049447.html
Copyright © 2020-2023  润新知