銀杏果

HTTPS和HTTP的區(qū)別主要如下:

1物赶、https協(xié)議需要到ca申請證書忍些,一般免費(fèi)證書較少,因而需要一定費(fèi)用。

2仰楚、http是超文本傳輸協(xié)議沃粗,信息是明文傳輸挂绰,https則是具有安全性的ssl加密傳輸協(xié)議抛腕。

3、http和https使用的是完全不同的連接方式肝劲,用的端口也不一樣迁客,前者是80,后者是443辞槐。

4掷漱、http的連接很簡單,是無狀態(tài)的榄檬;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸卜范、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,比http協(xié)議安全丙号。

IOS的ARC會導(dǎo)致的內(nèi)存泄露問題和解決方案

1.Block的循環(huán)引用
循環(huán)引用就是當(dāng)self 擁有一個block的時候先朦,在block 又調(diào)用self的方法。這個時候self強(qiáng)引用了block犬缨,而在block中使用self也會強(qiáng)引用self。這樣就會產(chǎn)生循環(huán)引用棉浸,導(dǎo)致兩個對象都得不到釋放怀薛。

 self.myBlock = ^{
    [self doSomething];
  };

解決的方法:掐斷其中的一條強(qiáng)引用,使之變成弱引用迷郑,變成這樣枝恋,就打破了循環(huán)引用:

__weak typeof (self) weakSelf = self;

還有一些系統(tǒng)的Block,這些Block中不用做特殊處理就可以直接使用self嗡害,因?yàn)檫@些系統(tǒng)的Block由系統(tǒng)strong引用焚碌,我們的代碼沒有強(qiáng)引用它

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    NSLog(@"Self.a %@", self.a);
});

2.NSTimer未釋放
在使用 NSTimer addtarget 時,為了防止 target 被釋放而導(dǎo)致的程序異常霸妹,timer 會強(qiáng)引用 target十电,所以這也是一處內(nèi)存泄露的隱患。解決方法是使用線程安全的MSWeakTimer,然后在dealloc中主動調(diào)用invalidate

- (void)dealloc {
   [timer invalidate];
}

3.performSelector 系列
performSelector分靜態(tài)調(diào)用和動態(tài)調(diào)用鹃骂,以下這種調(diào)用 selector 的方法和直接調(diào)用 selector 基本等效台盯,執(zhí)行效果相同,不存在內(nèi)存泄露

[object methodName];
[object performSelector:@selector(methodName)];

還有一種動態(tài)綁定方式畏线,編譯器不知道即將調(diào)用的 selector 是什么静盅,不了解方法簽名和返回值,甚至是否有返回值都不懂寝殴,所以編譯器無法用 ARC 的內(nèi)存管理規(guī)則來判斷返回值是否應(yīng)該釋放蒿叠。因此,ARC 采用了比較謹(jǐn)慎的做法蚣常,不添加釋放操作栈虚,即在方法返回對象時就可能將其持有,從而可能導(dǎo)致內(nèi)存泄露史隆。在ARC下編譯會告警:
warning: performSelector may cause a leak because its selector is unknow [-Warc-performSelector-leak]

-(void)method:(SEL)selector {
    [object performSelector:selector];
}

解決方式是使用函數(shù)指針魂务,顯示的聲明這個函數(shù)

IMP imp = [viewController methodForSelector:selector];
void (*func)(id, SEL) = (void *)imp;
func(viewController, selector);

4.Delegate循環(huán)引用
把delegate聲明為strong屬性導(dǎo)致了循環(huán)引用

@property (nonatomic, strong) SampleViewController *delegate;

解決方法很簡單把strong改成weak就行

@property (nonatomic, weak) SampleViewController *delegate;

5.循環(huán)未結(jié)束
如果某個ViewController中有無限循環(huán),也會導(dǎo)致即使ViewController對應(yīng)的view關(guān)掉了泌射,ViewController也不能被釋放粘姜。這種問題常發(fā)生于animation處理。

CATransition *transition = [CATransition animation];
transition.duration = 0.5;
tansition.repeatCount = HUGE_VALL;
[self.view.layer addAnimation:transition forKey:"myAnimation"];

解決辦法是熔酷,在ViewController關(guān)掉的時候孤紧,停止這個animation

-(void)viewWillDisappear:(BOOL)animated {
    [self.view.layer removeAllAnimations];
}

