1:iOS SEL的简单总结

SEL就是对方法的一种包装。包装的SEL类型数据它对应相应的方法地址,找到方法地址就可以调用方法

a.方法的存储位置

在内存中每个类的方法都存储在类对象中

每个方法都有一个与之对应的SEL类型的数据

根据一个SEL数据就可以找到对应的方法地址,进而调用方法

SEL类型的定义:  typedef struct objc_selector *SEL

b.SEL对象的创建

SEL s1 = @selector(test1);   // 将test1方法包装成SEL对象 

SEL s2 = NSSelectorFromString(@"test1");   // 将一个字符串方法转换成为SEL对象

c.SEL对象的其他用法

// 将SEL对象转换为NSString对象  

NSString *str = NSStringFromSelector(@selector(test));

实例:

Person *p = [Person new];

// 调用对象p的test方法

[p performSelector:@selector(test)];

[person performSelector:@selector(test2:) withObject:@"传入参数"];
Person类代码:

#import "Person.h"
@implementation Person
- (void)test
{
NSLog(@"无参数的对象方法");
}
- (void)test2:(NSString *)str
{
NSLog(@"带有参数的方法%@",str);
}
@end

d:在数组中的运用

// 对一个数组array的每个元素执行一次test方法

[array makeObjectsPerformSelector:@selector(test)];

[array makeObjectsPerformSelector:@selector(test)  withObject:@"aaa"];
//对一个数组array进行排序 [array sortedArrayUsingSelector:@selector(compare:)];

e:关于Sel传参运用(target - action设计模式)

在Button中我们经常用下面进行事件增加代码:

- (void)addTarget:(nullable id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;

实例:

#import <UIKit/UIKit.h>

@interface TapView : UIView
//目标
@property(weak,nonatomic)id target;
//行为
@property(assign,nonatomic)SEL action; //自定义方法
-(void)addCustomtarget:(id)target andAction:(SEL)action; @end
#import "TapView.h"

@implementation TapView

//自定义方法
-(void)addCustomtarget:(id)target andAction:(SEL)action{
_action = action;
_target = target;
} -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//当视图点击的时候,target去执行action的方法并把自己传过去.
//首先代理不能是空,而且代理(代理是对象!)的类中有方法并且能传出过来.
if (nil != _target && [[_target class] instancesRespondToSelector:_action]) {
[_target performSelector:_action withObject:self];
}
}

另一个实例:

#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import "Debug.h" // not given; just an assert @interface NSObject (Extras) // Enforce the rule that the selector used must return void.
- (void) performVoidReturnSelector:(SEL)aSelector withObject:(id)object;
- (void) performVoidReturnSelector:(SEL)aSelector; @end @implementation NSObject (Extras) // Apparently the reason the regular performSelect gives a compile time warning is that the system doesn't know the return type. I'm going to (a) make sure that the return type is void, and (b) disable this warning
// See http://stackoverflow.com/questions/7017281/performselector-may-cause-a-leak-because-its-selector-is-unknown - (void) checkSelector:(SEL)aSelector {
// See http://stackoverflow.com/questions/14602854/objective-c-is-there-a-way-to-check-a-selector-return-value
Method m = class_getInstanceMethod([self class], aSelector);
char type[];
method_getReturnType(m, type, sizeof(type)); NSString *message = [[NSString alloc] initWithFormat:@"NSObject+Extras.performVoidReturnSelector: %@.%@ selector (type: %s)", [self class], NSStringFromSelector(aSelector), type];
NSLog(@"%@", message); if (type[] != 'v') {
message = [[NSString alloc] initWithFormat:@"%@ was not void", message];
[Debug assertTrue:FALSE withMessage:message];
}
} - (void) performVoidReturnSelector:(SEL)aSelector withObject:(id)object {
[self checkSelector:aSelector]; #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
// Since the selector (aSelector) is returning void, it doesn't make sense to try to obtain the return result of performSelector. In fact, if we do, it crashes the app.
[self performSelector: aSelector withObject: object];
#pragma clang diagnostic pop
} - (void) performVoidReturnSelector:(SEL)aSelector {
[self checkSelector:aSelector]; #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self performSelector: aSelector];
#pragma clang diagnostic pop
} @end

2:代理模式实例

#import <UIKit/UIKit.h>

