服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - IOS - iOS开发之路--微博骨架搭建

iOS开发之路--微博骨架搭建

2020-12-16 15:05帅哥no微博 IOS

本文是IOS开发之路的第四篇,主要讲诉如何一步步搭建起微博的骨架,并附上源码,希望对大家的IOS开发能提供些借鉴

最终效果图:

iOS开发之路--微博骨架搭建

beyondviewcontroller.m

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
//
// beyondviewcontroller.m
// 20_帅哥no微博
//
// created by beyond on 14-8-3.
// copyright (c) 2014年 com.beyond. all rights reserved.
// 这个就是主控制器,分为两块,下面是dock栏,上面是显示不同的子控制器的view,子控制器最好用导航控制器包装一下,这样子控制器就自带了导航条,左按钮,标题,右按钮
 
/*
 无法点击,或点击 无响应的原因:
 userinteractionenabled = no;
 hidden = yes
 alpha <= 0.01
 clearcolor ,view的颜色为透明,不可以被点击
 */
 
#import "beyondviewcontroller.h"
#import "dock.h"
#import "dockbtn.h"
#import "column.h"
// 主控制器下面dock的高度
#define kdockheight 44
@interface beyondviewcontroller ()
{
  // 从plist中加载 的栏目对象数组
  nsmutablearray *_columns;
  
  // 主控制器下方的dock选项栏
  dock *_dock;
  
  // 记录当前选中的子控制器,目的是将其view从父控制器的view中移除,为添加新的子控制器的view做准备
  uiviewcontroller *_currentchildvc;
}
@end
 
@implementation beyondviewcontroller
 
- (bool)prefersstatusbarhidden
{
  return no;
  
}
 
- (void)viewdidload
{
  [super viewdidload];
 
  // 0.从plist加载 栏目数组,遍历数组,根据字典,生成一个一个栏目对象,存入栏目对象数组中
  _columns = [nsmutablearray array];
  nsbundle *mainbundle = [nsbundle mainbundle];
  nsstring *fullpath = [mainbundle pathforresource:@"columnlist.plist" oftype:nil];
  nsarray *arr = [nsarray arraywithcontentsoffile:fullpath];
  
  for (nsdictionary *dict in arr) {
    column *column = [column columnwithdict:dict];
    [_columns addobject:column];
  }
  // 1.添加dock到主控制器方的下方
  [self adddock];
  
  // 2.一次性创建所有的子控制器,并用导航包装后,添加到当前控制器的childviewcontrollers
  [self createallchildviewcontrollers];
  
  // 3.默认选中第0个控制器
  [self changechildviewatindex:0 andchildvcclassname:@"homeviewcontroller"];
  
  // 4.一次性设置全局的导航栏上面的颜色主题样式
  [self setglobalnavigationitemcolortheme];
  
}
#pragma mark 添加dock
- (void)adddock
{
  // 1.添加dock到主控制器方的下方
  _dock = [[dock alloc] init];
  
  // 2.监听dock内部btn的点击,让控制器成为dock的代理属性,或者,为dock的成员blok赋值
  __unsafe_unretained beyondviewcontroller *beyond = self;
  _dock.btnclickblock = ^(dockbtn *btn)
  {
    // 调用自定义方法,更改子视图,参数1:索引号,参数2:子控制器的类名
    [beyond changechildviewatindex:btn.tag andchildvcclassname:btn.viewcontrollerclassname];
  };
  
  
  // 3,设置dock的frame
  _dock.frame = cgrectmake(0, self.view.frame.size.height - kdockheight, self.view.frame.size.width, kdockheight);
  log(@"_dock frame--%@",nsstringfromcgrect(_dock.frame));
  // 4,添加dock到主控制器方的view
  [self.view addsubview:_dock];
  
  // 2.遍历column对象数组,批量添加dock里面的dockbtn
  for (column *column in _columns) {
    [_dock adddockbtnwithiconname:column.columnimgname title:column.columnname viewcontrollerclassname:column.columnclassname];
  }
  
  // 3.设置dock默认选中第0个
  [_dock setdockbtnclickedatindex:0];
  
}
// 自定义方法,更改子视图,参数1:索引号,参数2:子控制器的类名
- (void)changechildviewatindex:(int)index andchildvcclassname:(nsstring *)viewcontrollerclassname
{
  log(@"点击了 %@",viewcontrollerclassname);
  if (self.childviewcontrollers.count > 0) {
    // 0,先取出新的子控制器,如果 新的子控制器就是当前的这个控制器,直接返回 好吗?
    uiviewcontroller *childvc = [self childviewcontrollers][index];
    if (childvc == _currentchildvc) return ;
    // 1,先移除先前的子控制器的view
    [_currentchildvc.view removefromsuperview];
    
    // 2,添加新的子控制器的view到主控制器的view
    
    childvc.view.frame = cgrectmake(0, 20, 320, 416);
    //log(@"self view --%@",nsstringfromcgrect(self.view.frame));
    //log(@"childvc view --%@",nsstringfromcgrect(childvc.view.frame));
    // 不会重复添加view,因为一旦发现重复添加某个view,就会将它置于最上面,最好是,先移除旧的view,再添加新的view
    [self.view addsubview:childvc.view  ];
    
    // 3,重要,必须更新当前的子控制器,为下次移除做准备
    _currentchildvc = childvc;
  }
}
 
