02.實戰(zhàn)技術 父子控制器,常量Const,開發(fā)中常見問題

@(iOS Study)[實戰(zhàn)技術]


目錄

  • 02.實戰(zhàn)技術 父子控制器,常量Const,開發(fā)中常見問題
  • 開發(fā)中常見問題/常量Const/父子控制器
  • 1.super,superClass,class關鍵字
    • super,superClass,class介紹
    • super關鍵字
  • 2.項目奇怪的bug
    • bug1. 已添加文件到項目中,卻提示未定義
    • bug2. 重復添加文件到項目中
    • bug3. 導入.m文件
  • 3.const的使用
    • const與宏的區(qū)別
    • const的簡單使用
    • const開發(fā)中使用場景
    • static和extern使用
    • static和const聯合使用
    • extern和const聯合使用
  • 4.父子控制器
    • 父子控制器簡介
    • 父子控制器相關知識點
    • 父子控制器的簡單使用
  • 5.開發(fā)中常見問題
    • UIScrollView的自動布局
    • UIScrollView自動布局步驟(重要)
    • size和center設置注意點
    • bounds和frame簡介
    • bounds和frame介紹

開發(fā)中常見問題/常量Const/父子控制器


1.super,superClass,class關鍵字

super,superClass,class介紹

  • 關鍵字在方法中的意義
    • self: 方法調用者
    • class: 獲取方法調用者的類對象
    • superclass:獲取方法調用者的父類對象

super關鍵字

  • super關鍵字的介紹

    • super:不是一個指針,編譯指示器(標識符)
    • super的本質:其實還是當前對象去調用,只不過讓當前對象去調用父類方法
    • super不是父類對象,指的是父類方法
  • 注意:[super class]表示用self調用父類方法,[super superclass]表示用self調用父類的方法(獲取父類方法)

  • super的案例說明

@implementation SubPerson

- (void)test
{
    // [super class]表示用self調用父類方法,[super superclass]表示用self調用父類的方法(獲取父類方法)
    NSLog(@"%@ %@ %@ %@",[self class], [self superclass], [super class], [super superclass]);
    // 正確打印結果: SubPerson Person SubPerson Person √
    // 錯誤打印結果: SubPerson Person Person NSObject X
}

@end

2.項目奇怪的bug

bug1. 已添加文件到項目中,卻提示未定義

  • 已添加文件到項目中,卻提示未定義bug
1.bug1.已添加文件到項目中,卻提示未定義.png
  • 導致該bug的原因
    • 在創(chuàng)建文件/從其他地方拖進工程的時候,沒有勾選以下選項
      創(chuàng)建的時候未勾選該選項,導致沒添加到編譯列表
2.導致該bug的原因.png

從其他地方拖進工程的時候,沒有勾選Targets項,導致沒添加到編譯列表

3.沒有勾選Targets項.png
  • 解決方案: 在項目文件/Build Phases/Complie Sources將文件(.m文件)添加到編譯列表
4.解決方案.png

bug2. 重復添加文件到項目中

  • 重復添加文件,提示錯誤
5.bug2. 重復添加文件到項目中.png
  • 解決方案: 找出重復文件,將文件移除.

bug3. 導入.m文件

  • 不小心導入了.m文件
6.bug3. 導入.m文件.png

3.const的使用

const與宏的區(qū)別

  • const與宏的區(qū)別

    • 1.編譯時刻: const:編譯時期 宏:預編譯時期
    • 2.編譯檢測: const有編譯檢測,宏沒有編譯檢測.如#define WXKey @"123"488 ,這樣宏不會提示錯誤.
    • 3.宏可以替換方法和函數,const不行
    • 4.大量使用宏,容易造成預編譯時期過長.
    • 有博客提到:大量使用宏,會導致內存暴增,有異議.
  • 蘋果使用const為了迎合swift

  • '#'號是預編譯指令

  • 預編譯時期:項目一打開的時候,有個自動讀條時期,這個時期就是在做預編譯操作,如果定義了大量的宏,可能會導致自動讀條的時間變長,是開發(fā)效率變低,蘋果官方建議盡量少使用宏.