@protocol TouchViewDelegate <NSObject>
-(void)changeViewColor:(UIColor *)color;
@end @interface TouchView : UIView
//声明一个代理,这个代理遵守TouchViewDelegate协议,
@property(nonatomic,assign)id<TouchViewDelegate> delegate;
@end
#import "TouchView.h"

@implementation TouchView

//我们还是用touchesBegandian
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ if (nil != self.delegate && [self.delegate respondsToSelector:@selector(changeViewColor:)]) {
//我们传一个颜色到我们的ViewController去.
[self.delegate changeViewColor:[UIColor brownColor]];
}
} @end
运用代码:

#import "ViewController.h"
#import "TouchView.h" //在这里ViewController 要遵守协议....
@interface ViewController ()<TouchViewDelegate> @property(nonatomic,strong)TouchView *touchView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.touchView = [[TouchView alloc]initWithFrame:CGRectMake(, , , )]; self.touchView.backgroundColor = [UIColor redColor];
//指定touchView的代理为ViewController.即为本身~
self.touchView.delegate =self; [self.view addSubview: self.touchView];
} -(void)changeViewColor:(UIColor *)color{
//现在参数color是有值的,这是因为在TouchView那个页面传过来的.
self.touchView.backgroundColor = color;
}
@end

3:关于Bolck运用

#import <UIKit/UIKit.h>

//给block改名成MyBlock
typedef void(^MyBlock)(NSString *); @interface OtherViewController : UIViewController //ARC:语义设置使用strong即可
@property(nonatomic,strong)MyBlock block; @end
#import "OtherViewController.h"

@interface OtherViewController ()
@property(nonatomic,strong)UITextField *textField;
@end @implementation OtherViewController - (void)viewDidLoad {
[super viewDidLoad];
self.textField = [[UITextField alloc]initWithFrame:CGRectMake(, , , )];
self.textField.backgroundColor = [UIColor lightGrayColor];
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview: self.textField];
} -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
self.block(_textField.text);
[self.navigationController popViewControllerAnimated:YES];
}
@end
运用代码:

    OtherViewController *otherVC = [[OtherViewController alloc]init];
__weak typeof(self)weak = self;
//给block赋值~
otherVC.block = ^(NSString *string){
weak.label.text = string;
}; [self.navigationController pushViewController:otherVC animated:YES];

4:UIButton的几种触发方式

a、UIControlEventTouchDown

  指鼠标左键按下(注:只是“按下”)的动作

b、UIControlEventTouchDownRepeat

  指鼠标左键连续多次重复按下(注:只是“按下”)的动作,比如,鼠标连续双击、三击、……、多次连击。

  说明:多次重复按下时,事件序列是这样的:

  UIControlEventTouchDown ->

  (UIControlEventTouchUpInside) ->

  UIControlEventTouchDown -> 

  UIControlEventTouchDownRepeat -> 

  (UIControlEventTouchUpInside) -> 

  UIControlEventTouchDown -> 

  UIControlEventTouchDownRepeat -> 

  (UIControlEventTouchUpInside) ->

  ......

  除了第一次按下外,后面每次摁下都是一个UIControlEventTouchDown事件,然后紧跟一个UIControlEventTouchDownRepeat事件。

cUIControlEventTouchDragInside

  指按下鼠标,然后在控件边界范围内拖动。

dUIControlEventTouchDragOutside

  与UIControlEventTouchDragInside不同的是,拖动时,鼠标位于控件边界范围之外。

  但首先得有个UIControlEventTouchDown事件,然后接一个UIControlEventTouchDragInside事件,再接一个UIControlEventTouchDragExit事件,这时,鼠标已经位于控件外了,继续拖动就是UIControlEventTouchDragOutside事件了。

  具体操作是:在控件里面按下鼠标,然后拖动到控件之外。

eUIControlEventTouchDragEnter

  指拖动动作中,从控件边界外到内时产生的事件。

fUIControlEventTouchDragExit

  指拖动动作中,从控件边界内到外时产生的事件。

gUIControlEventTouchUpInside

  指鼠标在控件范围内抬起,前提先得按下,即UIControlEventTouchDownUIControlEventTouchDownRepeat事件。