6.非OBJC對象
ARC是自動檢測OBJC對象的,非objc對象就無能為力了拒秘,比如C或C++等号显。
C語言使用 malloc 開辟,free釋放躺酒。
C++使用new 開辟押蚤,delete釋放。

但是在ARC下羹应,不會添加非OBJC對象釋放語句揽碘,如果沒去釋放,也會造成內(nèi)存泄露园匹。

即使用了ARC雳刺,我們也要深刻理解iOS的內(nèi)存管理機(jī)制,這樣才能有效避免內(nèi)存泄露裸违。

怎么理解封裝和模塊化

1.模塊劃分

做模塊化還是要結(jié)合實(shí)際業(yè)務(wù)掖桦,對目前APP的功能做一個模塊劃分,在劃分模塊的時候還需要關(guān)注模塊之間的層級供汛。

比如說涌穆,在我們項(xiàng)目中,模塊被分成了3個層級:基礎(chǔ)層料饥、中間層蒲犬、業(yè)務(wù)層。

  • 基礎(chǔ)層模塊比如像網(wǎng)絡(luò)框架岸啡、持久化原叮、Log、社交化分享這樣的模塊巡蘸,這一層的模塊我們可以稱之為組件奋隶,具有很強(qiáng)的可重用性。

  • 中間層模塊可以有登錄模塊悦荒、網(wǎng)絡(luò)層唯欣、資源模塊等,這一層模塊有一個特點(diǎn)是它們依賴著基礎(chǔ)組件但又沒有很強(qiáng)的業(yè)務(wù)屬性搬味,同時業(yè)務(wù)層對這層模塊的依賴是很強(qiáng)的境氢。

  • 業(yè)務(wù)層模塊,就是直接和產(chǎn)品需求對應(yīng)的模塊了碰纬,比如類似朋友圈萍聊、直播、Feeds流這樣的業(yè)務(wù)功能了悦析。

2.代碼隔離

模塊化首先要做的是代碼層面上獨(dú)立寿桨,任意一個基礎(chǔ)模塊都是可以獨(dú)立編譯的,底層模塊絕對不能有對上層模塊的代碼依賴强戴,還要確保未來也不會再出現(xiàn)這樣的代碼亭螟。

3.依賴管理

選擇使用CocoaPods另外一個重要原因就是骑歹,可以通過它來管理模塊間的依賴预烙,之前項(xiàng)目各個功能之所以難以復(fù)用的重要原因之一就是沒有聲明依賴

緩存問題

數(shù)據(jù)庫底層基于Sqlite。
每個數(shù)據(jù)庫表只有Key, Value兩個字段陵刹。
直接將JSON數(shù)據(jù)存儲到Value中,并設(shè)置Key默伍。
通過Key查找對應(yīng)Value數(shù)據(jù),來進(jìn)行數(shù)據(jù)增刪改查操作,并更新視圖。
1.使用SDWebImage緩存圖片衰琐。
2.使用YTKKeyValueStore更方便,也可以使用YYCache
3.使用FMDB操作數(shù)據(jù)庫炼蹦。

這三個必問項(xiàng):
自我介紹
大概介紹下你的項(xiàng)目
項(xiàng)目中的技術(shù)難點(diǎn)和問題以及怎么解決

command + R 之前發(fā)生了什么

  • 預(yù)處理
  • 語法和語義分析
  • 生成代碼和優(yōu)化
  • 匯編
  • 鏈接

main函數(shù)里發(fā)生了什么

1.系統(tǒng)先讀取App的可執(zhí)行文件( Mach-0文件)羡宙,從里面獲得dyld的路徑,然后加載dyld, dyld去初始化運(yùn)行環(huán)境掐隐。

2.開啟緩存策略狗热,加載程序相關(guān)依賴庫(其中也包含我們的可執(zhí)行文件)钞馁,并對這些庫進(jìn)行鏈接,最后調(diào)用每個依賴庫的初始化方法匿刮,在這一步僧凰,runt ime被初始化。

3.當(dāng)所有依賴庫的初始化后熟丸,輪到最后-位(程序可執(zhí)行文件)進(jìn)行初始化训措,在這時 runtime會對項(xiàng)目中所有類進(jìn)行類機(jī)構(gòu)初始化,然后調(diào)用所有的load方法光羞。最后dyld返回main函數(shù)地址绩鸣, main函數(shù)被調(diào)用,我們便來到程字入口main函數(shù)纱兑。

