什么是響應(yīng)鏈庄蹋,它是怎么工作的耸弄?
這個問題筆者寫過一篇博客,里面有對這個問題的詳細(xì)解釋
如何訪問并修改一個類的私有屬性寨蹋?
- 有兩種方法可以訪問私有屬性,一種是通過KVC獲取,一種是通過runtime訪問并修改私有屬性
- 創(chuàng)建一個Father類,聲明一個私有屬性name,并重寫description打印name的值,在另外一個類中通過runtime來獲取并修改Father中的屬性
@interface Father ()
@property (nonatomic, copy) NSString *name;
@end
@implementation Father
- (NSString *)description
{
return [NSString stringWithFormat:@"name:%@",_name];
}
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Father *father = [Father new];
// count記錄變量的數(shù)量IVar是runtime聲明的一個宏
unsigned int count = 0;
// 獲取類的所有屬性變量
Ivar *menbers = class_copyIvarList([Father class], &count);
for (int i = 0; i < count; i++) {
Ivar ivar = menbers[i];
// 將IVar變量轉(zhuǎn)化為字符串,這里獲得了屬性名
const char *memberName = ivar_getName(ivar);
NSLog(@"%s",memberName);
Ivar m_name = menbers[0];
// 修改屬性值
object_setIvar(father, m_name, @"zhangsan");
// 打印后發(fā)現(xiàn)Father中name的值變?yōu)閦hangsan
NSLog(@"%@",[father description]);
}
}
iOS Extension 是什么?能列舉幾個常用的 Extension 么谦絮?
- Extension是擴(kuò)展,沒有分類名字,是一種特殊的分類,類擴(kuò)展可以擴(kuò)展屬性,成員變量和方法
- 常用的擴(kuò)展是在.m文件中聲明私有屬性和方法,這里不知道還哪些,請大家補(bǔ)充
如何把一個包含自定義對象的數(shù)組序列化到磁盤羞延?
- 自定義對象只需要實(shí)現(xiàn)
NSCoding
協(xié)議即可
- (void)viewDidLoad
{
[super viewDidLoad];
User *user = [User new];
Account *account = [Account new];
NSArray *userArray = @[user, account];
// 存到磁盤
NSData * tempArchive = [NSKeyedArchiver archivedDataWithRootObject: userArray];
}
// 代理方法
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
self.user = [aDecoder decodeObjectForKey:@"user"];
self.account = [aDecoder decodeObjectForKey:@"account"];
}
return self;
}
// 代理方法
-(void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:self.user forKey:@"user"];
[aCoder encodeObject:self.account forKey:@"account"];
}
Apple Pay 是什么?它的大概工作流程是怎樣的梢睛?
這個筆者也沒有詳細(xì)了解過,大家可以百度谷歌一下具體的
iOS 的沙盒目錄結(jié)構(gòu)是怎樣的肥印? App Bundle 里面都有什么?
1.沙盒結(jié)構(gòu)
- Application:存放程序源文件绝葡,上架前經(jīng)過數(shù)字簽名深碱,上架后不可修改
- Documents:常用目錄,iCloud備份目錄藏畅,存放數(shù)據(jù),這里不能存緩存文件,否則上架不被通過
- Library
- Caches:存放體積大又不需要備份的數(shù)據(jù),SDWebImage緩存路徑就是這個
- Preference:設(shè)置目錄敷硅,iCloud會備份設(shè)置信息
- tmp:存放臨時文件,不會被備份愉阎,而且這個文件下的數(shù)據(jù)有可能隨時被清除的可能
2.App Bundle 里面有什么
- Info.plist:此文件包含了應(yīng)用程序的配置信息.系統(tǒng)依賴此文件以獲取應(yīng)用程序的相關(guān)信息
- 可執(zhí)行文件:此文件包含應(yīng)用程序的入口和通過靜態(tài)連接到應(yīng)用程序target的代碼
- 資源文件:圖片,聲音文件一類的
- 其他:可以嵌入定制的數(shù)據(jù)資源
iOS 的簽名機(jī)制大概是怎樣的绞蹦?
假設(shè),我們有一個APP需要發(fā)布诫硕,為了防止中途篡改APP內(nèi)容坦辟,保證APP的完整性,以及APP是由指定的私鑰發(fā)的章办。首先锉走,先將APP內(nèi)容通過摘要算法,得到摘要藕届,再用私鑰對摘要進(jìn)行加密得到密文挪蹭,將源文本、密文休偶、和私鑰對應(yīng)的公鑰一并發(fā)布即可梁厉。那么如何驗(yàn)證呢?
驗(yàn)證方首先查看公鑰是否是私鑰方的踏兜,然后用公鑰對密文進(jìn)行解密得到摘要词顾,將APP用同樣的摘要算法得到摘要,兩個摘要進(jìn)行比對碱妆,如果相等那么一切正常肉盹。這個過程只要有一步出問題就視為無效。
iOS 7的多任務(wù)添加了哪兩個新的 API? 各自的使用場景是什么疹尾?
- 后臺獲壬先獭(Background Fetch):后臺獲取使用場景是用戶打開應(yīng)用之前就使app有機(jī)會執(zhí)行代碼來獲取數(shù)據(jù)骤肛,刷新UI。這樣在用戶打開應(yīng)用的時候窍蓝,最新的內(nèi)容將已然呈現(xiàn)在用戶眼前腋颠,而省去了所有的加載過程。
- 推送喚醒(Remote Notifications):使用場景是使設(shè)備在接收到遠(yuǎn)端推送后讓系統(tǒng)喚醒設(shè)備和我們的后臺應(yīng)用吓笙,并先執(zhí)行一段代碼來準(zhǔn)備數(shù)據(jù)和UI淑玫,然后再提示用戶有推送。這時用戶如果解鎖設(shè)備進(jìn)入應(yīng)用后將不會再有任何加載過程观蓄,新的內(nèi)容將直接得到呈現(xiàn)混移。
UIScrollView 大概是如何實(shí)現(xiàn)的,它是如何捕捉侮穿、響應(yīng)手勢的歌径?
- 我對UIScrollView的理解是frame就是他的contentSize,bounds就是他的可視范圍,通過改變bounds從而達(dá)到讓用戶誤以為在滾動,以下是一個簡單的UIScrollView實(shí)現(xiàn)
在頭文件定義一個contentSize屬性
@interface MyScrollView : UIView
@property (nonatomic) CGSize contentSize;
@end
@implementation MyScrollView
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self == nil) {
return nil;
}
// 添加一個滑動手勢
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panGesture:)];
[self addGestureRecognizer:pan];
return self;
}
- (void)panGesture:(UIPanGestureRecognizer *)gestureRecognizer{
// 改變bounds
CGPoint translation = [gestureRecognizer translationInView:self];
CGRect bounds = self.bounds;
CGFloat newBoundsOriginX = bounds.origin.x - translation.x;
CGFloat minBoundsOriginX = 0.0;
CGFloat maxBoundsOriginX = self.contentSize.width - bounds.size.width;
bounds.origin.x = fmax(minBoundsOriginX, fmin(newBoundsOriginX, maxBoundsOriginX));
CGFloat newBoundsOriginY = bounds.origin.y - translation.y;
CGFloat minBoundsOriginY = 0.0;
CGFloat maxBoundsOriginY = self.contentSize.height - bounds.size.height;
bounds.origin.y = fmax(minBoundsOriginY, fmin(newBoundsOriginY, maxBoundsOriginY));
self.bounds = bounds;
[gestureRecognizer setTranslation:CGPointZero inView:self];
}
- 第二個問題個人理解是解決手勢沖突,對自己添加的手勢進(jìn)行捕獲和響應(yīng)
// 讓UIScrollView遵守UIGestureRecognizerDelegate協(xié)議,實(shí)現(xiàn)這個方法,在這里方法里對添加的手勢進(jìn)行處理就可以解決沖突
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
Objective-C 如何對已有的方法,添加自己的功能代碼以實(shí)現(xiàn)類似記錄日志這樣的功能亲茅?
- 這題目主要考察的是runtime如何交換方法
先在分類中添加一個方法,注意不能重寫系統(tǒng)方法,會覆蓋
+ (NSString *)myLog
{
// 這里寫打印行號,什么方法,哪個類調(diào)用等等
}
然后交換方法
// 加載分類到內(nèi)存的時候調(diào)用
+ (void)load
{
// 獲取imageWithName方法地址
Method description = class_getClassMethod(self, @selector(description));
// 獲取imageWithName方法地址
Method myLog = class_getClassMethod(self, @selector(myLog));
// 交換方法地址回铛,相當(dāng)于交換實(shí)現(xiàn)方式
method_exchangeImplementations(description, myLog);
}
+load 和 +initialize 的區(qū)別是什么?
- +(void)load;
- 當(dāng)類對象被引入項(xiàng)目時, runtime 會向每一個類對象發(fā)送 load 消息
load 方法會在每一個類甚至分類被引入時僅調(diào)用一次,調(diào)用的順序:父類優(yōu)先于子類, 子類優(yōu)先于分類 - load 方法不會被類自動繼承
- 當(dāng)類對象被引入項(xiàng)目時, runtime 會向每一個類對象發(fā)送 load 消息
- +(void)initialize;
- 也是在第一次使用這個類的時候會調(diào)用這個方法
如何讓 Category 支持屬性克锣?
- 使用runtime可以實(shí)現(xiàn)
頭文件
@interface NSObject (test)
@property (nonatomic, copy) NSString *name;
@end
.m文件
@implementation NSObject (test)
// 定義關(guān)聯(lián)的key
static const char *key = "name";
- (NSString *)name
{
// 根據(jù)關(guān)聯(lián)的key茵肃,獲取關(guān)聯(lián)的值。
return objc_getAssociatedObject(self, key);
}
- (void)setName:(NSString *)name
{
// 第一個參數(shù):給哪個對象添加關(guān)聯(lián)
// 第二個參數(shù):關(guān)聯(lián)的key袭祟,通過這個key獲取
// 第三個參數(shù):關(guān)聯(lián)的value
// 第四個參數(shù):關(guān)聯(lián)的策略
objc_setAssociatedObject(self, key, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
NSOperation 相比于 GCD 有哪些優(yōu)勢验残?
- 提供了在 GCD 中不那么容易復(fù)制的有用特性。
- 可以很方便的取消一個NSOperation的執(zhí)行
- 可以更容易的添加任務(wù)的依賴關(guān)系
- 提供了任務(wù)的狀態(tài):isExecuteing, isFinished.
strong / weak / unsafe_unretained 的區(qū)別巾乳?
- weak只能修飾OC對象,使用weak不會使計(jì)數(shù)器加1,對象銷毀時修飾的對象會指向nil
- strong等價與retain,能使計(jì)數(shù)器加1,且不能用來修飾數(shù)據(jù)類型
- unsafe_unretained等價與assign,可以用來修飾數(shù)據(jù)類型和OC對象,但是不會使計(jì)數(shù)器加1,且對象銷毀時也不會將對象指向nil,容易造成野指針錯誤
如何為 Class 定義一個對外只讀對內(nèi)可讀寫的屬性?
在頭文件中將屬性定義為readonly
,在.m文件中將屬性重新定義為readwrite
Objective-C 中您没,meta-class 指的是什么?
meta-class 是 Class 對象的類,為這個Class類存儲類方法,當(dāng)一個類發(fā)送消息時,就去那個類對應(yīng)的meta-class中查找那個消息,每個Class都有不同的meta-class,所有的meta-class都使用基類的meta-class(假如類繼承NSObject,那么他所對應(yīng)的meta-class也是NSObject)作為他們的類
UIView 和 CALayer 之間的關(guān)系胆绊?
- UIView顯示在屏幕上歸功于CALayer氨鹏,通過調(diào)用drawRect方法來渲染自身的內(nèi)容,調(diào)節(jié)CALayer屬性可以調(diào)整UIView的外觀压状,UIView繼承自UIResponder仆抵,CALayer不可以響應(yīng)用戶事件
- UIView是iOS系統(tǒng)中界面元素的基礎(chǔ),所有的界面元素都繼承自它种冬。它內(nèi)部是由Core Animation來實(shí)現(xiàn)的镣丑,它真正的繪圖部分,是由一個叫CALayer(Core Animation Layer)的類來管理娱两。UIView本身传轰,更像是一個CALayer的管理器,訪問它的根繪圖和坐標(biāo)有關(guān)的屬性谷婆,如frame慨蛙,bounds等,實(shí)際上內(nèi)部都是訪問它所在CALayer的相關(guān)屬性
- UIView有個layer屬性纪挎,可以返回它的主CALayer實(shí)例期贫,UIView有一個layerClass方法,返回主layer所使用的類有序,UIView的子類蛉拙,可以通過重載這個方法球昨,來讓UIView使用不同的CALayer來顯示
+[UIView animateWithDuration:animations:completion:] 內(nèi)部大概是如何實(shí)現(xiàn)的?
- animateWithDuration:這就等于創(chuàng)建一個定時器
- animations:這是創(chuàng)建定時器需要實(shí)現(xiàn)的SEL
- completion:是定時器結(jié)束以后的一個回調(diào)block
以上只是自己的理解,不一定正確,有對這個有研究的朋友請告知下
什么時候會發(fā)生「隱式動畫」封孙?
當(dāng)改變CALayer的一個可做動畫的屬性,它并不能立刻在屏幕上體現(xiàn)出來.相反讽营,它是從先前的值平滑過渡到新的值虎忌。這一切都是默認(rèn)的行為,你不需要做額外的操作,這就是隱式動畫
如何處理異步的網(wǎng)絡(luò)請求橱鹏?
異步請求:會單獨(dú)開一個線程去處理網(wǎng)絡(luò)請求膜蠢,主線程依然處于可交互狀態(tài),程序運(yùn)行流暢
// POST請求
NSString *urlString = @"www.baidu.com";
// 創(chuàng)建url對象
NSURL *url = [NSURL URLWithString:urlString];
// 創(chuàng)建請求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10];
// 創(chuàng)建參數(shù)字符串對象
NSString *parmStr = [NSString stringWithFormat:@"參數(shù)"];
// 將字符串轉(zhuǎn)換為NSData對象
NSData *data = [parmStr dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:data];
[request setHTTPMethod:@"POST"];
// 創(chuàng)建異步連接
[NSURLConnection connectionWithRequest:request delegate:self];
然后實(shí)現(xiàn)代理方法
// 服務(wù)器接收到請求時
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
}
// 當(dāng)收到服務(wù)器返回的數(shù)據(jù)時觸發(fā), 返回的可能是資源片段
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
}
// 當(dāng)服務(wù)器返回所有數(shù)據(jù)時觸發(fā), 數(shù)據(jù)返回完畢
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
}
// 請求數(shù)據(jù)失敗時觸發(fā)
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"%s", __FUNCTION__);
}
frame 和 bounds 的區(qū)別是什么?
- frame相對于父視圖,是父視圖坐標(biāo)系下的位置和大小莉兰。bounds相對于自身,是自身坐標(biāo)系下的位置和大小挑围。
- frame以父控件的左上角為坐標(biāo)原點(diǎn),bounds以自身的左上角為坐標(biāo)原點(diǎn)
如何把一張大圖縮小為1/4大小的縮略圖糖荒?
let data = UIImageJPEGRepresentation(image, 0.25)