hUIControlEventTouchUpOutside

  指鼠标在控件边界范围外抬起,前提先得按下,然后拖动到控件外,即 

  UIControlEventTouchDown -> 

  UIControlEventTouchDragInside(n ) -> 

  UIControlEventTouchDragExit -> 

  UIControlEventTouchDragOutside(n 

  时间序列,再然后就是抬起鼠标,产生UIControlEventTouchUpOutside事件。

5:让编译器对一些警告闭嘴

a:方法弃用告警

#pragma clang diagnostic push  

#pragma clang diagnostic ignored "-Wdeprecated-declarations"
//会报警告的方法,比如SEL
[TestFlight setDeviceIdentifier:[[UIDevice currentDevice] uniqueIdentifier]]; #pragma clang diagnostic pop

b:未使用变量

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-variable" int a; #pragma clang diagnostic pop

6:一个六边形,并只在六边形里面有点击效果

#import <UIKit/UIKit.h>
//六边形Button
@interface HexagonButton : UIView
NS_ASSUME_NONNULL_BEGIN typedef void (^HexagonButtonBlock)(); @property (nonatomic, strong) UIBezierPath *path;
@property (nonatomic, strong) CAShapeLayer *maskLayer;
@property (nonatomic, strong) HexagonButtonBlock block; //点击事件 //添加点击事件 NS_ASSUME_NONNULL_END
@end
#import "HexagonButton.h"

@implementation HexagonButton
- (instancetype) initWithFrame:(CGRect)frame
{
if ([super initWithFrame:frame]) { self.backgroundColor = [UIColor brownColor];
self.userInteractionEnabled = YES; //添加单击手势
UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(click:)];
[self addGestureRecognizer:tap];
}
return self;
}
- (void) layoutSubviews
{
[super layoutSubviews];
CGFloat SIZE = self.frame.size.width;
// step 1: 生成六边形路径
CGFloat longSide = SIZE * 0.5 * cosf(M_PI * / );
CGFloat shortSide = SIZE * 0.5 * sin(M_PI * / );
CGFloat k = SIZE * 0.5 - longSide; //路径整体下移,保证六边形路径位于图形中间 _path = [UIBezierPath bezierPath];
[_path moveToPoint:CGPointMake(, longSide + k)];
[_path addLineToPoint:CGPointMake(shortSide, + k)];
[_path addLineToPoint:CGPointMake(shortSide + shortSide + shortSide, k)];
[_path addLineToPoint:CGPointMake(SIZE, longSide + k)];
[_path addLineToPoint:CGPointMake(shortSide * , longSide * + k)];
[_path addLineToPoint:CGPointMake(shortSide, longSide * + k)];
[_path closePath]; // step 2: 根据路径生成蒙板
_maskLayer = [CAShapeLayer layer];
// _maskLayer.position = self.center;
_maskLayer.path = [_path CGPath]; // step 3: 添加蒙版
self.layer.mask = _maskLayer; self.backgroundColor = [UIColor orangeColor];
} //点击事件
- (void) click:(UITapGestureRecognizer *) tap
{
if (_block) {
_block();
}
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
//如果点击的区域在所创建的路径范围内
if (CGPathContainsPoint(_path.CGPath, NULL, point, NO)) {
return [super hitTest:point withEvent:event];
}
return nil;
} @end
    //创建六变形按钮
HexagonButton * hexagonButton = [[HexagonButton alloc] initWithFrame:CGRectMake(, , , )];
hexagonButton.center = self.view.center;
hexagonButton.block = ^(){
NSLog(@"六边形区域被点击");
};
[self.view addSubview:hexagonButton];

7:self.navigationController.viewControllers修改

var controllerArr = self.navigationController?.viewControllers//获取Controller数组
controllerArr?.removeAll()//移除controllerArr中保存的历史路径
//重新添加新的路径
controllerArr?.append(self.navigationController?.viewControllers[])
controllerArr?.append(C)
controllerArr?.append(B)
//这时历史路径为(root -> c -> b)
//将组建好的新的跳转路径 set进self.navigationController里
self.navigationController?.setViewControllers(controllerArr!, animated: true)//直接写入,完成跳转B页面的同时修改了之前的跳转路径

主要解决那些乱七八糟的转转,不按顺序来的问题;