const的簡單使用

  • const的作用

    • 1.用來修飾右邊變量(基本變量,指針變量,對象等)
    • 2.只要被const修飾的變量,只讀
  • const使用原則

    • 放在const右邊被修飾的變量為只讀.
  • const筆試題

    // 1.原因:const修飾的是p,所以p為只讀;const在*之后,const沒修飾*p,所以*p是變量.
    int * const p; // p:只讀   *p:變量
    // 2.原因: const修飾的是*p1,所以*p1為只讀;const沒修飾p1,所以p1是變量.
    int const *p1; // p1:變量  *p1:只讀 
    // 3.原因: const修飾*p2,所以*p2為只讀;const沒修飾p2,所以p2為變量
    const int *p2; // p2:變量  *p2:只讀
    // 4.原因: 第一個const修飾*p3,所以*p3為只讀;第二個const修飾p3,所以p3為只讀
    int const * const p3; // p3:只讀 *p3:只讀
    // 5.原因: 第一個const修飾*p4,所以*p4為只讀;第二個const修飾p4,所以p4為只讀
    const int * const p4; // p4:只讀  *p4:只讀

const開發(fā)中使用場景

  • 1.當代碼多處(不同方法中)共用同一個只讀(無需修改)的字符串,比如多處(不同方法中)用到setValue:forKey:時都需要用到同一個key時,可以使用以下方法定義const字符串常量.
NSString * const key = @"key";

static和extern使用

  • static和extern的作用

    • static作用:

    1.描述局部變量,局部變量被static修飾,生命周期延長(整個app運行過程中都在),作用域不變.
    2.局部變量被static修飾,只會分配一次內存,程序一啟動就會分配.
    3.修飾全局變量,全局變量被static修飾,生命周期不變,作用域會變,只能在當前文件下使用.

    • extern作用:聲明一個全局變量,不能定義變量.

static和const聯合使用

  • static和const聯合使用場景
// 用于KVC的key時,可以static和const聯合使用
static NSString * const ageKey = @"age";

extern和const聯合使用

  • 開發(fā)規(guī)范:全局變量不能在自己的文件下定義,搞一個專門文件,去管理所有全局變量

  • extern和const聯合使用使用場景(聲明全局常量的時候)

    • 創(chuàng)建Const.h和Const.m文件用來存放全局常量
    • 在Const.h中使用extern和const聲明 NSString * const nameKey;注意:不能在.h文件中賦值.
    • 在Const.m中定義NSString * const nameKey = @"name";
  • 開發(fā)中存放常量的文件中,常量可以按功能模塊劃分.

// Const.m
#import "Const.h"
/*********我的********/
NSString * const nameKey = @"nameKey";

/*********發(fā)現********/
NSString * const discoveryKey = @"discoveryKey";


// Const.h
/*********我的********/
extern NSString * const nameKey;

/*********發(fā)現********/
extern NSString * const discoveryKey;
  • 模仿系統(tǒng)實現extern
// Const.h
// WXKIT_EXTERN相當于extern
#define WXKIT_EXTERN    extern __attribute__((visibility ("default")))
WXKIT_EXTERN NSString * const nameKey;

4.父子控制器

父子控制器簡介

父子控制器應用場景-多控制器管理者:導航控制器,tabBarController,內部原理就是采取父子控制器去管理.
任何控制器都可以成為父控制器
父子控制器設計原則: 把A控制器的view添加到B控制器的view上,那么A控制器必須要成為B控制器子控制器.

父子控制器相關知識點

  • 調試時已知問題可以先列出來,以防忘記,遺漏處理已經存在的問題
/*
    問題:
    1.每次都創(chuàng)建控制器
    2.每次都添加view
    3.控制器被銷毀
 */
  • 調用dismissViewControllerAnimated:completion:方法時,dismiss實現內部實現

    • 1.判斷下當前控制器是不是modal,如果是,就會dismiss
    • 2.如果不是,判斷下父控制器是不是modal,如果是,就會dismiss
    • 3.繼續(xù)判斷,直到沒有
  • 只有導航控制器子控制器才能獲取self.navigationController.

    • 使用self.navigationController時,會判斷自己是不是導航控制器子控制器,如果不是,判斷自己的父控制器是不是導航控制器子控制器,繼續(xù)判斷,直到沒有父控制器.

父子控制器的簡單使用

  • 父子控制的簡單使用
