前言:

1.在Block中一起使用weakSelf与strongSelf的含义

我们都会声明一个弱引用在block中使用, 目的就是防止循环引用, 那么weakSelf与strongSelf一起使用目的是什么呢? 首先先定义2个宏:

#define LRWeakSelf(type)  __weak typeof(type) weak##type = type;

#define LRStrongSelf(type)  __strong typeof(type) type = weak##type;

我们创建一个shop并且在shop.myBlock代码块中使用弱引用LRWeakSelf(shop);

LRShop *shop = [[LRShop alloc]init];

shop.string = @"welcome to our company";

//弱引用

LRWeakSelf(shop);

shop.myBlock = ^{

NSLog(@"%@",weakshop.string);

};

shop.myBlock();

LRWeakSelf(shop);与LRStrongSelf(shop);一起使用

LRShop *shop = [[LRShop alloc]init];

shop.string = @"welcome to our company";

//弱引用

LRWeakSelf(shop);

shop.myBlock = ^{

//强引用

LRStrongSelf(shop)

NSLog(@"%@",shop.string);

};

shop.myBlock();

这2个打印结果都是shop.string有值并且shop也销毁了, 看起来是没什么区别:

仅仅使用LRWeakSelf(shop);并且在myBlock中增加一个延迟3秒在输出就会出现问题, 虽然对象销毁了, 输出的值却是null

//弱引用

LRWeakSelf(shop);

shop.myBlock = ^{

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

NSLog(@"%@",weakshop.string);

});

};

shop.myBlock();

如果LRWeakSelf(shop);与LRStrongSelf(shop);一起使用输出的shop.string有值,对象也销毁了, 我就不再截图给大家看了!

//弱引用

LRWeakSelf(shop);

shop.myBlock = ^{

//强引用

LRStrongSelf(shop)

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

NSLog(@"%@",shop.string);

});

};

shop.myBlock();

通过上面一堆的解释, 我们明显发现LRWeakSelf(shop);与LRStrongSelf(shop);一起使用的好处, 不但能打印出我想要的值,而且也不会造成循环引用 , 在开发中这两个方法可以根据实际情况进行使用!

2.使用UIAppearance注意的问题

如果不熟悉可以点击了解, UIAppearance它的目的就是设置全局显示样式, 我们知道只要带UI_APPEARANCE_SELECTOR这个宏, 我们就可以使用UIAppearance比如这样设置:

我们知道UIBarButtonItem它是有状态的比如UIControlStateNormal或者是UIControlStateDisabled状态

如果通过UIAppearance设置UIControlStateDisabled状态下的颜色是不好使的, 因为使用appearance会有一些延迟, 导致在不同状态下的颜色不好使, 我们只要强制刷新一下就可以了:

// 刷新

[self.navigationController.navigationBar layoutIfNeeded];

所以以后使用UIAppearance在某个状态下设置颜色,字体等不好使, 只需要在对应的位置用layoutIfNeeded刷新一下就可以了!

3. UITextField使用注意

先贴一个UITextField如何设置占位文字的颜色, 如果不先设置占位文字, 占位文字的颜色是不管用的:

//先设置占位文字

textField.placeholder = @"设置了占位文字内容以后, 才能设置占位文字的颜色";

//占位文字颜色

[textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];

大家监听UITextField文字的改变会用到代理:

#pragma mark -

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {

//这里监听文字改变

return YES;

}

但是这个代理方法监听会有问题如下图:

所以我们要监听UITextField的文字改变不建议使用代理, 我们用addTarget监听文字

/** 占位文字 */

@property (nonatomic, copy)NSString *placeholder;

/** 占位文字颜色 */

@property (nonatomic, strong)UIColor *placeholderColor;

(2)设置占位文字的默认值, 如果不设置默认值,外界不用你提供的方法会有崩溃现象:

// 设置默认字体

self.font = [UIFont systemFontOfSize:17];

// 设置默认的占位文字颜色