#pragma mark 创建所有的子控制器(一共5个,首面,消息,我,广场,更多)
- (void)createallchildviewcontrollers
{
  // 1.遍历栏目对象数组,批量创建所有的子控制器,并用导航控制器包装,最后添加到self childviewcontrollers数组中保存
  for (column *column in _columns) {
    class c = nsclassfromstring(column.columnclassname);
    uiviewcontroller *childvc =nil;
    if ([nsstringfromclass(c) isequaltostring:@"moreviewcontroller"]) {
      // 特别注意:在继承了tableview之后,要想再使用group样式,必须在创建的时候指定样式为group,这儿特别指的是moreviewcontroller
      childvc = [[c alloc]initwithstyle:uitableviewstylegrouped];
    } else {
      childvc = [[c alloc]init];
    }
    // 设置导航栏的标题
    childvc.navigationitem.title = column.columnname;
    // 重写父类的方法
    [self addchildviewcontroller:childvc];
  }
}
#pragma marck - 重写父类的方法
// 为了在添加子控制器时,全部包装成一个个导航控制器,所以重写addchildviewcontroller方法
- (void)addchildviewcontroller:(uiviewcontroller *)childvc
{
  uinavigationcontroller *nav = [[uinavigationcontroller alloc]initwithrootviewcontroller:childvc];
  // 将包装成导航控制器的子控制器添加到主控制器中,这样每一个子控制器就拥有自己的特有的导航条了
  [super addchildviewcontroller:nav];
}
 
 
// 4.一次性设置全局的导航栏上面的颜色主题样式
- (void)setglobalnavigationitemcolortheme
{
  // 1.导航栏
  // 1.1.操作navbar相当操作整个应用中的所有导航栏
  uinavigationbar *navbar = [uinavigationbar appearance];
  
  // 1.2.设置导航栏uinavigationbar的背景图片(拉伸)
  [navbar setbackgroundimage:[uiimage imagestretchedwithname:@"navigationbar_background.png"] forbarmetrics:uibarmetricsdefault];
  // 1.3.设置状态栏背景,没有效果???
  [uiapplication sharedapplication].statusbarstyle = uistatusbarstylelightcontent;
  
  
  // 1.4.设置导航栏uinavigationbar的title文字属性,通过字典 设置
  nsmutabledictionary *navigationbartitledict = [nsmutabledictionary dictionary];
  // 前景色,即文字的颜色
  [navigationbartitledict setobject:[uicolor darkgraycolor] forkey:nsforegroundcolorattributename];
  // 文字阴影取消,字典中不能放结构体,要用nsvalue包装一下
  [navigationbartitledict setobject:[nsvalue valuewithuioffset:uioffsetzero] forkey:nsshadowattributename];
  
  
  // 2.导航栏上面的item
  uibarbuttonitem *barbtnitem =[uibarbuttonitem appearance];
  // 2.1.设置背景
  // 按钮正常状态时侯的背景
  [barbtnitem setbackgroundimage:[uiimage imagenamed:@"navigationbar_button_background.png"] forstate:uicontrolstatenormal barmetrics:uibarmetricsdefault];
  // 按钮高亮状态时侯的背景
  [barbtnitem setbackgroundimage:[uiimage imagenamed:@"navigationbar_button_background_pushed.png"] forstate:uicontrolstatehighlighted barmetrics:uibarmetricsdefault];
  // 按钮未选中状态时侯的背景
  [barbtnitem setbackgroundimage:[uiimage imagenamed:@"navigationbar_button_background_disable.png"] forstate:uicontrolstatedisabled barmetrics:uibarmetricsdefault];
  
  
  // 2.2.设置barbtnitem的文字属性
  nsmutabledictionary *baritemtitledict = [nsmutabledictionary dictionary];
  // baritemdict的文字颜色
  [baritemtitledict setvalue:[uicolor darkgraycolor] forkey:nsforegroundcolorattributename];
  // baritemdict的字体
  [baritemtitledict setvalue:[uifont systemfontofsize:13] forkey:nsfontattributename];
  
  // 2.3.用字典 设置barbtnitem的标题文字属性
  [barbtnitem settitletextattributes:baritemtitledict forstate:uicontrolstatenormal];
  [barbtnitem settitletextattributes:baritemtitledict forstate:uicontrolstatehighlighted];
}
@end