App之間跳轉(zhuǎn)實(shí)現(xiàn)

  1. URL Scheme方式

  2. Universal Links方式

雖然在微信內(nèi)部開網(wǎng)頁會禁止所有的Scheme呀闻,但是iOS 9.0新增加了一項(xiàng)功能是Universal Links,使用這個功能可以使我們的App通過HTTP鏈接來啟動App潜慎。
1.如果安裝過App捡多,不管在微信里面http鏈接還是在Safari瀏覽器,還是其他第三方瀏覽器铐炫,都可以打開App垒手。
2.如果沒有安裝過App,就會打開網(wǎng)頁驳遵。

iOS ipv4和ipv6

  1. 首先IPv6網(wǎng)絡(luò)下只能訪問IPv6站點(diǎn)淫奔,IPv4下只能訪問IPv4站點(diǎn)。兩者在不經(jīng)過DNS轉(zhuǎn)換前提下是無法直接互相訪問的堤结;
  2. IPv6網(wǎng)絡(luò)下通過域名到DNS服務(wù)器唆迁,然后首先去DNS66查找v6地址,發(fā)現(xiàn)沒有則繼續(xù)到DNS44查找v4竞穷,找到后返回v4地址唐责,DNS64合成IPv6地址,在經(jīng)過NAT64地址和協(xié)議轉(zhuǎn)換瘾带,最終路由到IPv4服務(wù)器鼠哥,最終完成IPv6網(wǎng)絡(luò)下通過域名訪問只有IPv4地址的站點(diǎn)或服務(wù)器。

3.ipv4轉(zhuǎn)換成ipv6 如下:

關(guān)于ipv6審核被拒絕的問題看政,公司給的服務(wù)器地址是ip地址朴恳,不是域名,所以在蘋果審核的時候遇到了ipv6的問題

GCDAsyncSocket.h第三方

.m文件

//
//  GCDAsyncSocket+GCDAsyncGetIPV6.m
//
//
//  Created by xuyushiguang on 2017/1/2.
//  Copyright ? 2017年 xuyushiguang. All rights reserved.
//

#import "GCDAsyncSocket+GCDAsyncGetIPV6.h"
#define IOS_CELLULAR    @"pdp_ip0"
#define IOS_WIFI        @"en0"
#define IOS_VPN         @"utun0"
#define IP_ADDR_IPv4    @"ipv4"
#define IP_ADDR_IPv6    @"ipv6"
#import <ifaddrs.h>
#import <arpa/inet.h>
#import <net/if.h>
@implementation GCDAsyncSocket (GCDAsyncGetIPV6)


/**
1允蚣,用于ip地址ipv4和ipv6之間的轉(zhuǎn)換(如果手機(jī)連接的是ipv6的wifi可用這個方法傳入ipv4獲取ipv6地址)
2于颖,根據(jù)傳入的ip地址,獲取你想要的IP地址嚷兔,比如手機(jī)連接的是ipv6的wifi森渐,你傳入的是ipv4的地址則返回一個ipv6的地址做入,前提是你的手機(jī)鏈接的是外網(wǎng)。
3同衣,怎么判斷手機(jī)連接的是不是ipv6的Wi-Fi竟块,可根據(jù)+(BOOL)isIpv6Net這個方法判斷
@param ipAddr 傳入的ip地址,主要是傳入ipv4的ip地址
@param port 端口號耐齐,要和你傳入的ip地址的端口號一直
@return 返回和手機(jī)連接的Wi-Fi的ip類型相同的ip浪秘,比如手機(jī)連接的是ipv6的Wi-Fi,則返回一個ipv6的地址
*/
+ (NSString*)getProperIPWithAddress:(NSString*)ipAddr port:(UInt32)port
{
    NSError *addresseError = nil;
    NSArray *addresseArray = [GCDAsyncSocket lookupHost:ipAddr
                                                   port:port
                                                  error:&addresseError];
    if (addresseError) {
        NSLog(@"");
    }
    NSString *ipv6Addr = @"";
    for (NSData *addrData in addresseArray) {
        if ([GCDAsyncSocket isIPv6Address:addrData]) {
            ipv6Addr = [GCDAsyncSocket hostFromAddress:addrData];
        }
    }
    if (ipv6Addr.length == 0) {
        ipv6Addr = ipAddr;
    }
    return ipv6Addr;
}