IOS开发基础知识--碎片45的更多相关文章

  1. IOS开发基础知识碎片-导航

    1:IOS开发基础知识--碎片1 a:NSString与NSInteger的互换 b:Objective-c中集合里面不能存放基础类型,比如int string float等,只能把它们转化成对象才可 ...

  2. IOS开发基础知识--碎片33

    1:AFNetworking状态栏网络请求效果 直接在AppDelegate里面didFinishLaunchingWithOptions进行设置 [[AFNetworkActivityIndicat ...

  3. IOS开发基础知识--碎片42

    1:报thread 1:exc_bad_access(code=1,address=0x70********) 闪退 这种错误通常是内存管理的问题,一般是访问了已经释放的对象导致的,可以开启僵尸对象( ...

  4. IOS开发基础知识--碎片50

      1:Masonry 2个或2个以上的控件等间隔排序 /** * 多个控件固定间隔的等间隔排列,变化的是控件的长度或者宽度值 * * @param axisType 轴线方向 * @param fi ...

  5. IOS开发基础知识--碎片3

    十二:判断设备 //设备名称 return [UIDevice currentDevice].name; //设备型号,只可得到是何设备,无法得到是第几代设备 return [UIDevice cur ...

  6. IOS开发基础知识--碎片11

    1:AFNetwork判断网络状态 #import “AFNetworkActivityIndicatorManager.h" - (BOOL)application:(UIApplicat ...

  7. IOS开发基础知识--碎片14

    1:ZIP文件压缩跟解压,使用ZipArchive 创建/添加一个zip包 ZipArchive* zipFile = [[ZipArchive alloc] init]; //次数得zipfilen ...

  8. IOS开发基础知识--碎片16

    1:Objective-C语法之动态类型(isKindOfClass, isMemberOfClass,id) 对象在运行时获取其类型的能力称为内省.内省可以有多种方法实现. 判断对象类型 -(BOO ...

  9. IOS开发基础知识--碎片19

    1:键盘事件顺序 UIKeyboardWillShowNotification // 键盘显示之前 UIKeyboardDidShowNotification // 键盘显示完成后 UIKeyboar ...

随机推荐

  1. 一起学微软Power BI系列-官方文档-入门指南(4)Power BI的可视化

    在前面的系列文章中,我们介绍了官方有关获取数据,以及建模的原始文档和基本介绍.今天继续给大家介绍官方文档中,有关可视化的内容.实际上获获取数据和建模更注重业务关系的处理,而可视化则关注对数据的解读.这 ...

  2. (转)对Lucene PhraseQuery的slop的理解

    所谓PhraseQuery,就是通过短语来检索,比如我想查"big car"这个短语,那么如果待匹配的document的指定项里包含了"big car"这个短语 ...

  3. 如何在ios中集成微信登录功能

    在ios中集成微信的登录功能有两种方法 1 用微信原生的api来做,这样做的好处就是轻量级,程序负重小,在Build Settings 中这样设置 然后设置 友盟的设置同上,但是要注意,加入你需要的所 ...

  4. objective-c 语法快速过(4)

    oc 里的字符串 字符串的快速创建(最简单的方法) NSStirng *str = @“Hello”;//oc的字符串都是@“”形式的 oc的字符串也是类的对象,是NSString类的对象,创建没有那 ...

  5. 倾情大奉送--Spark入门实战系列

    这一两年Spark技术很火,自己也凑热闹,反复的试验.研究,有痛苦万分也有欣喜若狂,抽空把这些整理成文章共享给大家.这个系列基本上围绕了Spark生态圈进行介绍,从Spark的简介.编译.部署,再到编 ...

  6. 资源等待类型sys.dm_os_wait_stats

    动态管理视图  sys.dm_os_wait_stats 返回执行的线程所遇到的所有等待的相关信息.可以使用该聚合视图来诊断 SQL Server 以及特定查询和批处理的性能问题. 列名 数据类型 说 ...

  7. Spring-Boot - 初步搭建

    official document:http://projects.spring.io/spring-boot/ 项目代码: https://github.com/chenxing12/springb ...

  8. 轻松理解AOP思想(面向切面编程)

    本文旨在帮助还没有理解AOP的童鞋看透弄懂AOP,也欢迎高手批评指正. 先说一个Spring是什么吧,大家都是它是一个框架,但框架这个词对新手有点抽象,以致于越解释越模糊,不过它确实是个框架的,但那是 ...

  9. 【翻译】设计模式学习系列1---【Design Patterns Simplified: Part 1【设计模式简述:第一部分】】

    原文链接:http://www.c-sharpcorner.com/UploadFile/19b1bd/design-patterns-simplified-part1/ Design Pattern ...

  10. git学习之冲突解决办法

    1.如果本地项目和远程服务器的同一文件都有改动,那么就会产生冲突,导致git pull 失败,报错见下. 解决办法:先执行git stash指令,暂存当前的改动状态,再执行git pull指令,就可以 ...