self.placeholderColor = [UIColor grayColor];

(3)内部添加占位文字的label ;

/** 占位文字label */

@property (nonatomic, weak) UILabel *placeholderLabel;

//懒加载

- (UILabel *)placeholderLabel

{

if (_placeholderLabel == nil) {

UILabel *placeholderLabel = [[UILabel alloc] init];

placeholderLabel.numberOfLines = 0;

[self addSubview:placeholderLabel];

_placeholderLabel = placeholderLabel;

}

return _placeholderLabel;

}

(4)通过监听文字改变,来显示或隐藏占位文字

// 监听文字

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChangeNotification) name:UITextViewTextDidChangeNotification object:nil];

//监听的方法

- (void)textDidChangeNotification {

// 有文字就隐藏占位文字

self.placeholderLabel.hidden = self.hasText;

}

(5)如果占位文字被修改, 颜色被修改, 字体被修改, 我们在内部需要重写set方法, 如果通过代码修改了textView文字(不是占位文字)不会发通知也需要重写set方法:

封装好的自定义TextView可以直接使用:Demo下载

https://github.com/luran2358/LRTextView

5.自定义控件里如何拿到导航控制器进行页面跳转?

(1)如果有UITabBarController我们会这样获取导航控制器:

UIViewController *viewC = [[UIViewController alloc]init];

// 取出当前的导航控制器

UITabBarController *tabBarVc = (UITabBarController *)[UIApplication sharedApplication].keyWindow.rootViewController;

//The view controller associated with the currently selected tab item

//当前选择的导航控制器

UINavigationController *navC = (UINavigationController *)tabBarVc.selectedViewController;

[navC pushViewController:viewC animated:YES];

(2)如果通过modal出来的控制器并且用UITabBarController不好使, 我们会这样获取导航控制器:

UIViewController *viewC = [[UIViewController alloc]init];

//获取最终的根控制器

UIViewController *rootC = [UIApplication sharedApplication].keyWindow.rootViewController;

//如果是modal出来的控制器,它就会通过presentedViewController拿到上一个控制器

UINavigationController *navC = (UINavigationController *)rootC.presentedViewController;

[navC pushViewController:viewC animated:YES];

6.修改了leftBarButtonItem如何恢复系统侧滑返回功能

在开发中系统的leftBarButtonItem不是我们想要的, 如果我们修改了leftBarButtonItem那么系统自带的侧滑返回功能就不好使了!

//设置代理

self.interactivePopGestureRecognizer.delegate = self;

#pragma mark -

//实现代理方法:return YES :手势有效, NO :手势无效

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer

{

//当导航控制器的子控制器个数 大于1 手势才有效

return self.childViewControllers.count > 1;

}

7.重新认识Bounds

我们之前对Bounds理解就是以自己的左上角为坐标原点, 也就是说Bounds的x值y值是0, 但是Bounds的x值y值有可能是正数也可能是负数, 不一定是0那么Bounds真正是什么意思呢 ?

  • Bounds: 是以自己内容的左上角为坐标原点, 计算出自己的位置和大小

  • Frame: 是以父类内容的左上角为坐标原点, 计算出自己的位置和大小

    那什么是内容呢 ? 首先内容是抽象的, 一个控件不仅仅只有一层矩形框的, 他有很多图层的, 这个内容其实就可以抽象成一个控件的内部图层

    内容:就是内部的东西, 它的子控件也属于内容,也就是说修改了Buonds子控件的位置也会跟着改变

上图蓝色和绿色是属于一个控件, 只不过蓝色是控件本身, 绿色是控件的内容, 我们改变这个控件的Bounds的x值y值为-20, 内容位置改变, 控件本身位置不变!

8.跟枚举相关的一些符号的含义

上图是一个苹果官方的一个枚举, 我们主要是看的用处, 如果在枚举中只要那它的含义就是可以通过|进行组合使用:

//随便添加一个UITextField

UITextField *field = [UITextField new];