//判斷是否是ipv6(判斷手機(jī)連接的是不是ipv6的WiFi)
+ (BOOL)isIpv6Net{
    NSArray *searchArray =
    @[ IOS_VPN @"/" IP_ADDR_IPv6,
       IOS_VPN @"/" IP_ADDR_IPv4,
       IOS_WIFI @"/" IP_ADDR_IPv6,
       IOS_WIFI @"/" IP_ADDR_IPv4,
       IOS_CELLULAR @"/" IP_ADDR_IPv6,
       IOS_CELLULAR @"/" IP_ADDR_IPv4 ] ;
    NSDictionary *addresses = [self getIPAddresses];
    __block BOOL isIpv6 = NO;
    [searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop)
     {
         if ([key rangeOfString:@"ipv6"].length > 0  && ![[NSString stringWithFormat:@"%@",addresses[key]] hasPrefix:@"(null)"] ) {
             
             if ( ![addresses[key] hasPrefix:@"fe80"]) {
                 isIpv6 = YES;
             }
         }
     } ];
    return isIpv6;
}

//獲取手機(jī)連接的ip地址(包括ipv4地址和ipv6地址)
+ (NSDictionary *)getIPAddresses
{
    NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8];
    // retrieve the current interfaces - returns 0 on success
    struct ifaddrs *interfaces;
    if(!getifaddrs(&interfaces)) {
        // Loop through linked list of interfaces
        struct ifaddrs *interface;
        for(interface=interfaces; interface; interface=interface->ifa_next) {
            if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ ) {
                continue; // deeply nested code harder to read
            }
            const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr;
            char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ];
            if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) {
                NSString *name = [NSString stringWithUTF8String:interface->ifa_name];
                NSString *type;
                if(addr->sin_family == AF_INET) {
                    if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) {
                        type = IP_ADDR_IPv4;
                        
//                        NSLog(@"ipv4 %@",name);
                    }
                } else {
                    const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr;
                    if(inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) {
                        type = IP_ADDR_IPv6;
//                        NSLog(@"ipv6 %@",name);
                        
                    }
                }
                if(type) {
                    NSString *key = [NSString stringWithFormat:@"%@/%@", name, type];
                    addresses[key] = [NSString stringWithUTF8String:addrBuf];
                }
            }
        }
        // Free memory
        freeifaddrs(interfaces);
    }
    return [addresses count] ? addresses : nil;
}

@end

iOS .m文件總結(jié)

  1. .m文件是純Object-C 文件

    .mm是Object-C和C++混合文件

  2. .m只能調(diào)用純Object-C的類蚪缀,不能調(diào)用混合的

    .mm可以調(diào)用Object-C的秫逝,也可以調(diào)用C++的

  3. .m要調(diào)用混合的怎么辦?

    可以

解決辦法是.h用Object-C的方式询枚,而具體實(shí)現(xiàn)用.mm的方式

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末违帆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子金蜀,更是在濱河造成了極大的恐慌刷后,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件渊抄,死亡現(xiàn)場離奇詭異尝胆,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)护桦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進(jìn)店門含衔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人二庵,你說我怎么就攤上這事贪染。” “怎么了催享?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵杭隙,是天一觀的道長。 經(jīng)常有香客問我因妙,道長痰憎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任攀涵,我火速辦了婚禮铣耘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘以故。我一直安慰自己涡拘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布据德。 她就那樣靜靜地躺著鳄乏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪棘利。 梳的紋絲不亂的頭發(fā)上橱野,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天,我揣著相機(jī)與錄音善玫,去河邊找鬼水援。 笑死,一個胖子當(dāng)著我的面吹牛茅郎,可吹牛的內(nèi)容都是我干的蜗元。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼系冗,長吁一口氣:“原來是場噩夢啊……” “哼奕扣!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起掌敬,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤惯豆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后奔害,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體楷兽,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年华临,在試婚紗的時候發(fā)現(xiàn)自己被綠了芯杀。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡雅潭,死狀恐怖揭厚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情寻馏,我是刑警寧澤棋弥,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站诚欠,受9級特大地震影響顽染,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜轰绵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一粉寞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧左腔,春花似錦唧垦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽巧还。三九已至,卻和暖如春坊秸,著一層夾襖步出監(jiān)牢的瞬間麸祷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工褒搔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留阶牍,地道東北人。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓星瘾,卻偏偏與公主長得像走孽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子琳状,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評論 2 353