#import "ViewController.h"
#import "SocietyViewController.h"
#import "TopLineViewController.h"
#import "HotViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIView *topView;
@property (nonatomic, weak) UIButton *selectedBtn;
@property (weak, nonatomic) IBOutlet UIView *contentView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 1.添加所有子控制器
    [self setUpAllChildViewController];
    
    // 2.通過控制器標題,設置按鈕顯示的文字
    [self setupTopButton];
    
}

// ----------------------------------------------------------------------------------
// 初始化
#pragma mark - 初始化

/** 初始化頂部button */
- (void)setupTopButton
{
    NSInteger count = self.topView.subviews.count;
    for (NSInteger i = 0; i < count; i++) {
        // 取出button
        UIButton *btn = self.topView.subviews[i];
        
        // 取出子控制器
        UIViewController *vc1 = self.childViewControllers[i];
        
        // 設置btn顯示的文字
        [btn setTitle:vc1.title forState:UIControlStateNormal];
        
        // 設置btn選中狀態(tài)的文字顏色,需在storyboard中將按鈕Type修改為Custom,否則系統(tǒng)默認會把按鈕渲染成藍色
        [btn setTitleColor:[UIColor redColor] forState:UIControlStateSelected];
        
        // 設置默認選中
        if (i == 0) {
            [self btnClick:btn];
        }
    }
}

/** 添加所有子控制器 */
- (void)setUpAllChildViewController
{
    // 1.添加社會控制器
    SocietyViewController *vc1 = [[SocietyViewController alloc] init];
    vc1.title = @"社會";
    [self addChildViewController:vc1];
    // 2.添加頭條控制器
    TopLineViewController *vc2 = [[TopLineViewController alloc] init];
    vc2.title = @"頭條";
    [self addChildViewController:vc2];
    // 3.添加熱點控制器
    HotViewController *vc3 = [[HotViewController alloc] init];
    vc3.title = @"熱點";
    [self addChildViewController:vc3];
    
}

// ----------------------------------------------------------------------------------
// 添加頂部三個按鈕的監(jiān)聽
#pragma mark - 事件監(jiān)聽

