IOS開發基礎知識--碎片45

来源:http://www.cnblogs.com/wujy/archive/2016/08/03/5732038.html
-Advertisement-
Play Games

1:iOS SEL的簡單總結 SEL就是對方法的一種包裝。包裝的SEL類型數據它對應相應的方法地址,找到方法地址就可以調用方法 a.方法的存儲位置 在記憶體中每個類的方法都存儲在類對象中 每個方法都有一個與之對應的SEL類型的數據 根據一個SEL數據就可以找到對應的方法地址,進而調用方法 SEL類型的 ...


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[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事件。

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 * 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頁面的同時修改了之前的跳轉路徑

主要解決那些亂七八糟的轉轉,不按順序來的問題;

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 支持輝光效果的Label 效果 源碼 https://github.com/YouXianMing/UI-Component-Collection 中的 FBGlowLabel ...
  • 今天項目遇到需求 要求 實現圖片預覽效果 。 類似於扣扣空間那種,本人也到網上找過 代碼量太大了 ,類多到處是註釋看的有點噁心 。然後自己寫了一個圖片預覽的效果,其實很簡單的 。 首先我們來分析一下 實現原理 :點擊 圖片 顯示 新的視窗 滑動顯示下一張 並且頁碼也跟隨的變化, 輕觸退出(本文代碼沒 ...
  • NSUserDefault的使用 NSUserDefaults用來存儲類似用戶的配置等一些比較小的數據。 一、創建NSUserDefaults對象 NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults]; 二、創建NSU ...
  • 該博文出自:http://www.cnblogs.com/yang-guang-girl/p/5683454.html 輸出 ...
  • androidstudio報錯, Unsupported major.minor version 52.0 ...
  • 使用osChina分支的創建分為兩種 1.直接在osChina上創建 需要pull否則查看git的狀態是不包含改分支的; 2.使用git命令創建分支 需要push否則查看osChina的分支的是不包含改分支的; 查看git下的所有分支 --online不是必須的,只是加上之後數據顯示會精簡很多。 " ...
  • 一個APP的需求來自於哪兒?產品、老闆、客戶….. 做程式員不容易,需求一句話,就是幾千幾萬行代碼!所幸,在AppCan平臺開發APP,開發者只需完成應用的前端部分,至於各項複雜的功能,就交給AppCan來搞定吧! ...
  • 最近項目中經常有遇到從伺服器請求的數據是null的情況,這種情況下如果用[dic objectForKey:@"key"]方法,程式會發生崩潰現象,因為項目是以前的老項目,而且有太多個這樣的方法,於是想起了前幾天的runtime知識,嘗試簡單的實現了一個交換方法。 1.首先實現了一個字典的分類。 2 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...