//可以通过 | 组合使用UIControlEventEditingDidBegin, UIControlEventValueChanged,UIControlEventEditingDidEnd

[field addTarget:self action:@selector(textFieldDidChanged) forControlEvents:UIControlEventEditingDidBegin | UIControlEventValueChanged | UIControlEventEditingDidEnd];

[self.view addSubview:field];

如果枚举没有就不能组合使用, 那它有什么规律呢1 :

//1 << 16 代表:2的16次方

UIControlEventEditingDidBegin = 1 << 16,

//1 << 17 代表:2的17次方

UIControlEventEditingChanged  = 1 << 17,

//1 << 18 代表:2的18次方

UIControlEventEditingDidEnd  = 1 << 18,

//1 << 19 代表:2的19次方

UIControlEventEditingDidEndOnExit  = 1 << 19,

原来这样的枚举可以组合使用, 那苹果官方是怎么知道我们多个条件组合使用了呢 ?

NSUInteger controlEvents = UIControlEventEditingDidBegin | UIControlEventValueChanged | UIControlEventEditingDidEnd;

/**

//通过 & 符号来判断是否包含:

UIControlEventEditingDidBegin,

UIControlEventValueChanged,

UIControlEventEditingDidEnd

*/

if (controlEvents & UIControlEventEditingDidBegin) {

NSLog(@"UIControlEventEditingDidBegin");

}else if (controlEvents & UIControlEventValueChanged) {

NSLog(@"UIControlEventValueChanged");

}else if (controlEvents & UIControlEventEditingDidEnd) {

NSLog(@"UIControlEventEditingDidEnd");

}

通过以上方法就能判断组合的状态, 在开发中这个意义很大的, 如果多个条件中, 任何一个条件满足我们也可用带的枚举给外界组合使用, 就像苹果官方添加使用是一样的!

9.Xib相关的一些问题

下图我们可以看出来, 如果通过xib加载出来的view尺寸是不正确的, 在xib中这个view不管你怎么设置都是治标不治本,我们会在layoutSubviews通过自己的宽度来计算子控件的尺寸!

//在这里拿出的宽度是不正确的

- (void)awakeFromNib {}

//对尺寸计算我们一般拿到这个方法中计算(拿到自己宽度计算子控件的尺寸)

- (void)layoutSubviews {

[super layoutSubviews];

//在这里拿到自己的宽度是正确的

}

那我们也会想到, 如果控制器的view也是xib创建的, 我们该怎么办 ? 其实不管控制器是在哪里创建的, 我们只要只在viewDidLayoutSubviews方法中拿到控制器尺寸来计算子控件尺寸都是正确的, 所以说建议大家以后在viewDidLayoutSubviews计算尺寸:

- (void)viewDidLayoutSubviews {

[super viewDidLayoutSubviews];

//在这里计算尺寸

}