dock.h

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//
// dock.h
// 20_帅哥no微博
//
// created by beyond on 14-8-3.
// copyright (c) 2014年 com.beyond. all rights reserved.
// dock就是主控制器下面的一条bar,它里面是由一个个按钮dockbtn组成
 
#import <uikit/uikit.h>
@class dockbtn;
@interface dock : uiview
// 添加一个item到dock(view),参数是图标名,和要显示 的标题 ,以及对应的子控制器的类名
 
- (void)adddockbtnwithiconname:(nsstring *)iconname title:(nsstring *)title viewcontrollerclassname:(nsstring *)viewcontrollerclassname;
 
// 当dock里面的某一个按钮被点击了的时候,调用代码块,处理相应的点击事件
@property (copy,nonatomic) void(^btnclickblock)(dockbtn *);
 
 
 
// 自定义方法,通过代码决定哪一个dockbtn被点击了,参数是 dock栏里面的那个将要被点击的按钮的索引
- (void)setdockbtnclickedatindex:(int)index;
@end

dock.m

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//
// dock.m
// 20_帅哥no微博
//
// created by beyond on 14-8-3.
// copyright (c) 2014年 com.beyond. all rights reserved.
// 这个就是主控制器下面那一栏,tabbar,也叫dock,里面有五个按钮,分别是首页,我,消息,广场,更多
 
#import "dock.h"
#import "dockbtn.h"
 
@interface dock()
{
 
  // 当前选中了那个dockbtn
  dockbtn *_currentdockbtn;
}
@end
 
@implementation dock
// init方法内部会调用initwithframne
- (id)initwithframe:(cgrect)frame
{
  self = [super initwithframe:frame];
  if (self) {
    // 固有固定属性,设置dock背景颜色(分类方法,使用imagename就可进行平铺)
    self.backgroundcolor = [uicolor colorwithpatternimagenamed:@"tabbar_background.png"];
  }
  return self;
}
 
