"百思不得姐"项目小结(更新中)

1.tableview的底部灰线延长到边:

//方法一:(iOS8以上)

self.tableView,separatorInset = UIEdgeInsetsZero;//清除tableView分割线内边距 

cell的初始化方法里写:  self.layoutMargins = UIEdgeInsetsZero;//清空cell的约束边缘

//方法二:

self.tableView.separatorStyle= UITableViewCellSeparatorStyleNone;//取消tableview的分割线

self.tableView.backgroundColor = [UIColor lightGrayColor];//设置tableView的背景色(=cell的背景色)

- (void)setFrame:(CGRect)frame{//cell 重写setFrame方法

      frame.size.height-=1;

      // 才是真正去给cell赋值

      [super setFrame:frame];

}

2.cell圆角图片优化(剪切图片)

[_iconView sd_setImageWithURL:[NSURL URLWithString:item.image_list]placeholderImage:[UIImageimageNamed:@"defaultUserIcon"]options:SDWebImageCacheMemoryOnlycompleted:^(UIImage*image,NSError*error,SDImageCacheTypecacheType,NSURL*imageURL) {

// 1.开启图形上下文

// 比例因素:当前点与像素比例

UIGraphicsBeginImageContextWithOptions(image.size,NO,0);

// 2.描述裁剪区域

UIBezierPath*path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0,0, image.size.width, image.size.height)];

// 3.设置裁剪区域;

[path addClip];

// 4.画图片

[image drawAtPoint:CGPointZero];

// 5.取出图片

image =UIGraphicsGetImageFromCurrentImageContext();

// 6.关闭上下文

UIGraphicsEndImageContext();

_iconView.image= image;

}];

1.  [[UIColor whiteColor]colorWithAlphaComponent:0.5]

2  // scrollView 默认内间距向下64,它上面的控件自动在y=64的位置

3.  // 按钮里面的属性控件是懒加载的,只有设置相关属性才会创建

4.  加载三方bundle里的图片,需要加上bundle的文件名,格式:bundle文件名/图片名, 比如[UIImage imageName:@“SVProgressHUD.bundle/error”]

5. 自定义构造方法:

@property int age;

@property NSString *name;

//自定义构造方法 在初始化的时候为属性"年龄"和"姓名"赋值

- (instancetype)initWithAge:(int)age andName:(NSString *)name;

实现

// 实现自定义构造函数 在初始化的时候为属性赋值

 - (id)initWithAge:(int)age andName:(NSString *)name

{

  if (self = [super init]) {

    _age = age;

    _name = name;

}

return self;

}

6.

//标题按钮

BDJTitleButton* firstTitleButton = self.titlesView.subviews.firstObject; 

titleUnderline.backgroundColor =[firstTitleButton titleColorForState:UIControlStateSelected];//下划线取button选中时的颜色

7. iOS里是控件准备显示的时候才去计算控件尺寸

8. self.tableView.contentInset = UIEdgeInsetMake(40,0,0,0);//设置内边距,不设置默认内边距64

9.  //加载xib控件

    UIView*testView = [[NSBundle mainBundle]loadNibNamed:@"TestView" owner:nil options:nil].firstObject;

    [self.viewaddSubview:testView];

10. Xib 编译后会变成 Nib, bundle是放一下不需要编译的资源,bundle一般是放图片