/** 監(jiān)聽頂部三個button的點擊 */
- (IBAction)btnClick:(UIButton *)btn {
    // 1.切換選中狀態(tài)
    [self changeSelectedBtn:btn];
    
    // 2.設置子控制器view的屬性
    // 2.1 根據button的tag值,取出對應的控制器
    UIViewController *vc = self.childViewControllers[btn.tag];
    // 2.2 設置控制器view的背景顏色和button的背景顏色一樣
    vc.view.backgroundColor = btn.backgroundColor;
    
    // 2.3 設置子控制器的view的frame
    vc.view.frame = self.contentView.bounds;
    
    // 3.將子控制器的view添加到contentView
    // 3.1 先移除當前控制器view的所有子控件
    [self.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
    // 3.2 添加子控件的view到當前控制器的contentView上
    [self.contentView addSubview:vc.view];
}

/** 切換按鈕選中狀態(tài) */
- (void)changeSelectedBtn:(UIButton *)btn
{
    self.selectedBtn.selected = NO;
    self.selectedBtn = btn;
    self.selectedBtn.selected = YES;
}

@end
  • NSArray類的makeObjectsPerformSelector方法的使用
// 數組調用該方法時,表示數組里每個元素會執(zhí)行test方法
[arr makeObjectsPerformSelector:@selector(test)];
  • UIButon的Type如果是System,系統(tǒng)默認會把按鈕渲染成藍色

5.開發(fā)中常見問題

UIScrollView的自動布局

  • UIScrollView的自動布局思考

    • 1.確定好UIScrollView的滾動范圍contentSize
    • 2.怎么確定?搞一個view添加到UIScrollView上,這個view用來確定UIScrollView的滾動范圍
    • 3.通過設置這個view約束.來告訴UIScrollView滾動范圍
    • 4.如何計算contentSize呢秧荆?要計算contentSize必須清楚每個subviews的frame,而subviews的frame居然又要依賴scrollView
  • UIScrollView的自動布局原則

    • 1.UIScrollView的contentSize依賴于subviews.
    • 2.UIScrollView的contentSize必須根據其子控件如UIView的4條邊來確定.
    • 3.注意:如果只設置UIScrollView子控件的上下左右間距為0,是不能確定contentSize的,必須設置其子控件UIView的尺寸才能確定4條邊.

UIScrollView自動布局步驟(重要)

  • UIScrollView自動布局實現步驟
    • 1.給UIScrollView添加一個UIView,作為UIScrollView的contentView.之后要添加其他子控件可以往contentView上添加,這樣UIScrollView就只有contentView一個子控件,便于布局
    • 2.設置contentView的尺寸(寬,高),因為UIScrollView的contentSize是由它的子控件的frame決定的,contentView是UIScrollView的子控件,所以必須設置contentView的size才能確定contentSize.
    • 3.設置contentView的約束,比如設置約束上下左右間距都為0.

size和center設置注意點

  • size和center如果一起使用時,如果設置的是frame的size,必須先設置尺寸frame.size,再設置center.如果設置的是bounds的size,就無需考慮先后順序.因為center就是根據bounds中的size決定的.

  • 設置frame的size屬性,先設置尺寸frame.size,再設置center.

- (void)viewDidLoad {
    [super viewDidLoad];

    // 創(chuàng)建redView
    UIView *redView = [[UIView alloc] init];
    redView.backgroundColor = [UIColor redColor];
    [self.view addSubview:redView];
    
    // 先設置尺寸
    CGRect frame = redView.frame;
    frame.size = CGSizeMake(200, 200);
    redView.frame = frame;
    
    // 再設置center
    redView.center = CGPointMake(self.view.bounds.size.width * 0.5, self.view.bounds.size.height * 0.5);
}
  • 設置bounds的size屬性,無需先后順序.
- (void)viewDidLoad {
    [super viewDidLoad];

    // 創(chuàng)建redView
    UIView *redView = [[UIView alloc] init];
    redView.backgroundColor = [UIColor redColor];
    [self.view addSubview:redView];
    
    // 設置center
    redView.center = CGPointMake(self.view.bounds.size.width * 0.5, self.view.bounds.size.height * 0.5);
    
    // 設置尺寸
    CGRect bounds = redView.bounds;
    bounds.size = CGSizeMake(200, 200);
    redView.bounds = bounds;
}

bounds和frame簡介

bounds和frame介紹

  • frame和bounds的區(qū)別

    • frame:以父控件的左上角為原點
    • bounds:以自己左上角為原點,x,y = 0,(X)
  • frame和bounds描述一個矩形

    • frame:可視范圍
    • bounds:描述 可視范圍 在 內容范圍 區(qū)域
  • bounds本質:修改內容原點位置

    • 子控件是相對于控件內容范圍
    • frame:相對于父控件,位置永遠不變
    • frame:相對于內容,就會改變
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子同欠,更是在濱河造成了極大的恐慌,老刑警劉巖缸榄,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件忱反,死亡現場離奇詭異泛释,居然都是意外死亡,警方通過查閱死者的電腦和手機温算,發(fā)現死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門怜校,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人注竿,你說我怎么就攤上這事茄茁。” “怎么了巩割?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵裙顽,是天一觀的道長。 經常有香客問我宣谈,道長愈犹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任闻丑,我火速辦了婚禮漩怎,結果婚禮上,老公的妹妹穿的比我還像新娘嗦嗡。我一直安慰自己勋锤,他們只是感情好,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布侥祭。 她就那樣靜靜地躺著怪得,像睡著了一般。 火紅的嫁衣襯著肌膚如雪卑硫。 梳的紋絲不亂的頭發(fā)上徒恋,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天,我揣著相機與錄音欢伏,去河邊找鬼入挣。 笑死,一個胖子當著我的面吹牛硝拧,可吹牛的內容都是我干的径筏。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼障陶,長吁一口氣:“原來是場噩夢啊……” “哼滋恬!你這毒婦竟也來了?” 一聲冷哼從身側響起抱究,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤恢氯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體勋拟,經...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡勋磕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了敢靡。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挂滓。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖啸胧,靈堂內的尸體忽然破棺而出赶站,到底是詐尸還是另有隱情,我是刑警寧澤纺念,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布亲怠,位于F島的核電站,受9級特大地震影響柠辞,放射性物質發(fā)生泄漏。R本人自食惡果不足惜主胧,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一叭首、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧踪栋,春花似錦焙格、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至囤官,卻和暖如春冬阳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背党饮。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工肝陪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人刑顺。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓氯窍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蹲堂。 傳聞我的和親對象是個殘疾皇子狼讨,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內容