// 给外部提供一个接口,添加一个dockbtn(按钮)到dock(view),参数是图标名,和要显示 的标题,以及对应的子控制器的类名
- (void)adddockbtnwithiconname:(nsstring *)iconname title:(nsstring *)title viewcontrollerclassname:(nsstring *)viewcontrollerclassname
{
  // 1.创建dock里面的按钮,并添加到dock里面
  dockbtn *dockbtn = [dockbtn buttonwithtype:uibuttontypecustom];
  [self addsubview:dockbtn];
  
  // 2.设置dockbtn正常状态下显示 的文字
  [dockbtn settitle:title forstate:uicontrolstatenormal];
  
  // 3.分类方法,设置按钮正常和选中状态下的图片,返回图片尺寸
  [dockbtn setbtnimgfornormalandselectedwithname:iconname];
  
  // 4.设置dockbtn对应点击后,要实例化的子控制器的类名
  [dockbtn setviewcontrollerclassname:viewcontrollerclassname];
  
  // 5.监听点击,只要按下就响应,(事件先传递给dock的方法,dock的方法中再通过调用属性block代码块,从而调用到主控制器里面的代码,原因是:在主控制器里面实例化的dock,在dock里面才实例化的dockbtn,因此,主控制器并不知道dockitem的存在)
  [dockbtn addtarget:self action:@selector(dockbtnclick:) forcontrolevents:uicontroleventtouchdown];
  
  // 6.遍历设置dock里面所有按钮的frame (使之平均分布)
  [self setdockbtnframes];
}
 
// 遍历设置dock里面所有按钮的frame (使之平均分布)
- (void)setdockbtnframes
{
  // 1,获取dock里面所有的按钮个数
  int dockbtnnum = self.subviews.count;
  
  // 2,根据dock中,当前当前有多少个dockbtn,计算出每个dockbtn的宽度(self是dock,320*44)
  cgfloat dockbtnwidth = self.frame.size.width / dockbtnnum;
  cgfloat dockbtnheight = self.frame.size.height;
  
  for (int i = 0; i < dockbtnnum; i++) {
    // 1.逐个取出子控件
    dockbtn *btn = self.subviews[i];
    
    // 2.根据索引 计算它的x
    btn.frame = cgrectmake(i * dockbtnwidth, 0, dockbtnwidth, dockbtnheight);
    
    // 3.初始化的时候,将第0个btn(即首页)选中
    if (i == 0) {
      btn.selected = yes;
      // 最重要的是,将选中的,置为当前的按钮,用成员变量记住,当点击dock上button的时候,先将current置为未选中,然后就被点击的按钮选中,最后最重要的是,将被点击的按钮重新置为当前 的按钮,用成员变量记住
      _currentdockbtn = btn;
    }
    
    // 4.因为点击dock里面的按钮的时候,要知道点击了哪一个按钮,所以给每个按钮绑定一个tag,作为它的索引
    btn.tag = i;
  }
}
 
// 最重要的是,当点击dock上button的时候,先将current置为未选中,然后就被点击的按钮选中,最后最重要的是,将被点击的按钮重新置为当前 的按钮,用成员变量记住
- (void)dockbtnclick:(dockbtn *)btn
{
  // 1.让当前的btn取消选中
  _currentdockbtn.selected = no;
  
  // 2.让新的btn选中
  btn.selected = yes;
  
  // 3.最后,让新的btn变为当前选中btn
  _currentdockbtn = btn;
  
  // 4.调用block,即主控制中传递过来的代码块,目的是处理点击之后的实例化对应的子控制器
  if (_btnclickblock) {
    // 将参数 dockbtn传递过去,给主控制器,它里面成员变量记住了它对应的控制器的类名
    _btnclickblock(btn);
  }
}
 
 
 
// 自定义方法,通过代码决定哪一个dockbtn被点击了,参数是 dock栏里面的那个将要被点击的按钮的索引
- (void)setdockbtnclickedatindex:(int)index
{
  // 1.robust判断
  if (index < 0 || index >= self.subviews.count) return;
  
  // 2.通过索引 拿到对应的dockbtn viewwithtag也行
  dockbtn *btn = self.subviews[index];
  
  // 3.手动调用下面方法,相当于用户用手点击了dock里面对应的按钮
  [self dockbtnclick:btn];
}
@end

dockbtn.h

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//
// dockbtn.h
// 20_帅哥no微博
//
// created by beyond on 14-8-4.
// copyright (c) 2014年 com.beyond. all rights reserved.
// 一个dockbtn代表dock上面的一个按钮,它有个成员是对应子控制器的类名,比如home按钮,成员属性的值就是叫:homeviewcontroller
 