11.  cell的全屏穿透 `

    self.tableView.contentInset= UIEdgeInsetsMake(64, 0, 49, 0);

12.  普通的UIViewController 的默认frame 是 {{0,0},{375,667}}

      TableViewController的默认 frame 是 {{0,20},{375,647}}  //这20 是状态栏的高度

13.  ViewWithTag 递归查找(包括自己),也就说如果当前view也包含这个tag值,就不会采用子View的tag值对应的对象,所以要小心tag为0的情况

14.tableView的重要特性分析:

    frame.size.height  tableView自身的高度

    contentSize.height所有内容的高度,内容: 1.有cell 2.没有contentInset 3.有tableHeaderView、tableFooterView

    contentOffset.y == frame顶部和contentSize顶部 的差值(相减后的值)

也就是说:

       contentInset: 在内容周围增加额外的间距(内边距),始终会粘着内容;

    contentOffset:内容距离frame矩形框,偏移了多少;

       有没有内边距跟contentOffset和 contentSize没关系;

15. frame : 是以父控件内容的左上角为坐标原点(0,0)

     bounds: 是以自己的内容左上角x,y距离本身矩形框的x,y

16. view用到的时候再创建,//所以让他在点击标题按钮的时候再创建

    /**

 *  添加第index个子控制器的view到scrollView中

 */

- (void)addChildVcViewIntoScrollView:(NSUInteger)index

{

    UIViewController *childVc = self.childViewControllers[index];


    // 如果view已经被加载过,就直接返回

    if(childVc.isViewLoaded)return;


    //取出index位置对应的子控制器view

    UIView*childVcView = childVc.view;


    //设置子控制器view的frame

    CGFloat scrollViewW = self.scrollView.kris_width;

    childVcView.frame=CGRectMake(index * scrollViewW, 0, scrollViewW,self.scrollView.kris_height);

    //添加子控制器的view到scrollView中

    [self.scrollViewaddSubview:childVcView];

}

17. 状态栏盖在Window上面

18.  [UIApplication sharedApplication].delegate; 就是APPDelegate的self

19.    //让Appledelegate成为tabBar的代理,防止跳转其它界面被销毁,因为Applegate会一直存在,监听点击事件

    //如果有黄色警告,是因为要Application遵循tabBar的协议,所以要强制转换一下告诉tabBar是遵循这个协议的

    tabBarVC.delegate=(id)[UIApplication sharedApplication].delegate;

20.一个Xib可以描述很多个View

21. 登录注册两个View放在一个bigView上,点击切换注册按钮时,移动下面bigView的位置

22. 

// viewDidLayoutSubviews:才会根据布局调整控件的尺寸

- (void)viewDidLayoutSubviews

{

    // 一定要调用super  开发中一般在这个方法里设置布局,这个方法会被调用给你多次

    [super viewDidLayoutSubviews];

}

23.    //在封装UITextField,监听开始编辑事件

    [self addTarget:self action:@selector(textBegin) forControlEvents:UIControlEventEditingDidBegin];

24 宏: #紧跟着后面的字符加一个双引号,定义宏时 @#aaa 就是@“aaa”

      ##是链接符号 比如abc##fileName 就是 abcfileName

25.  [array addObjectsFromArray: arrayTwo]; //把arrayTwo数组里的元素,添加到array数组元素后面

26. @property(nonatomic,assign,getter=isFooterRefreshing)BOOLfooterRefreshing; //通常我们可以用getter来定义一个自己喜欢的名字

27. 下一页,页码发给服务器逻辑(上拉刷新) : 

    //    parameters[@"page"] = @(self.page + 1);

    [mgrGET:KrisCommonURL parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {

        //存储maxtime

        self.maxtime= responseObject[@"info"][@"maxtime"];


        //字典数组->模型数据

        NSArray *moreTopics = [BDJTopic mj_objectArrayWithKeyValuesArray:responseObject[@"list"]];

        //累加到旧数组的后面

        [self.topics addObjectsFromArray:moreTopics];


        // 刷新表格

        [self.tableView reloadData];


        // 结束刷新

        [self footerEndRefreshing];


        //        self.page = [parameters[@"page"] integerValue];

    }failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

        [SVProgressHUD showErrorWithStatus:@"网络繁忙,请稍后再试!"];


        // 结束刷新

        [self footerEndRefreshing];


        //        self.page--;

    }];

28. //把oldArray数组的元素存储到 newArray 里从索引0开始存储,也就是存储到最前面

        [self.newArray insertObjects:oldArray atIndexes:[NSIndexSet indexSetWithIndex:0]];

29. 服务器数据不怎么变的时候,可以传页码;很多公司不传页码,因为服务器经常有新数据的话,会蹩脚;

      所以很多公司要求发最后一条数据的id给它来刷新数据,这样就不会出现数据断层

     // 所以要判断一下,已有数据是否是最新数据,然后再下拉刷新判断:拿记录下的第一条数据的id进行请求

 //发送请求给服务器,下拉刷新数据

- (void)loadNewTopics

{

    // 1.取消之前的请求

    // 取消所有的请求,并且关闭session(注意:一旦关闭了session,这个manager再也无法发送任何请求)

//    [self.manager invalidateSessionCancelingTasks:YES];

    [self.manager.tasks makeObjectsPerformSelector:@selector(cancel)];

//    [self footerEndRefreshing];


    // 2.拼接参数

    NSMutableDictionary *parameters = [NSMutableDictionary dictionary];

    parameters[@"a"] =@"list";

    parameters[@"c"] =@"data";

    parameters[@"type"] =@"31";

    parameters[@"mintime"] = @"5345345";


    // 3.发送请求

    [self.manager GET:XMGCommonURL parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {

        //存储maxtime

        self.maxtime= responseObject[@"info"][@"maxtime"];


        // //新数据直接覆盖之前数据

        self.topics = [XMGTopic mj_objectArrayWithKeyValuesArray:responseObject[@"list"]];

 //      if(self.topics){

 //          //把这个数组的元素从零存储到topics里

 //          [self.topics insertObjects:newTopics atIndexes:[NSIndexSet indexSetWithIndex:0]];

 //      }else{

 //          //新数据 直接覆盖之前数据

 //          self.topics=newTopics;

 //      }


        // 刷新表格

        [self.tableView reloadData];


        // 结束刷新

        [self headerEndRefreshing];

    }failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

        if (error.code != NSURLErrorCancelled) { //并非是取消任务导致的error,其他网络问题导致的error

            [SVProgressHUD showErrorWithStatus:@"网络繁忙,请稍后再试!"];

        }


        // 结束刷新

        [self headerEndRefreshing];

    }];

}

30.

    // 取消之前所有的请求

    // 取消所有的请求,并且关闭session(注意:一旦关闭了session,这个manager再也无法发送任何请求)

    //    [self.manager invalidateSessionCancelingTasks:YES];

    [self.manager.tasks makeObjectsPerformSelector:@selector(cancel)];

    //执行了这个方法后,会来到failure的block

31.  几个cell相同的属性提取出来,创建一个父cell

          XIb没有继承的特性,只能纯代码

32. 枚举

//typedef enum {

//    /**全部*/

//    XMGTopicTypeAll = 1,

//    /**图片*/

//    XMGTopicTypePicture = 10,

//    /**段子*/

//    XMGTopicTypeWord = 29,

//    /**声音*/

//    XMGTopicTypeVoice = 31,

//    /**视频*/

//    XMGTopicTypeVideo = 41

//} XMGTopicType;

typedefNS_ENUM(NSUInteger, XMGTopicType) {//使用枚举,参数可以说明枚举类型

    /**全部*/

    XMGTopicTypeAll = 1,

    /**图片*/

    XMGTopicTypePicture = 10,

    /**段子*/

    XMGTopicTypeWord = 29,

    /**声音*/

    XMGTopicTypeVoice = 31,

    /**视频*/

    XMGTopicTypeVideo = 41

};

32. Control + command +空格弹出表情文字标签键盘

       Control + Command +⬆️/⬇️切换.m和.h

33.  控件的命名 —> 功能 + 控件类型

34.  // 注册nibcell

    UINib *nib = [UINib nibWithNibName:NSStringFromClass([XMGTopicCell class]) bundle:nil];

    [self.tableView registerNib:nib forCellReuseIdentifier:XMGTopicCellId];

35. 图片上下左右边不拉伸,中间拉伸

      找到图片选择 slices >> Horizontal and Vertical >>然后告诉图片上下左右哪些区域需要保护起来

      或者 下面选择平铺/拉伸(最好要保证中间是纯色的)的范围

36. 调用方法时,左边有中文参数时,右边参数是没有提示的

37. 点击”前往” >> 按住option键 >> 会出来”资源库”等其他文件夹

38. 

/*

 插件的安装路径

 1.旧版本路径:/Users/用户名/Library/Application Support/Developer/Shared/Xcode/Plug-ins

 2.新版本路径:/Users/用户名/Library/Developer/Xcode/Plug-ins

 */

39. 想修改插件的话, 找到插件 >> Resource >> 更改Completion.plist文件 

40. 图片浏览插件 KSImage 

41. 公司需求要cell一种悬浮的效果: 

- (void)setFrame:(CGRect)frame

{

    frame.size.height-=10;


    [supersetFrame:frame];

}

42. [UIFont systemFontOfSize:15].lineHeight; //一行文字的高度

43. xib里面Lable有个line Breaks选项,可以设置超出内容的部分怎么显示(省略号的位置),比如:让英文字母在label字母可以拆分显示下一行时可选择CharacterWrap

       在纯代码开发中换行模式是: label.lineBreakMode = NSLineBreakByCharWrapping;

44. 

 1>每次刷新表格时,有多少数据,这个方法就一次性调用多少次(比如有100条数据,每次reloadData时,这个方法就会一次性调用100次)

 2>每当有cell进入屏幕范围内,就会调用一次这个方法

//每次都调用这个方法为了计算contentSize

- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath;

所以要缓存cell的高度

方法一: 用计算后的高度作为模型的一个属性

- (CGFloat)cellHeight

{

    // 如果已经计算过,就直接返回

    if (_cellHeight) return _cellHeight;


    //文字的Y值

    _cellHeight += 55;


    //文字的高度

    CGSizetextMaxSize =CGSizeMake(XMGScreenW- 2 *XMGMarin,MAXFLOAT);

    _cellHeight += [self.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:15]} context:nil].size.height + XMGMarin;


    //工具条

    _cellHeight += 35 + XMGMarin;


    return _cellHeight;

}

方法二: 估算高度(如果展示滚动条不推荐此方法) 优点: heightForRow只是在用到的时候才调用进行cell高度计算,不会每次都调用

    //设置cell的估算高度(每一行大约都是estimatedRowHeight)

    self.tableView.estimatedRowHeight = 100;

缺点:滚动条长度不准确,不稳定,甚至卡顿效果,cellForRow和heightForRow的执行顺序也会发生变化,会先cellForRow

45.autoresizing 和 autolayout 是不能共存的.

     一般情况下,以下这些view的autoresizingMask默认就是18(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth)

 1.从xib里面创建出来的默认控件

 2.控制器的view

 如果不希望控件拥有autoresizingMask的自动伸缩功能,应该设置为none

 blueView.autoresizingMask = UIViewAutoresizingNone;

46. 懒加载: eg

- (XMGTopicVideoView *)videoView

{

    if (!_videoView) {

        XMGTopicVideoView *videoView = [XMGTopicVideoView xmg_viewFromXib];

        [self.contentViewaddSubview:videoView];

        _videoView= videoView;

    }

    return _videoView;

}

47.- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath ;这个方法执行之后才调用cell的- (void)layoutSubviews;

48. 

/* iOS 9之前会报错

 如果错误信息里面包含了:NaN,一般都是因为除0造成(比如x/0)

 (NaN : Not a number)

 */

49. 有些人想 imageView里面添加 button 和label 和 label,但是不建议这么做,最后是用UIView和UIScrollView, Xib不接受这种做法因为这些控件里面本身就有控件,可能影响这些控件里的功能和排布,这些控件也是继承UIView控件的集合

50. xib 不设置宽高,让它朝一个方向对齐,控件会自动计算宽高

51.  // %.3f 小数点有保留三位小数      // %04d : 占据4位,多余的空位用0填补

52.   在 appDelegata.m开始监控网络状态

    // 开始监控网络状况

    [[AFNetworkReachabilityManager sharedManager] startMonitoring];

使用AFN获取网络状态: 

AFNetworkReachabilityManager *mgr = [AFNetworkReachabilityManager sharedManager]; 

    mgr.isReachableViaWiFi/mgr.isReachableViaWWAN / else

53.  // 获得缓存中原图(SDWebImage的图片缓存是用图片的url字符串作为key)

    UIImage *originImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:topic.image1URL];

54.点语法要想提示必须有方法声明

55.  @"foo" =  @("foo")

56. 查看图片有三种情况: 长图 动图 原图. 把这些情况都加载都一个cell上,通过网路返回字段来判断显示哪些控件

57.  // 控制Button内部的子控件对齐,不是用contentMode,是用以下2个属性

    btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;

    btn.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;


    // 控件Button内部子控件之间的间距

    btn.contentEdgeInsets = UIEdgeInsetsMake(10, 0, 0, 0);//button里面控件整体(文字+图片),上部空出10的内边距

    btn.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);//button文字左边空出10的内边距(往右挪动10)

    btn.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 10);// button图片右边空出10的内边距(往左边挪动10)

//注意: 两个控件分别左右挪动相同的距离,这样显示 两个控件依然居中

58. 按住option键 点击想要右侧展示的.m文件,会在Xib想拖线时快速定位到你想右侧想展示的.m文件

59. [string hasSuffix:@"gif”]; //string是否以gif结尾 

      [string hasPrefix:@"gif”]; //string是否以gif开头

      [string.lowercaseString hasSuffix:@"gif”]; // string里的字符统一转换小写后是否以gif结尾

   [string.uppercaseString hasSuffix:@"gif"]; // string里的字符统一转换大写后是否以gif开头

      [string.pathExtension.lowercaseString isEqualToString:@"gif”]; //string拓展名转小写后是否等于 gif


60.对于图片的data来说,它的首字节是来描述图片类型的:比如SDWebImage用来图片下载完毕后判读图片类型的方法

+ (NSString*)sd_contentTypeForImageData:(NSData*)data {//这个方法使用于后台返回的图片加载链接是 //http:www.abc.com/test 这种没有后缀的情况

    uint8_t c;

    [datagetBytes:&clength:1];//获取图片首字节赋值给c

    switch(c) {

        case0xFF:

            return@"image/jpeg";

        case0x89:

            return@"image/png";

        case0x47:

            return@"image/gif";

        case0x49:

        case0x4D:

            return@"image/tiff";

        case0x52:

            // R as RIFF for WEBP

            if([datalength] < 12) {

                returnnil;

            }

            NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];

            if([testStringhasPrefix:@"RIFF"] && [testStringhasSuffix:@"WEBP"]) {

                return@"image/webp";

            }

            returnnil;

    }

    return nil;

}

61.    self.imageView.contentMode = UIViewContentModeTop;//图片触顶,图片是不会拉伸图片的

        self.imageView.clipsToBounds = YES; //多余部分减掉

62. 

    //清除内存缓存

    [[SDImageCache sharedImageCache] clearMemory];

    // 设置缓存时长为1个月

    [SDImageCache sharedImageCache].maxCacheAge = 30 * 24 * 60 * 60;


    // 清除沙盒中所有使用SD缓存的过期图片(缓存时长 > 一个星期)

    [[SDImageCache sharedImageCache] cleanDisk];


    // 清除沙盒中所有使用SD缓存的图片

    [[SDImageCache sharedImageCache] clearDisk];

63.  SDWebImage其实缓存存储设置是以 字典的形式存储的,key绑定image,key对image强引用,清除内存缓存的原理是清除key,自然内存中的image也会被销毁

    cell图片 离开屏幕没有被强引用的话就会被销毁,后面再进来的时候回先从内存中加载看是否存在图片,不存在的话在沙盒中查找图片

64. FPS就是一秒钟渲染多少帧 Frame Per Second = FPS,值最佳为60左右,这个值是小于60代表卡顿. demo检测好的三方有YYFPSLabel

65. 保存图片到相册: 1> 保存图片到[相机胶卷] 2> 创建一个属于自己的相册  3>将刚才保存到[相机胶卷中的图片引用到[自定义相册] 

66. 

 使用weak和assign修饰OC对象的区别

 1>成员变量

 1) weak生成的成员变量是用__weak修饰的,比如XMGCat * __weak _cat;

 2) assign生成的成员变量是用__unsafe_unretained修饰的XMGCat * __unsafe_unretained _cat;

 2> __weak和__unsafe_unretained

 1)都不是强指针(不是强引用),不能保住对象的命

 2) __weak :所指向的对象销毁后,会自动变成nil指针(空指针),不再指向已经销毁的对象

 3) __unsafe_unretained :所指向的对象销毁后,仍旧指向已经销毁的对象

67. 模态弹出: 用现在所在的window最好拿的就是根控制器

 [self.window.rootViewController presentViewController:vc animated:YEScompletion:nil];

或者

 [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:vc animated:YES completion:nil]; (推荐)

68.[self.viewinsertSubview:scrollViewatIndex:0]; //放在所有子控制器view的最前面

69. 一种常见的布局适配中开发步骤:

     sp1.在viewDidLoad方法中添加初始化子控件

     sp2.在viewDidLayoutSubviews方法中布局子控件(设置子控件的位置和尺寸) 

      另一种常见的开发思路:

         sp1.  控件弄成懒加载

         sp2. 在viewDidLayoutSubviews方法中布局子控件(设置子控件的位置和尺寸) 

70.   // 图片缩小放大

    self.imageView= imageView;

    CGFloatmaxScale =width/ imageView.kris_width;

    if(maxScale > 1) {

        scrollView.maximumZoomScale= maxScale;// 设置最大放大比例

        scrollView.delegate=self;

    }

#pragma mark -

- (UIView*)viewForZoomingInScrollView:(UIScrollView*)scrollView

{

    return self.imageView;

}

71. 

   [[NSBundlemainBundle]pathForResource:@"Info"ofType:@"plist"]; //普通.plist文件内的信息用这个方法就可以获取到内容

   [NSBundlemainBundle].infoDictionary[@"CFBundleName"]; //获取系统的.plist文件内容用这种方法

72.  设置模拟器运行显示语言: sp1 在模拟器设置语言为简体中文  sp2 点击蓝色文件夹>>右侧点击蓝色文件夹 >> 在”Localizations” 点击 “+” >> 加上简体中文再运行就可以了

73. UI_USER_INTERFACE_IDIOM() = UIUserInterfaceIdiomPad;//当前设备运行的是平板

74. 父类不应该依赖于子类,抽成属性/get方法,供子类赋值.get方法供子类重写更好些

     子类利用变量get方法重写返回了一个值给父类

75. 封装: 1.组合类  2.继承(依赖性很强)

76. [self.tableView.mj_footer endRefreshingWithNoMoreData]; //结束刷新,不再加载新数据,并提醒加载完毕

77. 框架建议使用者子类化第三方框架

你可能感兴趣的:("百思不得姐"项目小结(更新中))