1,Search Bar 怎樣去掉背景的顔色(storyboard裡隻能設定background顔色,可是發現clear Color無法使用)。
其實在代碼裡還是可以設定的,那就是删除背景view
[[self.searchBar.subviews objectAtIndex:0] removeFromSuperview];
2,NSDate:
[java] view plain copy
- 字母 日期或時間元素 表示 示例
- G Era 标志符 Text AD
- y 年 Year 1996 96
- M 年中的月份 Month July; Jul; 07
- w 年中的周數 Number 27
- W 月份中的周數 Number 2
- D 年中的天數 Number 189
- d 月份中的天數 Number 10
- F 月份中的星期 Number 2
- E 星期中的天數 Text Tuesday; Tue
- a Am/pm 标記 Text PM
- H 一天中的小時數(0-23) Number 0
- k 一天中的小時數(1-24) Number 24
- K am/pm 中的小時數(0-11) Number 0
- h am/pm 中的小時數(1-12) Number 12
- m 小時中的分鐘數 Number 30
- s 分鐘中的秒數 Number 55
- S 毫秒數 Number 978
- z 時區 General time zone Pacific Standard Time; PST; GMT-08:00
- Z 時區 RFC 822 time zone -0800
[注意]在開發中,如果使用年月日,用NSDateFormatter setFormat :@"yyyy-MM-dd",如果是使用小時和分鐘,設定為:"HH:mm",切記不要設定“HH-mm”,這樣會出錯的。
舉例:
[java] view plain copy
- //建立一個時間對象
- NSData * date = [NSDate date];
- //列印時間
- NSLog(@"today is %@",date);
- //再擷取的時間date減去24小時的時間(昨天的這個時候)
- NSDate *yesterday = [NSDate dateWithTimeIntervalSinceNow:-(24*60*60)];
- NSLog(@"yesterday is %@",yesterday);//列印昨天的時間
- //設定一個字元串的時間
- NSString *datestring = [NSString stringWithFormat:@"1999-09-03"];
- //想要設定自己想要的格式,可以用nsdateformatter這個類,這裡是初始化
- NSDateFormatter * dm = [[NSDateFormatter alloc]init];
- //指定輸出的格式 這裡格式必須是和上面定義字元串的格式相同,否則輸出空
- [dm setDateFormat:@"yyyy-MM-dd"];
- //把字元串的時間轉換成Date對象,用dateFromString方法
- NSDate * newdate = [dm dateFromString:datestring];
- //輸出
- NSLog(@"newdate is %@",newdate);
- //把Date對象轉換成String對象 用stringFromDate方法
- NSString * datestring2 = [dm stringFromDate:newdate];
- //列印
- NSLog(@"datestring2 is %@",datestring2);
3,如果使用 UTTabviewCell,設定其accessory樣式為:Detail Disclosure ,就是在每一個cell右邊設定一個detail button。如果這樣的操作是使用storyboard,進行的,它會要求你給每一個你cell設定indentifier,然後你會在以下方法内設定重用indentfier,别忘記加上一句話,否則編譯運作時可能會彈出: cell未執行個體化
4,在開發項目中,有時有這樣的需求:運作程式,登陸界面是一個自由的ViewController,隻是擺放幾個TextField和button,點選後跳轉到孩子選擇或其它選擇界面,點選選項後進入我們的主界面:這個時候,在登陸界面作跳轉時,會有好多的方法,如果使用storyboard,就比較友善了,設定一個segue,跳轉代碼中:
[self PerformSegueWithIdentifier:@"targetViewController",self]; 就可以了,可是我想執行個體化想要跳轉的控制器,然後設定某一屬性的值,這樣跳轉後控制器擷取那個屬性,就會得到值了,可是這樣做會有一個問題:
主界面控制器如果使用了navigatorViewController,并且是其RootViewController,等到在主界面設定功能,點選某一功能,想push到一個新頁面時,問題就來了,你會發現毫無反應,沒有報錯,隻是segue無法跳轉。後來終于找到原因:就是我在登陸控制器跳轉時沒有使用segue的方法,而是用代碼self.storyboard,加載一個新類,具體原理目前還沒有搞明白,先把出問題的代碼記錄下來,回頭補之:
代碼這樣做,會導緻其後無法使用navigatorViewController做push跳轉
5,(1010更新)開發過程中,我們通過http請求,背景傳回json資料,而有時資料裡某一字段的值為null~,然後我們把此值指派給NSArray,NSdictionary,或是NSString,然後我們會判斷此值為null時,所做的處理,而通常慣性思維判斷時我們都會寫:if(dict == nil)或是if(dict == Nil)或是if(dict == NULL)再或是if(dict isEqual nil),我們發現,都不好用,根本沒有起到判斷的作用~後來我才發現,原來不能這樣來判斷。
簡單點說,就是當字典,數組為null時,背景列印的輸出結果是這樣:
然後,我們需要在代碼判斷時利用[NSNull null]來判斷,具體如:
isEqual:[NSNull null] 就搞定了,nsarray也是同樣的道理。
控制台列印:str=(null) 代表着 字元串或數組或字典是一個空指針,(而非空字元串)判斷的時候,直接用:
if(str == nil)就可以了。如下圖所示:
而控制台列印:str = <null>,代表着這是一個空字元串,指派為空,指針是存在的,隻是内容為空,這種判斷需要使用:
if(str is equal [NSNull null ]) ,因為在ios上,内容為空不能簡單的判斷str==null(null 在ios上得用[NSNull null])
一般這種情況是,伺服器那邊是null,直接傳回@"null"的字元串,這樣在ios這邊不好判斷,最好跟背景溝通,如果遇到null值,傳回@"",好做判斷
6,給uiview設定圓角樣式
隻需在加載時,添加這樣的話就可以了:
testView.layer.cornerRadius = 6;
testView.layer.masksToBounds = YES;
注意,需要 import <QuartzCore/QuartzCore.h> 導入,否則,不能識别cornerRadius和masksToBounds。
uiview設定背景圖檔:
[theMainView setBackgroundColor: [UIColor colorWithPatternImage: [UIImage imageNamed: @"bg.png"]]];
imageName 緩存,下面方法不緩存
NSString *thePath = [[NSBundle mainBundle] pathForResource:@"default" ofType:@"jpeg"];
UIImage *prodImg = [[UIImage alloc] initWithContentsOfFile:thePath"];
controller.productImg.image = prodImg;
[prodImg release];
7,隐藏鍵盤的兩種方法
1-1Did End On Exit 調用下面事件當點選鍵盤return得時候就會隐藏鍵盤
- (IBAction)textFieldShouldReturn:(UITextField *)textField {
//[sender resignFirstResponder];
if (textField == chi) {
[chi resignFirstResponder];
double m=[chi.textdoubleValue]/3.003;
double f=m *3.2808;
meter.text=[[NSStringalloc] initWithFormat:@"%.4f",m];
feet.text=[[NSStringalloc] initWithFormat:@"%.4f",f];
}
if (textField == meter) {
[meter resignFirstResponder];
}
if (textField == feet) {
[feet resignFirstResponder];
}
}
1-2 點選螢幕得時候隐藏鍵盤
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch=[[event allTouches] anyObject];
if (touch.tapCount >=1) {
[chi resignFirstResponder];
[meter resignFirstResponder];
[feet resignFirstResponder];
}
}
1-2的方法相當于螢幕任何位置的點選事件(除了各元件的點選處)可以在這個方法裡執行要隐藏或remove的view。
8,UITextField密文顯示輸入内容:
隻需要在TextField屬性中的Secure(安全的)勾選上就可以了。顯示apple預設的密文顯示方式。
9,通過系統自帶的NSPredicate使用正規表達式。(在TextField中)
[java] view plain copy
- NSString *regex =[NSString stringWithFormat:@"^1(3[4-9]|5[012789]|8[2378]|47)\\d{8}$"];
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
- BOOL isMatch = [predicate evaluateWithObject:editPhoneField.text];
10,項目設定應用程式顯示名稱:
1,在項目的Supporting Files下尋找infoPlist.strings檔案,打開後會看到一片空白(英文預設是跟随項目名稱顯示)。此時,可以就地添加一句代碼:CFBundleDisplayName="愛貝通";
這樣的話,無論手機設定英文語言還是中文語言,應用程式都會顯示設定的名稱。
2,為了國際化而言,我們最好建立一個chinese專有的infoPlist.strings檔案。
如上圖所示,添加一個中文的plist
然後打開添加代碼:
這個時候,大功告成。部署在模拟器或真機中吧,你的手機設定(中/英)文語言,它就會調用相應的配置檔案。
11更改Xcode的預設公司名
[java] view plain copy
- // testAppDelegate.m
- // test
- //
- // Created by gaohf on 11-5-24.
- // Copyright 2011 __MyCompanyName__. All rights reserved.
在終端中執行以下指令:
[java] view plain copy
- defaults write com.apple.Xcode PBXCustomTemplateMacroDefinitions '{"ORGANIZATIONNAME" = "COMPANY";}'
[java] view plain copy
- //
- // testAppDelegate.m
- // test
- //
- // Created by gaohf on 11-5-24.
- // Copyright 2011 COMPANY. All rights reserved.
- //
12,在有uinavigation,uitoolbar的情況下,如何添加一個全屏的 uiview (一般是作為顯示一個進度框,任何區域無法觸摸而使用)
隻需要在要添加view時侯這樣寫:
[java] view plain copy
- [[UIApplication sharedApplication].keyWindow addSubview:waitingview];
這樣,直接把waitingview添加到了uiWindow上,而不是self.view上。再次運作,會發現螢幕全部區域都已經遮擋住了。
13,使用了storyboard,運作程式模拟器顯示黑屏,這是由于,操作不當,擷取點選了例如 navigationViewController屬性種的in init ViewController選項,然後重置了目前進入程式後的首界面,解決辦法就是選擇入口界面,屬性種重新勾選此選項。
StoryboardApp[8593:207] Failed to instantiate the default view controller for UIMainStoryboardFile 'MainStoryboard' - perhaps the designated entry point is not set?
StoryBoard中沒有一個view controller設定了Initial Scene。您需要選擇一個view conroller作為story board的第一個界面:
14,如何給uiNavigationBar 設定背景顔色或是自定義圖檔?
在項目中添加如下代碼:
//設定背景顔色:
[java] view plain copy
- UIColor *itemcolor = [UIColor colorWithRed:100.0f/255.0f green:176.0f/255.0f blue:0.0f/255.0f alpha:0.3f];
- self.navigationController.navigationBar.tintColor = itemcolor;
//設定自定義的圖檔:
[java] view plain copy
- [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"navbg.png"] forBarMetrics:UIBarMetricsDefault];
5.0以上,api有了上面setBackgroundImage的方法,可以直接設定,如果項目需要适配5.0以下版本的裝置,最好加一個判讀,是否有此函數,有則設定,沒有就通過drawRect方法設定。
另外:設定背景圖檔無法比對backButton或rightButtonItem,是以傳回按鈕或右邊自定義的Bar button Item需要自行處理。
15,如何給uiview設定背景圖檔?
在storyboard或xib中,添加一個uiview,屬性設定欄一般都有設定背景顔色,樣式,透明度alpha,但是沒有提供設定image,隻有在imageview中才有,是以,要想設定背景圖檔,隻能在代碼中設定,如下:
[java] view plain copy
- [leftNaviView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"pabb_leftnaviview_bg.png"]]];
這樣,背景就可以變成想要的圖檔了。另外,設定大小:
[java] view plain copy
- [leftNaviView setFrame:CGRectMake(9, 60, 120, 250)];
效果圖:
16如何在項目用代碼打開AppStore軟體(也就是通路appstore)
[java] view plain copy
- //以下是通過id打開此軟體的評價
- // int m_appleID = 576337094;
- // NSString *str = [NSString stringWithFormat:
- // @"itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=%d",
- // m_appleID ];
- //以下是通過appstore連結到自己應用在商店的位置
- NSString *url = [NSString stringWithFormat:@"http://itunes.apple.com/cn/app/huo-xing-she-xin-dian/id549425594?l=en&mt=8"];
- [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
把以上代碼直接拷貝到想要實作點選跳轉的操作方法内就可以了,通過appID,随意可以通過appstore打開應用,直接用url就可以連結到了。很簡單,一般都用在檢查更新的時候。
17,如何代碼實作點選http://www.kaka.com或400-800-400或message實作跳轉safari,phone或message?
隻需要在相應的代碼中寫入:
1、調用 電話phone
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel://4008008288"]];
2、調用自帶 浏覽器 safari
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://www.abt.com"]];
3、調用 自帶mail
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"mailto://[email protected]"]];
4、調用 SMS
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"sms://800888"]];
5,跳轉到系統設定相關界面
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=WIFI"]];
其中,發短信,發Email的功能隻能填寫要發送的位址或号碼,無法初始化發送内容,如果想實作内容的話,還需要更複雜一些,實作其各自的委托方法。
若需要傳遞内容可以做如下操作:
加入:MessageUI.framework
#import <MessageUI/MFMessageComposeViewController.h>
實作代理:MFMessageComposeViewControllerDelegate
[java] view plain copy
- 調用sendSMS函數
- //内容,收件人清單
- - (void)sendSMS:(NSString *)bodyOfMessage recipientList:(NSArray *)recipients
- {
- MFMessageComposeViewController *controller = [[[MFMessageComposeViewController alloc] init] autorelease];
- if([MFMessageComposeViewController canSendText])
- {
- controller.body = bodyOfMessage;
- controller.recipients = recipients;
- controller.messageComposeDelegate = self;
- [self presentModalViewController:controller animated:YES];
- }
- }
- // 處理發送完的響應結果
- - (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
- {
- [self dismissModalViewControllerAnimated:YES];
- if (result == MessageComposeResultCancelled)
- NSLog(@"Message cancelled")
- else if (result == MessageComposeResultSent)
- NSLog(@"Message sent")
- else
- NSLog(@"Message failed")
- }
- 發送郵件的為:
- 導入#import <MessageUI/MFMailComposeViewController.h>
- 實作代理:MFMailComposeViewControllerDelegate
- //發送郵件
- -(void)sendMail:(NSString *)subject content:(NSString *)content{
- MFMailComposeViewController *controller = [[[MFMailComposeViewController alloc] init] autorelease];
- if([MFMailComposeViewController canSendMail])
- {
- [controller setSubject:subject];
- [controller setMessageBody:content isHTML:NO];
- controller.mailComposeDelegate = self;
- [self presentModalViewController:controller animated:YES];
- }
- }
- //郵件完成處理
- -(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error{
- [self dismissModalViewControllerAnimated:YES];
- if (result == MessageComposeResultCancelled)
- NSLog(@"Message cancelled");
- else if (result == MessageComposeResultSent)
- NSLog(@"Message sent");
- else
- NSLog(@"Message failed");
- }
- 預設發送短信的界面為英文的,解決辦法為:在.xib 中的Localization添加一組chinese
18,注冊設定應用程式通路使用者手機發送推送消息,(彈出Alertview)
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
19,輕松自定義複選框按鈕
-(void)checkboxClick:(UIButton *)btn
{
btn.selected = !btn.selected;
}
- (void)viewDidLoad {
UIButton *checkbox = [UIButton buttonWithType:UIButtonTypeCustom];
CGRect checkboxRect = CGRectMake(135,150,36,36);
[checkbox setFrame:checkboxRect];
[checkbox setImage:[UIImage imageNamed:@"checkbox_off.png"] forState:UIControlStateNormal];
[checkbox setImage:[UIImage imageNamed:@"checkbox_on.png"] forState:UIControlStateSelected];
[checkbox addTarget:self action:@selector(checkboxClick:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:checkbox];
}
20,程式中擷取軟體的版本号和app名稱
[java] view plain copy
- 應用程式的名稱和版本号等資訊都儲存在mainBundle的infoDictionary字典中,用下面代碼可以取出來。
- NSDictionary* infoDict =[[NSBundle mainBundle] infoDictionary];
- NSString* versionNum =[infoDict objectForKey:@"CFBundleVersion"];//版本名稱
- NSString*appName =[infoDict objectForKey:@"CFBundleDisplayName"];//app名稱
- NSString*text =[NSString stringWithFormat:@"%@ %@",appName,versionNum];
此version 為工程info下的Bundle version字段值:value可以随意定義。
21,如何使螢幕一直保持喚醒狀态?(就是不自動黑屏)
比如,如果我們做一個播放視訊的功能時,想在播放的時候,不會自動進入屏保(黑屏)
隻要在代碼裡加入這一行:
[java] view plain copy
- [[UIApplication sharedApplication] setIdleTimerDisabled:YES];
當然,在想要黑屏的時候還需要把它設定為NO(比如視訊播放完畢時),不然螢幕會在此軟體運作下一直亮着。
22,一直以來的疑問:在Xcode中,有時候在類名稱後邊帶有M或C等标示,不知道為何意。如下圖所示:
表示在版本控制中,自上一次送出以來,檔案做了修改。貌似隻有在帶有版本控制的項目代碼中才會顯示。
23,有關ios上螢幕旋轉,view設定Frame的相關問題(ios5)。
螢幕旋轉一共有4個相關屬性(旋轉方向):
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
UIInterfaceOrientationPortrait
UIInterfaceOrientationPortraitUpsideDown
前兩個是橫屏時的狀态,後兩個是正常狀态(Portrait)和上下颠倒(UpsideDown)時的狀态。
【注意:Left和Right兩個左右模拟器旋轉時移動的方向正好是相反的,但移動後Home的方向,就如下圖所示】
具體見下圖:
其中涉及到兩個方法,在ViewController中預設會實作這個方法:
[java] view plain copy
- - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
- {
- //除了不允許旋轉螢幕後:上下颠倒,其餘方向都運作旋轉
- //如果想都運作,可以直接傳回YES,或都不允許NO
- return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
- }
這個方法是聲明此ViewController所運作螢幕旋轉的方向,一共4種類型,全部允許傳回YES,上圖所示除了不允許上下颠倒,其餘都可以。【注意,項目設定Supported Device Orientations 所支援的螢幕旋轉類型并不影響此方法的設定,也就是說,哪怕Support隻支援Portrait,方法裡設定UpsideDown,此ViewController也會實作上下颠倒旋轉的】
第二個方法,是我們比較常用的,也就是在裝置即将以某個方向旋轉之前,我們在其狀态(方向)設定元件或view的Frame,bound,等需要改變的屬性時所用到的方法。
[java] view plain copy
- -(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
- //螢幕旋轉到橫屏時
- if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
- myMapview.frame = CGRectMake(0,0,480, 300);
- }
- //螢幕旋轉到豎屏時
- else{//== else if(UIInterfaceOrientationIsPortrait(toInterfaceOrientation))
- myMapview.frame = CGRectMake(0, 0, 320,460);
- }
- }
所有旋轉螢幕後需要改變元件尺寸屬性的設定都可以在這個方法裡面實作。
【注意,以上兩個方法,在最新的ios6貌似已經不提倡使用了,除非要适應舊裝置,新的旋轉螢幕的相關方法可以網絡搜尋一下】
http://blog.csdn.net/zzfsuiye/article/details/8251060 IOS6螢幕旋轉詳解(自動旋轉、手動旋轉、相容IOS6之前系統)
http://blog.csdn.net/huifeidexin_1/article/details/7826159 ios旋轉螢幕總結 詳細教程
http://blog.csdn.net/xiaoyun8822/article/details/8213738 Ios5(三)螢幕的旋轉和大小設定;
以上為參考教程
24,Xcode編譯警告和錯誤解決方法:
1 Application windows are expected to have a root view controller at the end of application launch
解決方法:在ios5以上版本,應用程式加載時,需要一個 root view controller ,是以需要編寫代碼
_rootViewController = [[RootViewController alloc] init];
self.window.rootViewController = _rootViewController;
此問題大多是在Xib或Storyboard下操作ViewController時不小心連接配接RootViewController 的底層View所導緻的,檢查删除沒有作用的view連接配接線,或是Clean,再運作。
25,如何設定視圖(view)在最上層?或是view1和view2交換?
情景再現:
我們在storyboard的一個視圖裡添加了一個view1用作快捷功能導航;然後在對應的viewController裡執行個體化了一個Mapview的地圖view2,大小是整個螢幕,這樣一來,就把我們在storyboard中添加的view1覆寫了,這個時候,我們想把view1在地圖view2的上面,該怎麼做?
簡而言之就是window中subview的交換。
首先通過:NSLog(@"subviews:%@",self.view.subviews); 這個我們可以看到目前下所有的subview(NSArray類型)如下圖所示:
可以看到一共有3個view:UILabel 地圖view2,添加的view1
我們現在要做的就是把後兩者對調一下,是以在self.view 中尋找一下看有沒有replace相關的方法
就是這個方法,第一個參數是要進行調換的地圖view2,第二個參數是調換後顯示的view1。
[self.viewexchangeSubviewAtIndex:1withSubviewAtIndex:2];
因為通過log列印,我們已經知道Mapview在第一個下标的位置,view1在第二個下标的位置。
大功告成。記住這個方法:self.view exchangeSubviewAtIndex:withSubviewAtIndex:];
26,如何隐藏UINavigationBar
有的時候,我們的視圖使用了Navigation Controller ,但是主界面(rootviewcontroller)或其它push進入的界面 想使用一個全屏的view,就是說,不顯示頂部的navigationBar,這個時候,就需要我們來隐藏了。
//隐藏NavigationBar
-(void) viewWillAppear:(BOOL)animated{
[self.navigationControllersetNavigationBarHidden:YESanimated:YES]; //設定隐藏
[super viewWillAppear:animated];
}
-(void) viewWillDisappear:(BOOL)animated{
[self.navigationControllersetNavigationBarHidden:NOanimated:YES];
[super viewWillDisappear:animated];
}
27,如何限制UITextField輸入長度(監聽textField文本變化的事件)
1、實作UITextFieldDelegate協定;
2、實作textField:shouldChangeCharactersInRange:replacementString:方法;
[java] view plain copy
- -(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
- int kMaxLength = 11;
- NSInteger strLength = textField.text.length - range.length + string.length;
- //輸入内容的長度 - textfield區域字元長度(一般=輸入字元長度)+替換的字元長度(一般為0)
- return (strLength <= kMaxLength);}
如上代碼,如果我們簡單的這樣寫: if(range.location<=11) return 或是 if (textfield.text.length>=11) 這樣雖然也能限制位數為11位,但是如果通過放大鏡把光标切換到之前的位數後,你照樣可以輸入,并且還會導緻輸入11位後,鍵盤上的倒退(X鍵)無法使用,原因是:我們在location到達11位後,傳回了NO,鍵盤無法相應:添加,修改,删除。這是很嚴重的。是以照着我上面的。
方法解讀:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
功能:
把textField中位置為range的字元串替換為string字元串;
此函數在textField内容被修改時調用;
傳回值:
YES,表示修改生效;NO,表示不做修改,textField的内容不變。
參數說明:
textField:響應UITextFieldDelegate協定的UITextField控件。
range: UITextField控件中光标選中的字元串,即被替換的字元串;
range.length為0時,表示在位置range.location插入string。
string: 替換字元串; string.length為0時,表示删除。
28,使用ios5.0以後的一個方法自定義table View Cell
[cpp] view plain copy
- UINib *nib = [UINib nibWithNibName:@"TvWeiboCell" bundle:nil];
- [tableView registerNib:nib forCellReuseIdentifier:CellIdentifier];
29,iOS和iPad各app圖示和啟動頁尺寸。
iphone APP圖示尺寸:57X57 高清:114X114 機關:pixel 命名:無特殊要求,最好是,app_icon 高清的要加@2x
iphone 啟動頁尺寸:大小最好是320X460或320X480(相當于整個螢幕尺寸) 機關:pixel 命名:Default.png
iPad APP圖示尺寸:72X72 高清:144X144 機關:pixel 命名:
ipad 啟動頁尺寸:大小最好是768X1004或768X1024 機關:pixel 命名:Default-Portrait~ipad.png 高清:[email protected]~ipad.png
30,如何用NSLog輸出NSRange,CGRect等結構體。
NSString 中的方法:
NSStringFromCGPoint
NSStringFromCGSize
NSStringFromCGRect
NSStringFromCGAffineTransform
NSStringFromUIEdgeInsets
如:NSLog(@"rect1: %@", NSStringFromCGRect(rect1));
31,如何在navigationviewcontroller中,pop到之前不同的viewcontroller(push過的viewcontroller)?
如上圖所示,回退到界面2,很簡單: [self.navigationControllerpopViewControllerAnimated:YES]; 直接就回退到界面2了,可是我們既不想回到rootviewcontroller,也不想回到界面2,隻想回到界面1,該如何做?
笨方法:在界面1要跳轉到界面2時,把自己self,set到界面2(前提界面2要設定一個id類型的屬性,用來存放界面1self,以此類推,當在界面3想退到界面1時,
[self.navigationControllerpopToViewController:controlleranimated:YES];
其實作在剛明白,一個很簡單的方法:
[cpp] view plain copy
- NSArray *viewControllers=[self.navigationController viewControllers];
- UIViewController *controller=[viewControllers objectAtIndex:1];
想起來navigation的機制了吧,每當我們push到一個viewcontroller時,就會把這個viewcontroller的執行個體儲存到nsarray裡,通過array可以擷取到任何一個viewcontroller,這不就解決問題了麼?
[cpp] view plain copy
- [self.navigationController popToViewController:controller animated:YES];
【注意】千萬不要在這個地方執行個體化 界面1 然後popToViewController,這種方法是不對的。
32,self.navigationItem.backBarButtonItem 的title設定
新寫的App中需要使用UINavigationController對各個頁面進行導航,但由于第一級頁面的title較長,在進入第二級頁面後傳回按鈕leftButtonItem的title就會變得很長,對NavigationBar空間占用很大,而且不美觀,于是使用代碼對leftButtonItem的title文本進行修改,無論是設定self.navigationItem.leftBarButtonItem.title = @"傳回";還是self.navigationItem.backBarButtonItem.title = @"傳回";都沒有效果,title文本始終不會發生變化。到網上亂搜一通後,得到了以下解決方法,相對來說比較簡單,特記錄如下:
在第一級頁面的viewDidLoad方法中加入以下代碼:
[cpp] view plain copy
- UIBarButtonItem *temporaryBarButtonItem = [[UIBarButtonItem alloc] init];
- temporaryBarButtonItem.title =@"傳回";
- self.navigationItem.backBarButtonItem = temporaryBarButtonItem;
- [temporaryBarButtonItem release]; // 也就是用一個新的按鈕在進行導航前将原來的傳回按鈕替換掉就可以了。
是以,通過這個我們可以明白, self.navigationItem.backBarButtonItem是在一級頁面設定的(提前設定下一個頁面的傳回按鈕),而self.navigationItem.leftBarButtonItem/rightBarButton是在二級頁面設定的,(随意設定本頁面的左右按鈕,左按鈕将替代系統的傳回按鈕)
---------------------------------------------------------------------------------------------------------
一般一個程式中有一個UIWindow,一個UINavigationController,一個根UIViewController,多個子UIViewController。
UIWindow是整個可視界面的容器,裡面放置我們看到的UIView。
UIView負責處理螢幕上一個矩形區域的繪制,UIView中還可包含子UIView。
UIWindow是UIView類的擴充,可以看作是整個螢幕的根UIView。
UIViewController負責管理UIView的層次結構。可以有多個UIViewController。
一個UIViewController中有一個頂部的UINavigationBar、一個根UIView,多個子UIView。
UINavigationBar中有一個UINavigationItem,UINavigationItem。
UINavigationController是用于建構分層應用程式的主要工具,它維護了一個UIViewController棧。
這個棧中必須有一個根UIViewController,其他的UIViewController都是子UIViewController。
UINavigationItem表示UINavigationBar中的控件,比如左按鈕、中間标題、右按鈕。
UINavigationController會自動在目前子UIViewController的UINavigationBar左邊添加一個傳回按鈕。
按鈕名稱是上一個UIViewController的标題。
---------------------------------------------------------------------------------------------------------
33,self.navigationItem和self.navigationController.navigationItem的差別?
self.navigationItem
self.navigationController.navigationItem
self.navigationController.navigationBar
1, 不要混淆 self.navigationItem 和 self.navigationController.navigationItem ,
UINavigationItem 本身是用來 定制 ViewController自己在被導航過程中的 appearence, navigationItem是UIViewController類關于UINavigationControllerItem類别的擴充:
@interface UIViewController (UINavigationControllerItem)
@property(nonatomic,readonly,retain)UINavigationItem * navigationItem;
...
@end
是以後者 是調用 VC的所在的導航控制器導航控制器自己自己作為VC的 navigationItem,是導航的疊加。
2. UINavigationBar 繼承于 UIView,隸屬于整個 UINavigationController ,用來定義整個導航過程中的導航欄的顔色等其他數值,(類似于 self.tabBarController.tabBar UINavigationBar ,隻需要一個設定通用的基本屬性),隻能通過self.navigationController.navigationBar來通路。
亦是以,定制于導航堆棧裡某個VC 的時候,一般通過self.navigationItem, 比如常用的self.navigationItem.leftBarButtonItem,self.navigationItem.rightButtonItem, 同時如果自己來定制導航欄的外觀的話,就要用到self.navigationItem.titleView,這個可以直接用一個 CustomView 指派于self.navigationItem.titleView即可。
此時,如果需要,就得自己畫導航過程中的傳回按鈕了。
34,圖檔模糊化處理
[cpp] view plain copy
- +(UIImage *)scale:(UIImage *)image toSize:(CGSize)size
- {
- UIGraphicsBeginImageContext(size);
- [image drawInRect:CGRectMake(0, 0, size.width, size.height)];
- UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
- UIGraphicsEndImageContext();
- return scaledImage;
- }
35,NSString轉換大小寫的用法
iOS 6中NSString對象有些新的使用方法,可以讓字元串轉變成全部大寫,全部小寫,或者每個單詞首字母大寫。
代碼如下所示:
[cpp] view plain copy
- NSString *str = @"mobile developer tips";
- // Convert string to uppercase
- NSString *upperStr = [str uppercaseStringWithLocale:[NSLocale currentLocale]];
- NSLog(@"upperStr: %@", upperStr);
- // Convert string to caps
- NSString *capStr = [upperStr capitalizedStringWithLocale:[NSLocale currentLocale]];
- NSLog(@"capStr: %@", capStr);
- // Convert string to lowercase
- NSString *lowerStr = [capStr lowercaseStringWithLocale:[NSLocale currentLocale]];
- NSLog(@"lowerStr: %@", lowerStr);
運作結果:
36,如何擷取手機硬體資訊?
通過使用UIDevice:
[[UIDevice currentDevice] systemName];
[[UIDevice currentDevice] systemVersion];//os version
[[UIDevice currentDevice] uniqueIdentifier];
[[UIDevice currentDevice] model];
[[UIDevice currentDevice] name];
真機上結果:
System Name: iPhone OS
System Version: 4.2.1
Unique ID: 9b5ded78d5fa0ac96250f8b4af0e46f40b96ea6d
Model: iPhone
Name: “wwk”的 iPhone
模拟器上結果:
System Name: iPhone OS
System Version: 4.2
Unique ID: 21FFE0FF-429B-5D0B-96D2-EADCA3203260
Model: iPhone Simulator
Name: iPhone Simulator
uniqueIdentifier:iPhone通過,向幾個硬體辨別符和裝置序列号應用内部雜湊演算法,而生成這一辨別符。
http://blog.csdn.net/qiwancong/article/details/7914923 參考
36,真機調試:could not change executable permissions錯誤?
雖然更改了新demo的bundle identifier和之前的identifier一樣,但是真機上還保留着之前調試時的demo,是以新的工程如果使用同樣的identifier真機調試,需要先把機器上原來的demo删除,再使用新工程調試。
37,判斷iphone5螢幕的宏定義
[cpp] view plain copy
- #define iPhone5 ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(640, 1136), [[UIScreen mainScreen] currentMode].size) : NO)
在需要判斷螢幕尺寸的地方:
[cpp] view plain copy
- mymapview = [[BMKMapView alloc] initWithFrame:CGRectMake(0,0,320,460+(iPhone5?88:0))];
iphone5的View為568,減去Nav(44)+工作列(20),為504,相比iphone4s及以前版本的480,減去Nav+工作列,為416,高出88(差别).
http://www.cnblogs.com/maxfong/archive/2012/10/04/2711379.html
38、invalid deployment target for -stdlib=libc++ (requires iOS 5.0 or later)錯誤
選中項目--target---build settings 找到C++Standard Library 改成:Compiler Default,再編譯就不會有錯誤了.
39,如何調用系統聲音?【iphone 調用系統鈴聲與震動功能】
首先要在工程裡加入Audio Toolbox framework這個庫,然後在需要調用的檔案裡
#import <AudioToolbox/AudioToolbox.h>
最後在需要播放提示音的地方編寫如下代碼:
AudioServicesPlaySystemSound(1000);//新郵件消息提示
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); //震動
注:括号中為系統聲音的id,詳見請參考以下網址http://iphonedevwiki.net/index.php/AudioServices。
http://blog.csdn.net/tskyfree/article/details/8096500
http://www.cnblogs.com/martin1009/archive/2012/06/14/2549473.html
http://www.cnblogs.com/chen1987lei/archive/2012/02/07/2341535.html
40,重複調用2次loadView和viewDidLoad
最好不要在UIViewController的loadView方法中改變狀态欄的可視性(比如狀态欄由顯示變為隐藏、或者由隐藏變為顯示),因為會導緻重複調用2次loadView和viewDidLoad方法。
[cpp] view plain copy
- 錯誤代碼:
[cpp] view plain copy
- - (void)loadView {
- NSLog(@"loadView");
- // 隐藏狀态欄
- [UIApplication sharedApplication].statusBarHidden = YES;
- // .... 建立UIView
- self.view = [[[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds] autorelease];
- self.view.backgroundColor = [UIColor grayColor];
- }
- - (void)viewDidLoad {
- [super viewDidLoad];
- NSLog(@"viewDidLoad");
- }
列印資訊:
1 2013-05-14 00:51:36.152 test[2251:c07] loadView
2 2013-05-14 00:51:36.153 test[2251:c07] loadView
3 2013-05-14 00:51:36.153 test[2251:c07] viewDidLoad
4 2013-05-14 00:51:36.154 test[2251:c07] viewDidLoad
雖然運作效果是對的,但是系統連續調用了2次loadView和viewDidLoad方法,導緻建立了2次UIView,造成了不必要的開銷。
原因分析:
狀态欄由顯示變為隐藏,意味着螢幕的可用高度變長了,UIViewController的UIView的高度也要重新調整,是以系統會重新調用loadView方法建立UIView,建立完畢後再次調用viewDidLoad方法。
41,點選UIButton 無法産生觸摸事件
如果在UIImageView中添加了一個按鈕,你會發現在預設情況下這個按鈕是無法被點選的,需要設定UIImageView的userInteractionEnabled為YES:
imageView.userInteractionEnabled = YES;
設定為YES後,UIImageView内部的按鈕就可以被點選了
42,如何啟動app時全屏顯示Default.png(圖檔)?
大部分app在啟動過程中全屏顯示一張背景圖檔,比如新浪微網誌會顯示這張:
要想在iOS中實作這種效果,毫無壓力,非常地簡單,把需要全屏顯示的圖檔命名為Default.png即可,在iOS app啟動時預設會去加載并全屏顯示Default.png。
也可以用其他名稱來命名圖檔,在Info.plist配置一下即可:
配置過後,app啟動時就會去加載并全屏顯示lufy.png
在預設情況下,app顯示Default.png時并非真正的"全屏顯示",因為頂部的狀态欄并沒有被隐藏,比如下面的效果:
大部分情況下,我們都想隐藏狀态欄,讓Default.png真正全屏顯示。
說到這裡,可能有人馬上就想到了一種辦法:在AppDelegate的application:didFinishLaunchingWithOptions:方法中添加如下代碼:
[UIApplication sharedApplication].statusBarHidden = YES;
我隻能說你的思路是對的,但實際上達不到想要的效果,你會發現顯示Default.png時狀态欄還是存在的,等Default.png顯示完畢後,狀态欄才被隐藏。
我先解釋下為什麼這種方法不可行,其實原因很簡單:
1> Default.png是在app啟動過程中加載的,并不是在app啟動完畢後再加載的
2> AppDelegate的application:didFinishLaunchingWithOptions:方法是在app啟動完畢後才調用的
下面說一下解決方案,在Info.plist中增加一個配置即可:
這裡的YES表示在app初始化(啟動)的時候就隐藏狀态欄。
當然,在Default.png顯示完畢後狀态欄還是隐藏的。如果想重新顯示狀态欄,補上下面代碼即可:
[UIApplication sharedApplication].statusBarHidden = NO;
43,使用ASIHTTPRequest儲存cookies
假如我的APP,第一次啟動請求了登入接口并得到了Cookie,然後我把APP關了,下次啟動APP,我不請求登入接口了,那上次得到的Cookie就不存在了。如果需要,那麼2種方法,下次啟動app,自動登入,這樣能得到伺服器配置設定給你的cookier(這一種是最好的,因為session也會過期),還有一種是你把上次登入的時候,拿到的cookier存起來,然後下次啟動app的時候,手動給請求(ASIHTTP)添加cookie。
是以當第一次登入成功後,可以把cookie儲存到CoreData,SQLite,UserDefault等,等到下次網絡請求時,讀取:
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:UserInfoURL];
[request setRequestMethod:@"POST"];
[request addRequestHeader:@"Cookie" value:[NSString stringWithFormat:@"cookie=%@",[[NSUserDefaults standardUserDefaults] objectForKey:@"cookie"]]];//把cookie的值放進Header裡,這個cookie的值是一串很長的字元串。
44,UITextField隻有當有字元輸入後,鍵盤右下角的搜尋/傳回/done/等等鍵才可以使用
TextField設定這個屬性為YES就可以了,預設為NO
searchField.enablesReturnKeyAutomatically =YES;
45.類似QQ等IM軟體,長度和高度不一的聊天氣泡的圖檔是如何做的?拉伸?
其實是一個小氣泡png,然後拉伸中間部分,四個角不拉動,就是局部拉伸。ios自帶方法,四個角可以不拉伸的,如下:
46,UITableView中有多個UITextField時,被擋住的TextField如何實作自動向上彈起?
首先要實作TextField的delegate,在方法:
[cpp] view plain copy
- - (void)textFieldDidBeginEditing:(UITextField *)textField {
- [self.tableView setContentOffset:CGPointMake(0, 70) animated:YES];
- }
這說明當開始輸入時,tableview在原來的基礎上向上擡起70個距離。多個UITextFiled可以通過判斷來使用CGPoint的調整高度,我這寫的是70.
tableview的scrollEnabled屬性一定要是YES;要不然滾動不了了。
記得在return時複原tableview的位置:
[cpp] view plain copy
- - (BOOL)textFieldShouldReturn:(UITextField *)sender {
- [self.tableView setContentOffset:CGPointMake(0, 0) animated:YES];
- return YES;
- }
47,ios如何在調試時,輕松找到程式在哪裡崩潰?
我們給自己的工程添加一個通用的斷點:
一步步按上面圖完成操作。
再運作程式
自動就斷點到這裡來了,
log資訊是:
[cpp] view plain copy
- 2013-05-20 11:14:19.635 GestureRecognizer[1491:c07] -[__NSCFNumber isEqualToString:]: unrecognized selector sent to instance 0x7a88df0
- 2013-05-20 11:15:21.148 GestureRecognizer[1491:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber isEqualToString:]: unrecognized selector sent to instance 0x7a88df0'
這樣很簡單就能發現程式崩潰是因為value沒有 isEqualToString方法。 如果沒加上面這個通用的斷點,那程式會直接斷點到main函數去。
48,UIImageView 如何實作windows 桌面類似的背景桌面螢幕(很小的圖檔會顯示N多個)?
從UImageView上找ContentMode或clipToBounds是都不管用的,正确的辦法是,不用UImageView,使用UIView,然後設定backgroundColor屬性為我們的圖檔,這樣的話自動會以螢幕的方式顯示。
[cpp] view plain copy
- UIView *gridView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 195)];
- gridView.backgroundColor = [UIColor colorWithPatternImage:BUNDLE_IMAGE(@"blue_grid")];
- [self.view addSubview:gridView];
- [gridView release];
下圖所示:(原圖是一個6X6的方格)
49,UITableViewCell 的backgroundColor不起作用的問題?
在開發時,想要在tableview中的某一個Cell設定選中狀态,并且Cell的背景顔色是一個自定義顔色。
[cpp] view plain copy
- -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
- <span style="white-space:pre"> </span>//省略....
- cell.textLabel.font = [UIFont systemFontOfSize:6.0];
- cell.textLabel.text = @"13832207020";
- if (indexPath.row==0) {
- [cell setBackgroundColor:[UIColor colorWithRed:100.0f/255.0f green:176.0f/255.0f blue:0.0f/255.0f alpha:1.0f]];
- }
- else{
- [cell setBackgroundColor:[UIColor whiteColor]];
- }
- return cell;
- }
這樣的話,第1行cell就應該是我們設定好的顔色,不過請注意,此方法在UITableViewStylePlain的風格下有效, 在 UITableViewStyleGrouped的樣式下是無效的 !這個跟tableview的backgroundView和backgroundColor是沒有關系的,個人猜想應該是在Grouped風格下,cell選中的顔色有系統的view遮罩,導緻我們設定的無法顯示出來。
【補充】如果想在reload或init時設定tableview的某一cell為 selected狀态,千萬不要使用cell setSelected:YESanimated:YES,使用tableview的方法:
[cpp] view plain copy
- NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
- terminalTableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
50,UITableViewCell選中時contentView中各元件的高亮狀态
使用系統或簡單自定義的UITableViewCell時,當選中某一行Cell後,除了背景顔色改變外,Cell上所有的元件(資料)比如UILabel,UIbutton等都被自動顯示成了其
Highlighted(高亮)狀态下的效果,(如果想顯示出效果,你的那些自定義的元件必須要設定高亮狀态,比如highlightedTextColor,UIControlStateHighlighted等),是以這一點需要特别注意,如果不想要系統的這個自動特效,有兩個解決辦法:
1,元件不設定highlighted下的屬性
2,如果自定義的Cell:
[cpp] view plain copy
- - (void)setSelected:(BOOL)selected animated:(BOOL)animated
- {
- [super setSelected:selected animated:animated];
- if (selected) {
- //強制系統在UITableViewCell選中時SettingButton元件的高亮狀态為NO
- [(UIButton *)[self.contentView.subviews objectAtIndex:1] setHighlighted:NO];
- [settingBtn setImage:BUNDLE_IMAGE(@"accessory_sel") forState:UIControlStateNormal];
- }
- else{
- [settingBtn setImage:BUNDLE_IMAGE(@"accessory_nor") forState:UIControlStateNormal];
- }
- }
51,IOS atomic與nonatomic,assign,copy與retain的定義和差別
atomic和nonatomic用來決定編譯器生成的getter和setter是否為原子操作。
atomic
設定成員變量的@property屬性時,預設為atomic,提供多線程安全。
在多線程環境下,原子操作是必要的,否則有可能引起錯誤的結果。加了atomic,setter函數會變成下面這樣:
{lock}
if (property != newValue) {
[property release];
property = [newValue retain];
}
{unlock}
nonatomic
禁止多線程,變量保護,提高性能。
atomic是Objc使用的一種線程保護技術,基本上來講,是防止在寫未完成的時候被另外一個線程讀取,造成資料錯誤。而這種機制是耗費系統資源的,是以在iPhone這種小型裝置上,如果沒有使用多線程間的通訊程式設計,那麼nonatomic是一個非常好的選擇。
指出通路器不是原子操作,而預設地,通路器是原子操作。這也就是說,在多線程環境下,解析的通路器提供一個對屬性的安全通路,從擷取器得到的傳回值或者通過設定器設定的值可以一次完成,即便是别的線程也正在對其進行通路。如果你不指定 nonatomic ,在自己管理記憶體的環境中,解析的通路器保留并自動釋放傳回的值,如果指定了 nonatomic ,那麼通路器隻是簡單地傳回這個值。
assign
對基礎資料類型 (NSInteger,CGFloat)和C資料類型(int, float, double, char)等等。
此标記說明設定器直接進行指派,這也是預設值。在使用垃圾收集的應用程式中,如果你要一個屬性使用assign,且這個類符合NSCopying協 議,你就要明确指出這個标記,而不是簡單地使用預設值,否則的話,你将得到一個編譯警告。這再次向編譯器說明你确實需要指派,即使它是 可拷貝的。
retain
對其他NSObject和其子類對參數進行release舊值,再retain新值
指定retain會在指派時喚醒傳入值的retain消息。此屬性隻能用于Objective-C對象類型,而不能用于Core Foundation對象。(原因很明顯,retain會增加對象的引用計數,而基本資料類型或者Core Foundation對象都沒有引用計數——譯者注)。
注意: 把對象添加到數組中時,引用計數将增加對象的引用次數+1。
copy
對NSString 它指出,在指派時使用傳入值的一份拷貝。拷貝工作由copy方法執行,此屬性隻對那些實行了NSCopying協定的對象類型有效。更深入的讨論,請參考“複制”部分。
copy與retain:
Copy其實是建立了一個相同的對象,而retain不是:
1.比如一個NSString 對象,位址為0×1111 ,内容為@”STR”,Copy 到另外一個NSString 之後,位址為0×2222 ,内容相同。
2.新的對象retain為1 ,舊有對象沒有變化retain 到另外一個NSString 之後,位址相同(建立一個指針,指針拷貝),内容當然相同,這個對象的retain值+1。
總結:retain 是指針拷貝,copy 是内容拷貝。
assign與retain:
1. 接觸過C,那麼假設你用malloc配置設定了一塊記憶體,并且把它的位址指派給了指針a,後來你希望指針b也共享這塊記憶體,于是你又把a指派給(assign)了b。此時a和b指向同一塊記憶體,請問當a不再需要這塊記憶體,能否直接釋放它?答案是否定的,因為a并不知道b是否還在使用這塊記憶體,如果a釋放了,那麼b在使用這塊記憶體的時候會引起程式crash掉。
2. 了解到1中assign的問題,那麼如何解決?最簡單的一個方法就是使用引用計數(reference counting),還是上面的那個例子,我們給那塊記憶體設一個引用計數,當記憶體被配置設定并且指派給a時,引用計數是1。當把a指派給b時引用計數增加到2。這時如果a不再使用這塊記憶體,它隻需要把引用計數減1,表明自己不再擁有這塊記憶體。b不再使用這塊記憶體時也把引用計數減1。當引用計數變為0的時候,代表該記憶體不再被任何指針所引用,系統可以把它直接釋放掉。
總結:上面兩點其實就是assign和retain的差別,assign就是直接指派,進而可能引起1中的問題,當資料為int, float等原生類型時,可以使用assign。retain就如2中所述,使用了引用計數,retain引起引用計數加1, release引起引用計數減1,當引用計數為0時,dealloc函數被調用,記憶體被回收。
52,#pragma mark -#pragma mark Initialization含義
它們告訴Xcode編譯器,要在編輯器窗格頂部的方法和函數彈出菜單中将代碼分隔開;注意 #pragma mark – 的“-”後面不能有空格。如果你的标志沒有出現在彈出菜單中,比如沒有分隔線出現,請在Xcode菜單 “Preferences..”中的 “Code Sense”選項取消選中”Sort listalphabetically”即可。
53,自定義delegate變量聲明時使用assign還是retain?
我們通過發送消息給對象出發特定動作;對象發送某些變化的時候通過回調函數(callback)通知我們。對象在特定事件發生的時候,就會調用對應的回調函數,觸發業務邏輯。回調函數通過所謂的代理(Delegation)來實作.
delegate使用方法:
@property (assign) <id>xxxDelegate delegate;
正确的使用方法是使用assign屬性而不是retain。之是以對于delegate這類對象使用assign而不是用retain是為了防止循環retain(retain loop)
54,給成員變量(屬性)指派時使不使用self?
使用@property和@synthesize聲明一個成員變量,給其指派是時要在前面加上"self.",以便調用成員變量的setmember方法。直接調用成員變量并且給其指派:member=[NSString stringWithFormat:@””];将不執行setmember 方法。
使用self調用成員變量并且給其指派:self.member=[NSString stringWithFormat:@””];将執行setmember方法。
55,如何給UIbutton 同時設定圖檔(Image)和文字(Title)以及它們的各種狀态?
[cpp] view plain copy
- startRangeButton = [UIButton buttonWithType:UIButtonTypeCustom];
- startRangeButton.frame = CGRectMake(85,componentOriginY, regionImage.size.width, 16);
- [startRangeButton setBackgroundImage:regionImage forState:UIControlStateNormal];
- //還可以設定其高亮狀态startRangeButton setBackgroundImage:regionImage forState:UIControlStateHighlighted];
- startRangeButton.titleLabel.font = [UIFont systemFontOfSize:7.0];
- [startRangeButton setTitle:@"2013-08-01 07:00" forState:UIControlStateNormal];
- [startRangeButton setTitleColor:COLOR(101, 199, 240, 1) forState:UIControlStateNormal];
- [startRangeButton setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted];
代碼中我設定button背景圖檔為自己定義的一個regionImage,并設定了button的title = “2013-08-01 07:00” 【注意,設定了背景圖檔後,title隻能這樣添加,以button.titleLabel.text方式添加會無法顯示的】 ,并且設定了tiitle正常和高亮下文字顔色。
是以看到這裡,應該明白button.setBackgroundImage 和 set Image 的差別了吧,前者是可以同時設定文字,後者是一旦設定了image,無法再顯示文字。
普通:
高亮:
56,如何将NSDate類型轉化為距離1970/1/1的毫秒差?
[formatter setDateFormat:@"yyyy-MM-dd HH:mm"]; 這種格式得到的數值是精确到秒的,也就是說少1000,
但是嘗試[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];或SS大寫,或[formattersetDateFormat:@"yyyy-MM-dd HH:mm.ss.SSS"];都不起作用,最後才發現,原來是這樣
NSTimeInterval本身是個秒級别的double類型數值,小數點後面即毫秒數,*1000.0f即可得到毫秒級别的時間差
//為了相容java版本,事件是從1970/1/1開始
-(NSDate *)getDateTimeFromMilliSeconds:(long long) miliSeconds
{
NSTimeInterval tempMilli = miliSeconds;
NSTimeInterval seconds = tempMilli/1000.0;
NSLog(@"seconds=%f",seconds);
return [NSDate dateWithTimeIntervalSince1970:seconds];
}
//将NSDate類型的時間轉換為NSInteger類型,從1970/1/1開始
-(long long)getDateTimeTOMilliSeconds:(NSDate *)datetime
{
NSTimeInterval interval = [datetime timeIntervalSince1970];
NSLog(@"interval=%f",interval);
long long totalMilliseconds = interval*1000 ;
NSLog(@"totalMilliseconds=%llu",totalMilliseconds);
return totalMilliseconds;
}
也就是說,計算結果再自己乘以1000就可以了
[cpp] view plain copy
- NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
- [formatter setDateFormat:@"yyyy-MM-dd HH:mm"];
- NSDate *sDate = [formatter dateFromString:startRangeButton.titleLabel.text];
- NSDate *eDate = [formatter dateFromString:endRangeButton.titleLabel.text];
- NSTimeInterval sinterval = [sDate timeIntervalSince1970];
- long long start = sinterval*1000;
- NSTimeInterval einterval = [eDate timeIntervalSince1970];
- long long end = einterval*1000;
- [mConnectionHelper doTrack:mobile startTime:start endTime:end];
57,ios中的全局靜态變量
Objective-C 支援全局變量
主要有兩種實作方式:
(1)第一種和C/C++中的一樣, 使用"extern"關鍵詞;
(2)另外一種就是使用單例實作。
(比如我們經常會把一個變量放在AppDelegate裡面作為全局變量來通路, 其中AppDelegate就是一個單例類)
在Objective-C中如何實作像C++中那樣的靜态成員變量呢?
你需要做的是在一個類A的implementation(.m或者.mm)檔案中定義一個static變量,然後為A類定義靜态成員函數(class method,也就是類方法)來操作該變量。
這樣在其它類中你就不需要建立A類的執行個體來對static變量進行通路。雖然該static變量并不是A類的靜态成員變量,但是也算達到了同樣的效果。static變量的作用域被限制在單一的檔案中。
[cpp] view plain copy
- //example.h
- @interface Example : NSObject {
- }
- - (id)init;
- +(int)instanceCount;
- @end
[cpp] view plain copy
- //example.m
- #import "example.h"
- static int count;
- @implementation Example
- -(id)init{
- self = [super init];
- if(nil!=self){
- count+=1;
- }
- return self;
- }
- +(int)instanceCount{
- return count;
- }
- @end
上面的例子中你就可以通過[Example instanceCount]對靜态變量count進行通路,無須建立執行個體。
警告: static 寫在interface外面編譯是沒有錯誤的,但是編譯器會報警告,這麼說這樣的寫法是不被編輯器認可的。
錯誤:static 寫在interface裡面會直接報錯,顯然這樣的文法是不被認可的。
static關鍵字聲明的變量必須放在implementation外面,或者方法中,如果不為它指派預設為0,
它隻在程式開機初始化一次。
58,如何使用 NSNotificationCenter 在viewcontroller之間進行傳值?
簡單點的來,兩個界面間傳值,直接上代碼了:
sendViewcontroller.m
[cpp] view plain copy
- //SettingViewController :接受值的viewcontroller
- SettingViewController *setting = [[SettingViewController alloc] init];
- [[NSNotificationCenter defaultCenter] addObserver:setting selector:@selector(received:) name:@"msetting" object:nil];
- NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:@"user",@"type", nil];
- [[NSNotificationCenter defaultCenter] postNotificationName:@"msetting" object:dict];
- [self.navigationController pushViewController:setting animated:YES];
- [setting release];
SettingViewController.m(接收值的viewcontroller)
[cpp] view plain copy
- -(void)received:(NSNotification *)notification{
- id data = [notification object];
- NSLog(@"received data: %@",data);
- }
這樣就實作了基本的使用,跟delegate類似,注意 addObserver時,需要寫目标viewcontroller的執行個體,而不是self。
59,Thread EXC_BAD_ACCESS : objc_retain, objc_getProperty 崩潰錯誤
如上圖所示,遇到這個錯誤,從字面的意思我們大緻能猜到,是有屬性已經被release掉了,但是我們又使用它了,是以,一部一部排查把,一定有某個地方的屬性提前被release掉了,自己手動管理記憶體就會有這樣的困惱,代碼很多,不想去找,一定要有耐心,找的過程還可以學到很多知識。
如上圖,這個就是我找到的原因所在,unarchiver release掉了,而我們在其它的類中想使用location的屬性。