1,Search Bar 怎樣去掉背景的顏色(storyboard裏只能設置background顏色,可是發現clear Color無法使用)
其實在代碼裏還是可以設置的,那就是刪除背景view
[[self.searchBar.subviews objectAtIndex:0] removeFromSuperview];
2,NSDate使用
字母 日期或時間元素 表示 示例
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”,這樣會出錯的。
舉例:
//創建一個時間對象
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 未實例化
如果使用 UTTabviewCell,設置其accessory樣式爲:Detail Disclosure ,就是在每一個cell右邊設置一個detail button。如果這樣的操作是使用storyboard,進行的,它會要求你給每一個你cell設置indentifier,然後你會在以下方法內設置重用indentfier,別忘記加上一句話,否則編譯運行時可能會彈出: cell未實例化
4,StoryBoard中segue的使用
在開發項目中,有時有這樣的需求:運行程序,登陸界面是一個自由的ViewController,只是擺放幾個TextField和button,點擊後跳轉到其它選擇界面,點擊選項後進入我們的主界面:這個時候,在登陸界面作跳轉時,會有好多的方法,如果使用storyboard,就比較方便了,設置一個segue,跳轉代碼中
[self PerformSegueWithIdentifier:@"targetViewController",self]; 就可以了,可是我想實例化想要跳轉的控制器,然後設置某一屬性的值,這樣跳轉後控制器獲取那個屬性,就會得到值了,可是這樣做會有一個問題:
主界面控制器如果使用了navigatorViewController,並且是其RootViewController,等到在主界面設置功能,點擊某一功能,想push到一個新頁面時,問題就來了,你會發現毫無反應,沒有報錯,只是segue無法跳轉。後來終於找到原因:就是我在登陸控制器跳轉時沒有使用segue的方法,而是用代碼self.storyboard,加載一個新類,具體原理目前還沒有搞明白,先把出問題的代碼記錄下來,回頭補之:
代碼這樣做,會導致其後無法使用navigatorViewController做push跳轉
5,nil和Nil和NULL的判斷
開發過程中,我們通過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使用正則表達式
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的缺省公司名
// testAppDelegate.m
// test
//
// Created by gaohf on 11-5-24.
// Copyright 2011 __MyCompanyName__. All rights reserved.
在終端中執行以下命令:
defaults write com.apple.Xcode PBXCustomTemplateMacroDefinitions '{"ORGANIZATIONNAME" = "COMPANY";}'
//
// testAppDelegate.m
// test
//
// Created by gaohf on 11-5-24.
// Copyright 2011 COMPANY. All rights reserved.
//
12,在有uinavigation,uitoolbar的情況下,如何添加一個全屏的 uiview (作爲顯示一個進度框,任何區域無法觸摸而使用)
只需要在要添加view時侯這樣寫:
[[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 設置背景顏色或是自定義圖片
在項目中添加如下代碼:
//設置背景顏色:
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;
//設置自定義的圖片:
[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中才有,所以,要想設置背景圖片,只能在代碼中設置,如下:
[leftNaviView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"pabb_leftnaviview_bg.png"]]];
這樣,背景就可以變成想要的圖片了。另外,設置大小:
[leftNaviView setFrame:CGRectMake(9, 60, 120, 250)];
16,如何在項目用代碼打開AppStore
//以下是通過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,如何代碼實現跳轉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
調用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名稱
應用程序的名稱和版本號等信息都保存在mainBundle的infoDictionary字典中,用下面代碼可以取出來。
NSDictionary* infoDict =[[NSBundle mainBundle] infoDictionary];
NSString* versionNum =[infoDict objectForKey:@"CFBundleVersion"];//版本名稱
NSString*appName =[infoDict objectForKey:@"CFBundleDisplayName"];//app名稱
<p style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; font-family: Menlo;"><span style="color: #703daa">NSString</span> * versionShortString = [infoDict <span style="color: rgb(61, 29, 129);">objectForKey</span>:<span style="color: #d12f1b">@"CFBundleShortVersionString"</span>];//標識應用程序發佈版本號</p>NSString*text =[NSString stringWithFormat:@"%@ %@",appName,versionNum,<span style="font-family: Menlo; font-size: 11px; white-space: pre; background-color: rgb(240, 240, 240);">versionShortString</span>];
此version 爲工程info下的Bundle version字段值:value可以隨意定義。
CFBundleVersion,標識(發佈或未發佈)的內部版本號。這是一個單調增加的字符串,包括一個或多個時期分隔的整數。
CFBundleShortVersionString 標識應用程序的發佈版本號。該版本的版本號是三個時期分隔的整數組成的字符串。第一個整數代表重大修改的版本,如實現新的功能或重大變化的修訂。第二個整數表示的修訂,實現較突出的特點。第三個整數代表維護版本。該鍵的值不同於“CFBundleVersion”標識。 圖片裏的 Version 對應的就是CFBundleShortVersionString (發佈版本號 如當前上架版本爲1.1.0 之後你更新的時候可以改爲1.1.1)
Build 對應的是 CFBundleVersion(內部標示,用以記錄開發版本的,每次更新的時候都需要比上一次高 如:當前版本是11 下一次就要大於11 比如 12,13 ....10000)
21,如何使屏幕一直保持喚醒狀態?(就是不自動黑屏)
比如,如果我們做一個播放視頻的功能時,想在播放的時候,不會自動進入屏保(黑屏)
只要在代碼里加入這一行:
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
當然,在想要黑屏的時候還需要把它設置爲NO(比如視頻播放完畢時),不然屏幕會在此軟件運行下一直亮着。
22,在Xcode中,文件名後小方框中的A(M或C)表示什麼意思啊?
表示在版本控制中,自上一次提交以來,文件做了修改。貌似只有在帶有版本控制的項目代碼中才會顯示,也就是說你的項目使用了SVN、GIT等工具後,會在Xcode中識別出來。
'A' 新增
'D' 刪除
'M' 修改
'R' 替代
'C' 衝突
'I' 忽略
'?' 未受控
'!' 丟失,一般是將受控文件直接刪除導致
23,有關ios5上屏幕旋轉,view設置Frame的相關問題
屏幕旋轉一共有4個相關屬性(旋轉方向):
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
UIInterfaceOrientationPortrait
UIInterfaceOrientationPortraitUpsideDown
前兩個是橫屏時的狀態,後兩個是正常狀態(Portrait)和上下顛倒(UpsideDown)時的狀態。
【注意:Left和Right兩個左右模擬器旋轉時移動的方向正好是相反的,但移動後Home的方向,就如下圖所示】
具體見下圖:
其中涉及到兩個方法,在ViewController中默認會實現這個方法:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
//除了不允許旋轉屏幕後:上下顛倒,其餘方向都運行旋轉
//如果想都運行,可以直接返回YES,或都不允許NO
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
這個方法是聲明此ViewController所運行屏幕旋轉的方向,一共4種類型,全部允許返回YES,上圖所示除了不允許上下顛倒,其餘都可以。【注意,項目設置Supported Device Orientations 所支持的屏幕旋轉類型並不影響此方法的設置,也就是說,哪怕Support只支持Portrait,方法裏設置UpsideDown,此ViewController也會實現上下顛倒旋轉的】
第二個方法,是我們比較常用的,也就是在設備即將以某個方向旋轉之前,我們在其狀態(方向)設置組件或view的Frame,bound,等需要改變的屬性時所用到的方法。
-(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:方法;
-(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
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 高清:Default-Portrait@2x~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];
其實現在剛明白,一個很簡單的方法:
NSArray *viewControllers=[self.navigationController viewControllers];
UIViewController *controller=[viewControllers objectAtIndex:1];
想起來navigation的機制了吧,每當我們push到一個viewcontroller時,就會把這個viewcontroller的實例保存到nsarray裏,通過array可以獲取到任何一個viewcontroller,這不就解決問題了麼?
[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方法中加入以下代碼:
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,圖片模糊化處理
+(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對象有些新的使用方法,可以讓字符串轉變成全部大寫,全部小寫,或者每個單詞首字母大寫。
代碼如下所示:
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 參考
37,真機調試:could not change executable permissions錯誤?
雖然更改了新demo的bundle identifier和之前的identifier一樣,但是真機上還保留着之前調試時的demo,所以新的工程如果使用同樣的identifier真機調試,需要先把機器上原來的demo刪除,再使用新工程調試。
38,判斷iphone5屏幕的宏定義
#define iPhone5 ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(640, 1136), [[UIScreen mainScreen] currentMode].size) : NO)
在需要判斷屏幕尺寸的地方:
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
39,invalid deployment target for -stdlib=libc++ (requires iOS 5.0 or later)錯誤
選中項目--target---build settings 找到C++Standard Library 改成:Compiler Default,再編譯就不會有錯誤了.
40,如何調用系統聲音?【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
41,重複調用2次loadView和viewDidLoad
最好不要在UIViewController的loadView方法中改變狀態欄的可視性(比如狀態欄由顯示變爲隱藏、或者由隱藏變爲顯示),因爲會導致重複調用2次loadView和viewDidLoad方法。
錯誤代碼:
- (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方法。
42,點擊UIButton 無法產生觸摸事件
如果在UIImageView中添加了一個按鈕,你會發現在默認情況下這個按鈕是無法被點擊的,需要設置UIImageView的userInteractionEnabled爲YES:
imageView.userInteractionEnabled = YES;
設置爲YES後,UIImageView內部的按鈕就可以被點擊了
43,如何啓動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;
44,使用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的值是一串很長的字符串。
45,UITextField只有當有字符輸入後,鍵盤右下角的搜索/返回/done/等等鍵纔可以使用
TextField設置這個屬性爲YES就可以了,默認爲NO
searchField.enablesReturnKeyAutomatically =YES;
46,類似QQ等IM軟件,長度和高度不一的聊天氣泡的圖片是如何做的?拉伸?
其實是一個小氣泡png,然後拉伸中間部分,四個角不拉動,就是局部拉伸。ios自帶方法,四個角可以不拉伸的,如下:
47,UITableView中有多個UITextField時,被擋住的TextField如何實現自動向上彈起?
首先要實現TextField的delegate,在方法:
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[self.tableView setContentOffset:CGPointMake(0, 70) animated:YES];
}
這說明當開始輸入時,tableview在原來的基礎上向上擡起70個距離。多個UITextFiled可以通過判斷來使用CGPoint的調整高度,我這寫的是70.
tableview的scrollEnabled屬性一定要是YES;要不然滾動不了了。記得在return時復原tableview的位置:
- (BOOL)textFieldShouldReturn:(UITextField *)sender {
[self.tableView setContentOffset:CGPointMake(0, 0) animated:YES];
return YES;
}
48,ios如何在調試時,輕鬆找到程序在哪裏崩潰?
我們給自己的工程添加一個通用的斷點:
一步步按上面圖完成操作。
再運行程序
自動就斷點到這裏來了,
log信息是:
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函數去。49,UIImageView 如何實現windows 桌面類似的背景壁紙屏幕(很小的圖片會顯示N多個)?
從UImageView上找ContentMode或clipToBounds是都不管用的,正確的辦法是,不用UImageView,使用UIView,然後設置backgroundColor屬性爲我們的圖片,這樣的話自動會以屏幕的方式顯示。
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的方格)
50,UITableViewCell 的backgroundColor不起作用的問題?
在開發時,想要在tableview中的某一個Cell設置選中狀態,並且Cell的背景顏色是一個自定義顏色。
-(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:YES animated:YES,使用tableview的方法:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
[terminalTableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
51,UITableViewCell選中時contentView中各組件的高亮狀態
使用系統或簡單自定義的UITableViewCell時,當選中某一行Cell後,除了背景顏色改變外,Cell上所有的組件(數據)比如UILabel,UIbutton等都被自動顯示成了其
Highlighted(高亮)狀態下的效果,(如果想顯示出效果,你的那些自定義的組件必須要設置高亮狀態,比如highlightedTextColor,UIControlStateHighlighted等),所以這一點需要特別注意,如果不想要系統的這個自動特效,有兩個解決辦法:
1,組件不設置highlighted下的屬性
2,如果自定義的Cell:
- (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];
}
}
52,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函數被調用,內存被回收。
53,#pragma mark -#pragma mark Initialization含義
它們告訴Xcode編譯器,要在編輯器窗格頂部的方法和函數彈出菜單中將代碼分隔開;注意 #pragma mark – 的“-”後面不能有空格。如果你的標誌沒有出現在彈出菜單中,比如沒有分隔線出現,請在Xcode菜單 “Preferences..”中的 “Code Sense”選項取消選中”Sort listalphabetically”即可。
54,自定義delegate變量聲明時使用assign還是retain?
我們通過發送消息給對象出發特定動作;對象發送某些變化的時候通過回調函數(callback)通知我們。對象在特定事件發生的時候,就會調用對應的回調函數,觸發業務邏輯。回調函數通過所謂的代理(Delegation)來實現.
delegate使用方法:
@property (assign) <id>xxxDelegate delegate;
正確的使用方法是使用assign屬性而不是retain。之所以對於delegate這類對象使用assign而不是用retain是爲了防止循環retain(retain loop)
55,給成員變量(屬性)賦值時使不使用self?
使用@property和@synthesize聲明一個成員變量,給其賦值是時要在前面加上"self.",以便調用成員變量的setmember方法。直接調用成員變量並且給其賦值:member=[NSString stringWithFormat:@””];將不執行setmember 方法。
使用self調用成員變量並且給其賦值:self.member=[NSString stringWithFormat:@””];將執行setmember方法。
56,如何給UIbutton 同時設置圖片(Image)和文字(Title)以及它們的各種狀態?
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,無法再顯示文字。
普通:高亮:
57,如何將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就可以了
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];
58,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變量的作用域被限制在單一的文件中。
//example.h
@interface Example : NSObject {
}
- (id)init;
+(int)instanceCount;
@end
//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,
它只在程序開機初始化一次。
59,如何使用 NSNotificationCenter 在viewcontroller之間進行傳值?
簡單點的來,兩個界面間傳值,直接上代碼了:
sendViewcontroller.m
//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)
-(void)received:(NSNotification *)notification{
id data = [notification object];
NSLog(@"received data: %@",data);
}
這樣就實現了基本的使用,跟delegate類似,注意 addObserver時,需要寫目標viewcontroller的實例,而不是self。
60,Thread EXC_BAD_ACCESS : objc_retain, objc_getProperty 崩潰錯誤
如上圖所示,遇到這個錯誤,從字面的意思我們大致能猜到,是有屬性已經被release掉了,但是我們又使用它了,所以,一部一部排查把,一定有某個地方的屬性提前被release掉了,自己手動管理內存就會有這樣的困惱,代碼很多,不想去找,一定要有耐心,找的過程還可以學到很多知識。
如上圖,這個就是我找到的原因所在,unarchiver release掉了,而我們在其它的類中想使用location的屬性。
61,MAC 終端(bash)svn命令不識別 command not found
在mac os 10.8中,svn Command line tools是沒有自動安裝的,這樣的話,svn 命令行就會失效,解決辦法:
1.打開xcode偏好設置(comand+,)-->"Download" -->Components:
2.點擊“Command line tools”下載,下載完成之後安裝。
3.安裝完成之後,打開終端,輸入“svn help”,如果出現如下所示,說明命令行工具安裝好了。
62,ios MapKit 判斷座標是否在MapView顯示範圍內
CLLocationDegrees leftDegrees = mapView.region.center.longitude –(mapView.region.span.longitudeDelta / 2.0);
CLLocationDegrees rightDegrees = mapView.region.center.longitude +(mapView.region.span.longitudeDelta / 2.0);
CLLocationDegrees bottomDegrees = mapView.region.center.latitude –(mapView.region.span.latitudeDelta / 2.0);
CLLocationDegrees topDegrees = self.region.center.latitude +(mapView.region.span.latitudeDelta / 2.0);
if (leftDegrees > rightDegrees) { // Int'l Date Line in View
leftDegrees = -180.0 - leftDegrees;
if (coords.longitude > 0) // coords to West of Date Line
coords.longitude = -180.0 - coords.longitude;
}
If (leftDegrees <= coords.longitude && coords.longitude <= rightDegrees && bottomDegrees <= coords.latitude && coords.latitude <= topDegrees) {
// 座標在範圍內
}
63,簡單的冒泡排序法
-(void) doDesc{
int list[12] = {12,42,21,45,6,13,89,23,48,74,3,32};
for (int i=0; i<=11; i++) {
for (int j=11; j>i; j--) {
//從大到小
// if (list[j]>list[j-1]) {
// int temp =list[j];
// list[j] = list[j-1];
// list[j-1] = temp;
//
// }
//從小到大
if (list[j]<list[j-1]) {
int temp = list[j-1];
list[j-1] = list[j];
list[j] = temp;
}
}
}
for (int k =0 ; k<12; k++) {
NSLog(@"%d == %d",k,list[k]);
}
}