IOS开发基础知识--碎片45
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-valueMethod m = class_getInstanceMethod([self class], aSelector);char type[128];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[0] != '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(100, 100, 100, 100)];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(0, 100, 414, 40)];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事件。
c、UIControlEventTouchDragInside
指按下鼠标,然后在控件边界范围内拖动。
d、UIControlEventTouchDragOutside
与UIControlEventTouchDragInside不同的是,拖动时,鼠标位于控件边界范围之外。
但首先得有个UIControlEventTouchDown事件,然后接一个UIControlEventTouchDragInside事件,再接一个UIControlEventTouchDragExit事件,这时,鼠标已经位于控件外了,继续拖动就是UIControlEventTouchDragOutside事件了。
具体操作是:在控件里面按下鼠标,然后拖动到控件之外。
e、UIControlEventTouchDragEnter
指拖动动作中,从控件边界外到内时产生的事件。
f、UIControlEventTouchDragExit
指拖动动作中,从控件边界内到外时产生的事件。
g、UIControlEventTouchUpInside
指鼠标在控件范围内抬起,前提先得按下,即UIControlEventTouchDown或UIControlEventTouchDownRepeat事件。
h、UIControlEventTouchUpOutside
指鼠标在控件边界范围外抬起,前提先得按下,然后拖动到控件外,即
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_BEGINtypedef 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 * 30 / 180);CGFloat shortSide = SIZE * 0.5 * sin(M_PI * 30 / 180);CGFloat k = SIZE * 0.5 - longSide; //路径整体下移,保证六边形路径位于图形中间 _path = [UIBezierPath bezierPath];[_path moveToPoint:CGPointMake(0, longSide + k)];[_path addLineToPoint:CGPointMake(shortSide, + k)];[_path addLineToPoint:CGPointMake(shortSide + shortSide + shortSide, k)];[_path addLineToPoint:CGPointMake(SIZE, longSide + k)];[_path addLineToPoint:CGPointMake(shortSide * 3, longSide * 2 + k)];[_path addLineToPoint:CGPointMake(shortSide, longSide * 2 + 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(20, 20, 100, 100)];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[0]) controllerArr?.append(C) controllerArr?.append(B)//这时历史路径为(root -> c -> b)//将组建好的新的跳转路径 set进self.navigationController里 self.navigationController?.setViewControllers(controllerArr!, animated: true)//直接写入,完成跳转B页面的同时修改了之前的跳转路径
主要解决那些乱七八糟的转转,不按顺序来的问题;
IOS开发基础知识--碎片45相关推荐
- iOS开发基础知识--碎片44
iOS开发基础知识--碎片44 iOS开发基础知识--碎片44 1:App跳转至系统Settings 跳转在IOS8以上跟以下是有区别的,如果是IOS8以上可以如下设置: NSURL *url = ...
- iOS开发基础知识--碎片27
iOS开发基础知识--碎片27 1:iOS中的round/ceil/floorf extern float ceilf(float); extern double ceil(double); ext ...
- iOS开发基础知识--碎片37
iOS开发基础知识--碎片37 iOS开发基础知识--碎片37 iOS开发基础知识--碎片37 1:iOS 使用NJKWebViewProgress做webview进度条 引入头文件: #import ...
- iOS开发基础知识--碎片41
iOS开发基础知识--碎片41 1:UIWebView加载本地的HTML NSString *path = [[NSBundle mainBundle] bundlePath]; NSURL *bas ...
- iOS开发基础知识--碎片19
iOS开发基础知识--碎片19 1:键盘事件顺序 UIKeyboardWillShowNotification // 键盘显示之前 UIKeyboardDidShowNotification // ...
- IOS开发基础知识--碎片33
1:AFNetworking状态栏网络请求效果 直接在AppDelegate里面didFinishLaunchingWithOptions进行设置 [[AFNetworkActivityIndicat ...
- IOS开发基础知识--碎片14
1:ZIP文件压缩跟解压,使用ZipArchive 创建/添加一个zip包ZipArchive* zipFile = [[ZipArchive alloc] init];//次数得zipfilenam ...
- IOS开发基础知识--碎片13
1:运行程序报the file couldn't be opened because you don't have permission to view it 解决办法:项目->targets- ...
- IOS开发基础知识--碎片34
1:第三方插件SKSTableView在IOS7.1.1出现闪退的问题 解决办法,修改其内部源代码: (NSInteger)subRow { id indexpath = [NSIndexPath c ...
最新文章
- 人脸口罩识别——人脸添加口罩方法masked_faces
- 亲手把360奇安信软件卸载了,爽!
- 2044. 统计按位或能得到最大值的子集数目
- 深入浅出的排序算法-冒泡排序
- 热电偶校验仪_热电偶校验方法_南昌手持热工校验仪,杭州全功能热工过程校验仪厂家...
- 最终,我还是放弃了字节50W开发offer,选择了测试开发……
- android-x86 下载地址
- 数据集:同一年龄段学生身高数据
- 一个Windows C++的线程池类实现
- python最优分箱计算iv值_基于sklearn决策树的最优分箱与IV值计算-Python实现
- 一个软件完整的开发流程,不会程序也能自己制作手机App
- 在x64上构建智能家居(home assistant) (一) Supervised版本安装
- 快递地址自动识别填充
- 金属类的大宗商品创下新高,对冲基金疯狂买涨
- 超级计算机阿波罗11,阿波罗11号制导计算机中指令模块和登月模块原始代码已在 GitHub 上开源...
- 基于FMC接口的PCIEx8+FPGAXC7K325T+DDR3的3UVPX处理板
- 【信息安全技术】实验报告:木马及远程控制技术
- MyBatis骨骼惊奇,跟着腾讯大牛学源码分析,总结出这份pdf文档
- 网站加载图片速度提升
- Win32汇编:各种语句的构造方式