#import <uikit/uikit.h>
 
@interface dockbtn : uibutton
// 每个dockbtn中,用一个成员记住 它对应的控制器的类名
@property (nonatomic,copy) nsstring *viewcontrollerclassname;
@end

dockbtn.m

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//
// dockbtn.m
// 20_帅哥no微博
//
// created by beyond on 14-8-4.
// copyright (c) 2014年 com.beyond. all rights reserved.
// 一个dockbtn代表dock上面的一个按钮,它有个成员是对应子控制器的类名,比如home按钮,成员属性的值就是叫:homeviewcontroller
 
#import "dockbtn.h"
 
// 按钮的内容的总宽度
#define kbtncontentwidth contentrect.size.width
// 按钮的内容的总高度
#define kbtncontentheight contentrect.size.height
 
// 按钮里的图片的所占的高度比例
#define kimageheightratio 0.6
// 按钮里的文本标签的所占的高度比例
#define klabelheightratio (1- kimageheightratio)
 
@implementation dockbtn
 
// 一些默认的通用的属性一定要写在构造方法里面
- (id)initwithframe:(cgrect)frame
{
  self = [super initwithframe:frame];
  if (self) {
    // 1.设置按钮文字属性 (局中,字体大小)
    self.titlelabel.textalignment = nstextalignmentcenter;
    self.titlelabel.font = [uifont systemfontofsize:12];
    
    // 2.设置按钮图片属性 (放大模式,取消按钮默认的点击高亮时的变色)
    self.imageview.contentmode = uiviewcontentmodescaleaspectfit;
    // 取消按钮默认的点击高亮时的变色(image is drawn darker when highlighted or pressed)
    self.adjustsimagewhenhighlighted = no;
    
    // 3.分类方法,设置按钮选中时的背景
    [self setbgimgforselected:@"tabbar_slider.png"];
  }
  return self;
}
 
#pragma mark 重写父类的方法(覆盖父类在高亮时所作的行为)
- (void)sethighlighted:(bool)highlighted
{
  // 因为 这里只需用按钮的选中和默认状态时的图片,所以要取消高亮状态的一些默认变色行为
  // 这里什么也不写,即取消,按钮本身 在高亮的时候执行的那些行为
  
}
 
 
#pragma mark 返回是按钮内部uiimageview的边框(按钮中的图片在上方,居中)
- (cgrect)imagerectforcontentrect:(cgrect)contentrect
{
  // 要居中,最快办法就是让按钮中的图片宽度和按钮一样宽
  return cgrectmake(0, 0, kbtncontentwidth, kbtncontentheight * kimageheightratio);
}
 
#pragma mark 返回是按钮内部uilabel的边框(按钮中的文字在下方,居中)
- (cgrect)titlerectforcontentrect:(cgrect)contentrect
{
  // 要居中,最快办法就是让按钮中的label宽度和按钮一样宽
  
  // 文字的y位于图片的下边线的上方5个单位距离,即距离图片上方5
  cgfloat labely = kbtncontentheight * kimageheightratio - 5;
  // 文字的高度是占按钮余下的所有高度
  cgfloat labelheight = kbtncontentheight - labely;
  return cgrectmake(0, labely, kbtncontentwidth, labelheight);
}
 
@end

模型column.h

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//
// column.h
// 20_帅哥no微博
//
// created by beyond on 14-8-4.
// copyright (c) 2014年 com.beyond. all rights reserved.
// 1个column模型对应dock上面的一个按钮,类别
 
#import <foundation/foundation.h>
 
// 数据模型 代表一个栏目
@interface column : nsobject
 
// 栏目名称
@property (nonatomic,copy)nsstring *columnname;
// 栏目图片名称
@property (nonatomic,copy)nsstring *columnimgname;
// 栏目对应的控制器的类名
@property (nonatomic,copy)nsstring *columnclassname;
// ui控件用weak,字符串用copy,其他对象用strong
 
