前言:

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. (四)学习CSS之position、bottom、left、right和top属性

    参考:http://www.w3school.com.cn/cssref/pr_class_position.asp position 属性规定元素的定位类型. 这个属性定义建立元素布局所用的定位机制 ...

  2. [Bhatia.Matrix Analysis.Solutions to Exercises and Problems]ExI.4.6

    Let $A$ and $B$ be two matrices (not necessarily of the same size). Relative to the lexicographicall ...

  3. e2e 自动化集成测试 架构 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step (五) 如何让窗体记录登录状态Session

    在写自动化测试的Node.js脚本时, 时常需要测试所写的case, 可能都需要去重新登录一遍,这将相当的耗时, 好在Selenium都借了Session的机制, 如果在最初的浏览器没有关闭的情况下, ...

  4. MFC程序运行流程

    ->进入入口函数_tWinMain() 程序首先进入文件AppModul.cpp,找到_tWinMain()函数运行,调用其中的AfxWinMain()函数. 由于为了支持UNICODE,C运行 ...

  5. 常规页生命周期(class0620)

    常规页声明周期阶段 阶段                   说明 页请求 开始 页初始化 加载 验证 回发事件处理 卸载 生命周期事件 页事件               典型使用

  6. 如何实现CSS居中?–CSS居中常用方法

    来源:http://www.ido321.com/824.html 一.水平居中 1.内联元素居中:相对父级块级元素居中对齐 1: .center-children { 2: text-align: ...

  7. NOIP2003 传染病控制

    题四     传染病控制 [问题背景] 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国 大范围流行,该国政府决定不惜一切代价控制传染病的蔓延.不幸的是,由于人们尚未完 全认 ...

  8. 今天考试的JAVA编程题

    今天早上考了java, 题目感觉还不错, 共四道题,有一道定义类的没啥意思就没列出来. 这三道题目还是不错的,特别是第一道,大一上学期学linux的时候,那时还没学C语言呢,准确的来说,还不知道什么是 ...

  9. Android开发错误信息收集

    android sdk 无法更新或更新太慢 备注信息:sdk manager中加入mirrors.opencas.org,强迫http方式 ADT下载地址:http://dl.google.com/a ...

  10. $GLOBALS 添加超全局变量

    <?php function test() { $foo = "local variable"; echo '$foo in global scope: ' . $GLOBA ...