iOS 开发中你是否遇到这些经验问题(二)的更多相关文章

  1. iOS开发中你是否遇到这些经验问题

    前言 小伙伴们在开发中难免会遇到问题, 你是如何解决问题的?不妨也分享给大家!如果此文章其中的任何一条问题对大家有帮助,那么它的存在是有意义的! 反正不管怎样遇到问题就要去解决问题, 在解决问题的同时 ...

  2. iOS 开发中你是否遇到这些经验问题(一)

    前言 小伙伴们在开发中难免会遇到问题, 你是如何解决问题的?不妨也分享给大家!如果此文章其中的任何一条问题对大家有帮助,那么它的存在是有意义的! 反正不管怎样遇到问题就要去解决问题, 在解决问题的同时 ...

  3. iOS开发中的单元测试(三)——URLManager中的测试用例解析

    本文转载至 http://www.cocoachina.com/cms/plus/view.php?aid=8088   此前,我们在<iOS开发中的单元测试(一)&(二)>中介绍 ...

  4. IOS开发中UI编写方式——code vs. xib vs.StoryBoard

    最近接触了几个刚入门的iOS学习者,他们之中存在一个普遍和困惑和疑问,就是应该如何制作UI界面.iOS应用是非常重视用户体验的,可以说绝大多数的应用成功与否与交互设计以及UI是否漂亮易用有着非常大的关 ...

  5. iOS开发中调试小技巧

    对于软件开发而言,调试是必须学会的技能,重要性不言而喻.对于调试的技能,基本上是可以迁移的,也就是说你以前在其他平台上掌握的很多调试技巧,很多也是可以用在iOS开发中.不同语言.不同IDE.不同平台的 ...

  6. 深入理解 iOS 开发中的锁

    来源:伯乐在线 - 夏天然后 链接:http://ios.jobbole.com/89474/ 点击 → 申请加入伯乐在线专栏作者 摘要 本文的目的不是介绍 iOS 中各种锁如何使用,一方面笔者没有大 ...

  7. 李洪强iOS开发本人集成环信的经验总结_07_监听好友请求

    李洪强iOS开发本人集成环信的经验总结_07_监听好友请求 来到Appdalegate中: 遵守代理协议 设置代理  实现监听好友请求的回调的方法

  8. 李洪强iOS开发本人集成环信的经验总结_02_基本配置

     李洪强iOS开发本人集成环信的经验总结_02_基本配置 来到APPdelegate中做一些配置 01 - 导入头文件 02 - 在didFinishLaunchingWithOptions用法总结 ...

  9. 李洪强iOS开发本人集成环信的经验总结_01环信SDK的导入

    李洪强iOS开发本人集成环信的经验总结_01环信SDK的导入 01 - 直接在项目中导入SDK和一些静态库 这个时候,没有错误的编译没有错误的话,就说明SDK已经配置成功 还有一种方法是用cocoap ...

随机推荐

  1. EntityFramework程序集版本不同

    问题: Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE /* Style Definitions */ table.MsoNormalT ...

  2. 在Oracle中更新数据时,抛出:ORA-01008: not all variables bound

    在Oracle中更新数据时,抛出了一个 :ORA-01008 not all variables bound, 我的理解是不是所有的变量/参数都有边界,不懂: 后来知道了,原来是“不是所有变量/参数都 ...

  3. [原]AngularJS iframe打开不同域的内容时报错误

    <iframe id="myFrame" ng-src="{{url}}" width="100%" height="100 ...

  4. HDU 1024 DP Max Sum Plus Plus

    题意:本题的大致意思为给定一个数组,求其分成m个不相交子段和最大值的问题. kuangbin专题. dp[i][j]=Max(dp[i][j-1]+a[j] , max( dp[i-1][k] ) + ...

  5. 为zend studio增加Extjs代码提示功能

    http://blog.163.com/liuhaijun_83/blog/static/61175622201223114216786/ 需要将其中的http://www.spket.com/upd ...

  6. 用python的numpy作线性拟合、多项式拟合、对数拟合

    转自:http://blog.itpub.net/12199764/viewspace-1743145/ 项目中有涉及趋势预测的工作,整理一下这3种拟合方法:1.线性拟合-使用mathimport m ...

  7. MySQL 字段类型详解

    一.非数字类型 类型 范围 说明   Char(N) [ binary] N=1~255 个字元 binary :分辨大小写 固定长度 std_name cahr(32) not null VarCh ...

  8. leetcode@ [2/43] Add Two Numbers / Multiply Strings(大整数运算)

    https://leetcode.com/problems/multiply-strings/ Given two numbers represented as strings, return mul ...

  9. Hadoop MapReduce编程 API入门系列之mr编程快捷键活用技巧详解(四)

    1.Shift + Alt + S Hadoop没有使用jdk自带的默认序列化机制. 现在呢,hadoop-2.*里有两套序列化机制.一个是自己hadoop的序列化机制,一个是谷歌的. 所以,要改为. ...

  10. hdu 1034 Candy Sharing Game

    Candy Sharing Game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...