// 提供一个类方法,即构造函数,返回封装好数据的对象(返回id亦可)
+ (column *)columnnamed:(nsstring *)columnname imgname:(nsstring*)columnimgname classname:(nsstring *)columnclassname;
 
// 类方法,字典 转 对象 类似javabean一次性填充
+ (column *)columnwithdict:(nsdictionary *)dict;
 
// 对象方法,设置对象的属性后,返回对象
- (column *)initwithdict:(nsdictionary *)dict;
 
@end

模型column.m

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//
// column.m
// 20_帅哥no微博
//
// created by beyond on 14-8-4.
// copyright (c) 2014年 com.beyond. all rights reserved.
//
 
#import "column.h"
 
@implementation column
// 返回一个包含了 栏目对应控制器名字的 对象实例
+ (column *)columnnamed:(nsstring *)columnname imgname:(nsstring *)columnimgname classname:(nsstring *)columnclassname
{
  // 为了兼容子类 使用self
  column *column = [[self alloc]init];
  column.columnname = columnname;
  column.columnimgname = columnimgname;
  column.columnclassname = columnclassname;
  return column;
}
 
 
// 类方法,字典 转 对象 类似javabean一次性填充
+ (column *)columnwithdict:(nsdictionary *)dict
{
  // 只是调用对象的initwithdict方法,之所以用self是为了对子类进行兼容
  return [[self alloc]initwithdict:dict];
}
 
// 对象方法,设置对象的属性后,返回对象
- (column *)initwithdict:(nsdictionary *)dict
{
  // 必须先调用父类nsobject的init方法
  if (self = [super init]) {
    // 设置对象自己的属性
    [self setvaluesforkeyswithdictionary:dict];
  }
  // 返回填充好的对象
  return self;
}
 
@end

dock里面的五个栏目按钮的数据来源columnlist.plist

iOS开发之路--微博骨架搭建

延伸 · 阅读

精彩推荐
  • IOSiOS 雷达效果实例详解

    iOS 雷达效果实例详解

    这篇文章主要介绍了iOS 雷达效果实例详解的相关资料,需要的朋友可以参考下...

    SimpleWorld11022021-01-28
  • IOSIOS开发之字典转字符串的实例详解

    IOS开发之字典转字符串的实例详解

    这篇文章主要介绍了IOS开发之字典转字符串的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握这样的方法,需要的朋友可以参考下...

    苦练内功5832021-04-01
  • IOSIOS 屏幕适配方案实现缩放window的示例代码

    IOS 屏幕适配方案实现缩放window的示例代码

    这篇文章主要介绍了IOS 屏幕适配方案实现缩放window的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    xiari5772021-06-01
  • IOSiOS布局渲染之UIView方法的调用时机详解

    iOS布局渲染之UIView方法的调用时机详解

    在你刚开始开发 iOS 应用时,最难避免或者是调试的就是和布局相关的问题,下面这篇文章主要给大家介绍了关于iOS布局渲染之UIView方法调用时机的相关资料...

    windtersharp7642021-05-04
  • IOS解析iOS开发中的FirstResponder第一响应对象

    解析iOS开发中的FirstResponder第一响应对象

    这篇文章主要介绍了解析iOS开发中的FirstResponder第一响应对象,包括View的FirstResponder的释放问题,需要的朋友可以参考下...

    一片枫叶4662020-12-25
  • IOSiOS中tableview 两级cell的展开与收回的示例代码

    iOS中tableview 两级cell的展开与收回的示例代码

    本篇文章主要介绍了iOS中tableview 两级cell的展开与收回的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    J_Kang3862021-04-22
  • IOSiOS通过逆向理解Block的内存模型

    iOS通过逆向理解Block的内存模型

    自从对 iOS 的逆向初窥门径后,我也经常通过它来分析一些比较大的应用,参考一下这些应用中某些功能的实现。这个探索的过程乐趣多多,不仅能满足自...

    Swiftyper12832021-03-03
  • IOS关于iOS自适应cell行高的那些事儿

    关于iOS自适应cell行高的那些事儿

    这篇文章主要给大家介绍了关于iOS自适应cell行高的那些事儿,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    daisy6092021-05-17