- 判斷日期是不是同一天,不要求是小時、分鍾要一樣。from:http://www.oliverfoggin.com/nsdate-isequaltodatetounitgranularity/?utm_source=iOS+Dev+Weekly&utm_campaign=iOS_Dev_Weekly_Issue_115&utm_medium=email
#import <Foundation/Foundation.h>
@interface NSCalendar (equalWithGranularity)
- (BOOL)isDate:(NSDate *)date1 equalToDate:(NSDate *)date2 withGranularity:(NSCalendarUnit)granularity;
@end
#import "NSCalendar+equalWithGranularity.h"
@implementation NSCalendar (equalWithGranularity)
- (BOOL)isDate:(NSDate *)date1 equalToDate:(NSDate *)date2 withGranularity:(NSCalendarUnit)granularity {
if ([date1 isEqualToDate:date2]) {
return YES;
}
int componentFlags = [self componentFlagsWithGranularity:granularity];
date1 = [self dateFromDate:date1 withComponentFlags:componentFlags];
date2 = [self dateFromDate:date2 withComponentFlags:componentFlags];
return [date1 isEqualToDate:date2];
}
- (int)componentFlagsWithGranularity:(NSCalendarUnit)granularity
{
int componentFlags = 0;
for (int i = 1<<1 ; i <= granularity ; i = i<<1) {
componentFlags = componentFlags | i;
}
return componentFlags;
}
- (NSDate *)dateFromDate:(NSDate *)date withComponentFlags:(int)componentFlags {
NSDateComponents *components = [self components:componentFlags fromDate:date];
return [self dateFromComponents:components];
}
@end
- CGRect rect = { CGPointZero, image.size };
- 光照效果+雜色效果
雜色圖片附件
- 使用解固XIB文件得到的視圖,初始化方法為initWithCoder:;使用代碼創建的視圖,初始化方法為initWithFrame:。
- Podfile文件配置
- 圖片的灰度處理 from:http://bj007.blog.51cto.com/1701577/541525
- 自定義模態跳轉動畫
- 當某一線程上正在運行一個任務,接着在沒有取消該線程的情況下,又啟動了一個執行同樣操作任務的線程。當最初的線程執行完任務后,執行清理工作,並將清理工作的運行環境關閉。而新開的線程上的操作執行完以后也執行一次清理工作,但此時執行清理的運行環境已經被關閉,致使app奔潰。所以在開啟一個同樣操作的新線程的時,要取消之前的線程。這在不斷點擊同一個事件觸發按鈕時尤為明顯。
當使用NSOperation類進行網絡請求(AFNetworking的網絡請求對象就是基於NSOperation),如果用戶離開某個請求還沒有完成的界面,除了將NSOpeation取消,還需要在NSOpeation塊內時刻監測NSOpeation類的isCancelled屬性的變化。當塊內的某個操作比較耗時,即使你取消了操作,但可能此時NSOperation已經獲取到了結果,只是在處理得到的結果,因為取消並不能讓NSOpeation塊內的代碼停下來。所以對於耗時的操作,在操作前要檢測NSOpeation是否被取消。
當使用MBProgressHUD,對hud設置當前頁面的控制器為hud代理。記住:當退出當前控制器視圖時,要將hud的代理置為nil,防止出現使用hide:afterDelay:方法后,hud延遲隱藏之后回調已經被釋放的代理,而致使ap奔潰。
- 利用Core Graphics為圖片添加內陰影 from:http://stackoverflow.com/questions/4431292/inner-shadow-effect-on-uiview-layer
代碼運行截圖:
- 內陰影+外陰影+邊框效果
- CGRectInset與CGRectOffset的區別
CGRect CGRectInset (
CGRect rect,
CGFloat dx,
CGFloat dy
);
該結構體的應用是以原rect為中心,再參考dx,dy,進行縮放或者放大。dx,dy為正數縮小,負數則放大。如果縮放后的結果矩形的寬或高存在負值,則返回空矩形。
CGRect CGRectOffset(
CGRect rect,
CGFloat dx,
CGFloat dy
);
相對於源矩形原點rect(左上角的點)沿x軸和y軸偏移
- Quartz常用曲線路徑的相關函數:from:http://blog.shoguniphicus.com/2011/05/19/keyframe-animation-ios-cakeyframeanimation-objective-c/
曲線的理論基礎是貝塞爾曲線,曲線的定義有四個點:起始點、終止點(也稱錨點)以及兩個相互分離的中間點。滑動兩個中間點,貝塞爾曲線的形狀會發生變化。
<1> 關於CGPathAddQuadCurveToPoint(path, NULL, cx, cy, x, y)。cx、cy為控制點的xy坐標,x、y為結束點。該函數只有一個控制點,當控制點的x坐標處在開始點和結束點的中間,則該條曲線關於中心點y軸對稱。
CGPathAddQuadCurveToPoint函數原理圖
示例代碼1:
代碼1運行截圖
<2>關於CGPathAddCurveToPoint(path, NULL, cx1, cy1, cx2, cy2, x, y);cx1、cy1為控制點1點xy坐標,cx2、cy2為控制點2的xy坐標。x、y為結束點。
CGPathAddCurveToPoint函數原理圖
示例代碼2:
代碼2運行截圖
<3>關於void CGPathAddArcToPoint (CGMutablePathRef path,const CGAffineTransform *m, CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2, CGFloat radius)。
該函數想可變的圖形路徑中追加一條弧線,可能弧線的前面是一條直線。該函數使用了一個三次貝塞爾曲線序列以創建一個弧線。當前點到(x1,y1)的直線以及(x1,y1)到(x2,y2)直線與弧線相切。弧線的開始點和結束點被分別定位在第一條與第二條切線上。弧線的開始點和結束點也被成為線段的切點。如果當前的點和第一個弧線的切點不相等,quartz就追加一條從當前點到第一個弧線切點的直線段。弧線的結束點變成了新路徑的當前點。在路徑中繪制弧線的另外方式,可見CGPathAddArc參數。
CGPathAddArcToPoint函數原理圖
示例代碼3:
代碼3運行截圖
<4>關於void CGPathAddArc ( CGMutablePathRef path,const CGAffineTransform *m, CGFloat x, CGFloat y, CGFloat radius, CGFloat startAngle, CGFloat endAngle, bool clockwise)。x和y表示圓心的xy坐標。radius表示半徑。startAngle和endAngle表示開始和結束角度。clockwise如果為YES,表示從開始角度到結束角度之間的弧線以順時針方向,也即為從左到右,從上到下。如果為NO表示從左到右,從下到上。如原理圖所示。具體關於該函數的數學原理,請參見:http://blog.csdn.net/zhanglei5415/article/details/8147833 中”創建弧線-數學問題“一節。
CGPathAddArc函數參數表征的具體元素
CGPathAddArc函數原理圖
示例代碼4:
代碼4運行截圖
- 繪制帶有陰影的圓
- 不規則陰影代碼:
from:http://nachbaur.com/blog/fun-shadow-effects-using-custom-calayer-shadowpaths
代碼運行截圖:
不規則陰影路徑的繪制主要使用shadowPath屬性,使用陰影路徑可以大幅提升陰影繪制的性能。 陰影路徑告訴UIKit將路徑內的區域設置為不透明,這減少了渲染引擎的大部分工作。
- CABasicAnimation中animationKeyPath的屬性值。
from:http://www.cnblogs.com/pengyingh/articles/2379631.html
CABasicAnimation 為圖層屬性提供了基本的單關鍵幀動畫功能。創建CABasicAnimation實例的一般方法是通過繼承的類方法animationWithKeyPath:,並給出在渲染樹中生成的動畫的關鍵路徑屬性。
可以通過animationWithKeyPath鍵值對的方式來改變動畫。animationWithKeyPath的值包括針對一般屬性變化和幾何變化兩類。幾何變換包括平移、旋轉、縮放。
如下表所示為幾何變換keypath:
另:CAAnimation的delegate方法:
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
NSLog(@"animation stop");
}
- (void)animationDidStart:(CAAnimation *)theAnimation {
NSLog(@"animation start");
}
一般的屬性變化包括以下幾個keypath屬性:
margin zPosition backgroundColor cornerRadius borderWidth bounds contents contentsRect cornerRadius frame hidden mask masksToBounds opacity position shadowColor shadowOffset shadowOpacity shadowRadius
簡單圖層屬性變化動畫
- CATransform3D制作3D動畫效果
初始狀態 點擊后狀態
- 路徑動畫示例代碼(商品落入購物車)
CATransition
類實現了圖層的過度動畫效果。可以通過從預定義的過渡集合中選擇過渡效果,或是提供自定義的CIFilter實例。
from:http://www.devdiv.com/home.php?mod=space&uid=8639&do=blog&id=4143
其中有些過渡類型沒有出現在Common transition types documentation中。這可能會導致應用被apple store拒絕,但僅僅是可能,因為至今還沒有明確的文檔或資料說使用Core Animation的無文檔的過渡效果API會被apple store拒絕。在iphonedevsdk上也討論過該問題,其中一位回答者談到:“I asked Apple's engineers about this specific issue. They said that officially, undocumented transition effects are just like any other undocumented API feature, and are not allowed.However, their automated tools are not set up to detect using undocumented transitions like they are using undocumented methods, so you may get away with it, and you may not. It's a gamble.”。
代碼部分:
- [UIView transitionFromView] 視圖間的切換
- 仿射變換的回退
CGAffineTransform inverse = CGAffineTransformInvert(CGAffineTransformMakeTranslation(5.0, 5.0));
- 多個仿射變換的拼接
CGAffineTransform transform = CGAffineTransformConcat(CGAffineTransformMakeScale(1, 1), CGAffineTransformMakeTranslation(-50, -50));
- 判斷視圖顯示或消失的原因
偶爾我們需要了解視圖顯示和消失的原因,比如說,你可能想知道一個視圖的顯示是因為它被加入到一個容器中還是因為其他遮蔽它的內容被移除才致使它被顯示。一個常見的例子是當使用導航控制器,你的內容控制器視圖可能是因為視圖控制器被壓入導航控制器棧中而被顯示,也有可能是因為在它上面的控制器從棧中被移除致使其顯示。
UIViewController類提供一組可以調用以了解視圖的顯示狀態變化的原因,下表是對這些方法的描述與用法。這些方法可以在viewWillAppear:viewDidAppear:,viewWillDisapper:與viewDidDisppaer:方法中使用。
方法名 |
用法 |
isMovingFromParentViewController |
在viewWillDisappaer:與viewDidDisapper:方法中調用這個方法,用以了解視圖控制器的視圖被隱藏是因為視圖控制器從它的容器控制器中被移除。 |
isMovingToParentViewController |
在viewWillAppear:和viewDidAppear方法中調用,用以了解視圖控制器的顯示是因為視圖控制器被加入到容器視圖控制器中。 |
isBeingPresented |
在viewWillAppaer:與viewDidApper:方法中調用這個方法,用以了解視圖控制器的視圖被顯示是因為被另外的控制器呈現,如模態呈現 |
isBeingDismissed |
在viewWillDisappear:和viewDidDisappear方法中調用,用以了解視圖控制器的的隱藏是因為控制器被dismissed |
- parameter 是參數,而 argument 是參數的值。
- iOS-Best-Practices By Jeff Verkoeyen from https://github.com/jverkoey/iOS-Best-Practices.
- 小女子的總結:from: http://www.cocoachina.com/bbs/read.php?tid=105689
下載地址:http://dl.vmall.com/c0k19fs478
- UITableview滾動觸發事件
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;
{
[self.searchBox resignFirstResponder];
}
- 去除UITableview多余的空行橫線
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
// This will create a "invisible" footer
return 0.01f;
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
return [UIView new];
}
- UIPickerView添加圖標行
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row
forComponent:(NSInteger)component reusingView:(UIView *)view {
UILabel *firstLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 0, 60, 32)];
firstLabel.text = [array1 objectAtIndex:row];
firstLabel.textAlignment = UITextAlignmentLeft;
firstLabel.backgroundColor = [UIColor clearColor];
UILabel *secondLabel = [[UILabel alloc] initWithFrame:CGRectMake(165, 0, 60, 32)];
secondLabel.text = [array2 objectAtIndex:row];
secondLabel.textAlignment = UITextAlignmentLeft;
secondLabel.backgroundColor = [UIColor clearColor];
UIImage *img = [UIImage imageNamed:[NSString stringWithFormat:@"%@.png",[countries objectAtIndex:row]]];
UIImageView *icon = [[UIImageView alloc] initWithImage:img];
temp.frame = CGRectMake(170, 0, 30, 30);
UIView *tmpView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 290, 32)] autorelease];
[tmpView insertSubview:icon atIndex:0];
[tmpView insertSubview:firstLabel atIndex:0];
[tmpView insertSubview:secondLabel atIndex:0];
[tmpView setUserInteractionEnabled:NO];
[tmpView setTag:row];
[channelLabel release];
[temp release];
return tmpView;
}
from:http://stackoverflow.com/questions/10128068/uipickerview-showing-images-and-strings
- 在iOS中使用自定義字體
Here’s the updated details of how to use custom fonts in iPhone. This is only available for SDK 4.0 and above.
- Add your custom font files into your project using XCode as resources.
- Add a key to your info.plist file called “Fonts provided by application” ( Used to be called UIAppFonts).
- It’s an array key.
- For each font you have, enter the full name of your font file (including the extension).
- Save info.plist.
- Now in your application you can simply call [UIFont fontWithName:@"CustomFontName" size:12] to get the custom font to use with your UILabels and UITextView.
- “CustomFontName” is not the font’s file name. It is the font name registered in the operating system. For example, if you try to use “Bauhaus Medium BT.ttf”, the “CustomFontName” should be “Bauhaus Md BT”, no extension “.ttf” is needed. You need to install the font in your system to find out what name it is. Some fonts have 2 names, you may need FontForge to find out and try which one works.
- So far I found out that both ttf and otf format work out of the box. I haven’t tested other font formats yet.
*Points 1-6 credit to http://blog.beefyapps.com/
- iOS啟動畫面設計的若干建議
try a very simple logo and a solid background. Its a loading screen that is only seen for a few seconds and doesn't need to be fansy., make your splash screen be something that will compress well as a png file. Two things happen, first the pixels are passed through a filter function to take advantage of the fact that pixel near each other will have similar values, then they are compressed with the deflate algorithm (same as used by gzip or zlib).
So some things that can help take advantage of that.
1) Avoid photos. They have a lot of noise and detail in them which doesn't compress well as png.
2) If possible, use very few colors. A solid color background with some text on it is going to compress very small. ~100kb for a 1024x768.
3) Similar to #2, reduce your colors. You don't *really* need a 24bit png file to display on a (probably?) 18-21 bit LCD. Use the photoshop "posterize" command. See if 64 or 32 levels looks ok for your art.
4) Avoid dithering if possible. Dithering adds a bunch of randomness to the data that compresses poorly.
5) Less detail means more repetition that the can be compressed.
6) Stick with simple linear gradients if possible.
- 刪除.svn文件腳本
find ./ -name .svn -exec rm -rf {} \;
- Mac OS 顯示/關閉顯示被隱藏的文件終端命令:
1.顯示
defaults write com.apple.finder AppleShowAllFiles -bool true
KillAll Finder
2.關閉顯示
defaults write com.apple.finder AppleShowAllFiles -bool false
KillAll Finder
- 關於時間的若干操作 from:http://blog.csdn.net/yangbo_hbzjk/article/details/7625276
1 // 當前時間創建NSDate
NSDate *myDate = [NSDate date];
NSLog(@"myDate = %@",myDate);
2 //從現在開始的24小時
NSTimeInterval secondsPerDay = 24*60*60;
NSDate *tomorrow = [NSDate dateWithTimeIntervalSinceNow:secondsPerDay];
NSLog(@"myDate = %@",tomorrow);
3//根據已有日期創建日期
NSTimeInterval secondsPerDay1 = 24*60*60;
NSDate *now = [NSDate date];
NSDate *yesterDay = [now addTimeInterval:-secondsPerDay1];
NSLog(@"yesterDay = %@",yesterDay);
4//比較日期
BOOL sameDate = [now isEqualToDate:yesterDay];
NSLog(@"sameDate = %lu",sameDate);
4.1//獲取較早的日期
NSDate *earlierDate = [yesterDay earlierDate:now];
NSLog(@"earlierDate = %@",earlierDate);
4.2//較晚的日期
NSDate *laterDate = [yesterDay laterDate:now];
NSLog(@"laterDate = %@",laterDate);
//兩個日期之間相隔多少秒
NSTimeInterval secondsBetweenDates= [yesterDay timeIntervalSinceDate:now];
NSLog(@"secondsBetweenDates= %lf",secondsBetweenDates);
//通過NSCALENDAR類來創建日期
NSDateComponents *comp = [[NSDateComponentsalloc]init];
[comp setMonth:06];
[comp setDay:01];
[comp setYear:2001];
NSCalendar *myCal = [[NSCalendaralloc]initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *myDate1 = [myCal dateFromComponents:comp];
NSLog(@"myDate1 = %@",myDate1);
//從已有日期獲取日期
unsigned units = NSMonthCalendarUnit|NSDayCalendarUnit|NSYearCalendarUnit;
NSDateComponents *comp1 = [myCal components:units fromDate:now];
NSInteger month = [comp1 month];
NSInteger year = [comp1 year];
NSInteger day = [comp1 day];
//NSDateFormatter實現日期的輸出
NSDateFormatter *formatter = [[NSDateFormatteralloc]init];
[formatter setDateStyle:NSDateFormatterFullStyle];//直接輸出的話是機器碼
//或者是手動設置樣式[formatter setDateFormat:@"yyyy-mm-dd"];
NSString *string = [formatter stringFromDate:now];
NSLog(@"string = %@",string);
NSLog(@"formater = %@",formatter);
question: Given a NSDate * startDate and endDate and a NSManagedObjectContext * moc:
NSPredicate*predicate =[NSPredicate predicateWithFormat:@"(date >= %@) AND (date <= %@)", startDate, endDate];
NSFetchRequest*request =[[[NSFetchRequest alloc] init] autorelease];
[request setEntity:[NSEntityDescription entityForName:@"EntityName" inManagedObjectContext:moc]];
[request setPredicate:predicate];NSError*error = nil;
NSArray*results =[moc executeFetchRequest:request error:&error];
- 添加調試條件
objc_exception_throw
- NSMutableSet操作
- (void)unionSet:(NSSet *)otherSet; // 求並集
- (void)minusSet:(NSSet *)otherSet; // 求差集
- (void)intersectSet:(NSSet *)otherSet; // 求交集
· Block作為形參
語法:(<返回類型> (^)(參數列表…))<塊名>
(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success
- Block類型重定義
語法:typedef <返回類型> (^類型名)(參數列表);
typedef void (^MBProgressHUDCompletionBlock)();
typedef void (^SuccessBlock)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON);
- 放置在UIScrollView上的UIImageView響應點擊事件
UIImageView* myImageView;
myImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"ic_playvideo.png"]];
myImageView.userInteractionEnabled = YES;
UITapGestureRecognizer *pgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapEvent:)];
[myImageView addGestureRecognizer:pgr];
- (void) handleTapEvent: (id)sender {
UIImageView* touchedImageView = (UIImageView*)((UITapGestureRecognizer *)sender).view;
}
- 移除視圖的所有子視圖
[[myView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
- 兩個日期相距的秒數
NSDate *lastDate = [NSDate date];
NSDate *todaysDate = [NSDate date];
NSTimeInterval lastDiff = [lastDate timeIntervalSinceNow];
NSTimeInterval todaysDiff = [todaysDate timeIntervalSinceNow];
int intervalSecond = lastDiff - todaysDiff;
- 限制UITextView字數
- (BOOL)isAcceptableTextLength:(NSUInteger)length {
return length <= kWordLimit;
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)string {
return [self isAcceptableTextLength:textView.text.length + string.length - range.length];
}
限制UITextField字數
- (BOOL)textField:(UITextField *) textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSUInteger oldLength = [textField.text length];
NSUInteger replacementLength = [string length];
NSUInteger rangeLength = range.length;
NSUInteger newLength = oldLength - rangeLength + replacementLength;
BOOL returnKey = [string rangeOfString: @"\n"].location != NSNotFound;
return newLength <= kWordLimit || returnKey;
}
- 方法響應檢測執行
if ([self.delegate respondsToSelector:@selector(dismissPopoverView:)]) {
[_delegate performSelector:@selector(dismissPopoverView:) withObject:sender];
}
- protocol聲明規范
@class PlayerDetailsViewController;
@protocol PlayerDetailsViewControllerDelegate <NSObject>
- (void)playerDetailsViewControllerDidCancel:(PlayerDetailsViewController *)controller;
- (void)playerDetailsViewControllerDidSave:(PlayerDetailsViewController *)controller;
@end
@protocol PlayerDetailsViewControllerDelegate <NSObject>
- (void)playerDetailsViewControllerDidCancel:(PlayerDetailsViewController *)controller;
- (void)playerDetailsViewController:(PlayerDetailsViewController *)controller didAddPlayer:(Player *)player;
@end
- UIBarButtonItem添加間隙
UIBarButtonItem *fixed;
fixed = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
fixed.width = 8;
- 對數組排序的三種方法、
1. 使用比較方法
- (NSComparisonResult)compare:(Person *)otherObject {
return [self.birthDate compare:otherObject.birthDate];
}
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(compare:)];
2. 使用NSSortDescriptor(最佳)
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate"
ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];
3. 使用block (帥)
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSDate *first = [(Person*)a birthDate];
NSDate *second = [(Person*)b birthDate];
return [first compare:second];
}];
- NSSet排序
NSArray *sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]];
NSArray *sortedRecipes = [[recipes allObjects] sortedArrayUsingDescriptors:sortDescriptors];
- NSSet轉化為NSMutableArray
NSMutableArray *array = [NSMutableArray arrayWithArray:[set allObjects]];
NSMutableArray *array = [[set allObjects] mutableCopy];
- 消除NSString首尾空格
- (NSString *)stringByTrimmingLeadingCharactersInSet:(NSCharacterSet *)characterSet {
NSRange rangeOfFirstWantedCharacter = [self rangeOfCharacterFromSet:[characterSet invertedSet]];
if (rangeOfFirstWantedCharacter.location == NSNotFound) {
return @"";
}
return [self substringFromIndex:rangeOfFirstWantedCharacter.location];
}
- (NSString *)stringByTrimmingLeadingWhitespaceAndNewlineCharacters {
return [self stringByTrimmingLeadingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
- (NSString *)stringByTrimmingTrailingCharactersInSet:(NSCharacterSet *)characterSet {
NSRange rangeOfLastWantedCharacter = [self rangeOfCharacterFromSet:[characterSet invertedSet]
options:NSBackwardsSearch];
if (rangeOfLastWantedCharacter.location == NSNotFound) {
return @"";
}
return [self substringToIndex:rangeOfLastWantedCharacter.location+1]; // non-inclusive
}
- (NSString *)stringByTrimmingTrailingWhitespaceAndNewlineCharacters {
return [self stringByTrimmingTrailingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
- nil是一個對象指針為空,Nil是一個類指針為空,NULL是基本數據類型為空
id aValue = [arrayWithNull objectAtIndex:0];
if (aValue == nil) {
NSLog(@"equals nil");
} else if (aValue == [NSNull null]) {
NSLog(@"equals NSNull instance");
if ([aValue isEqual:nil]) {
NSLog(@"isEqual:nil");
}
}
- 添加DEBUG預處理標記
· 獲得一個類的屬性列表 from: http://stackoverflow.com/questions/754824/get-an-object-attributes-list-in-objective-c
- (void)myMethod {
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList([self class], &outCount);
for(i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
const char *propName = property_getName(property);
if(propName) {
const char *propType = getPropertyType(property);
NSString *propertyName = [NSString stringWithCString:propName];
NSString *propertyType = [NSString stringWithCString:propType];
...
}
}
free(properties);
}
static const char *getPropertyType(objc_property_t property) {
const char *attributes = property_getAttributes(property);
char buffer[1 + strlen(attributes)];
strcpy(buffer, attributes);
char *state = buffer, *attribute;
while ((attribute = strsep(&state, ",")) != NULL) {
if (attribute[0] == 'T') {
return (const char *)[[NSData dataWithBytes:(attribute + 3) length:strlen(attribute) - 4] bytes];
}
}
return "@";
}
· URL中文編碼與解碼
在iOS app開發中,如果需要對url中的中文和特殊字符進行url編碼,一般有兩種方法:
1. 使用NSString實現encode:
NSString* sURL = [string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
實現decode:
NSString* sURL = [string stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
2.使用CFStringRef實現encode:
指定需要編碼的字符
NSString* sURL = (NSString*)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)input, NULL, (CFStringRef)@"!*'();:@&=+$,/?%#[]", kCFStringEncodingUTF8);
如果僅僅只需要編碼中文
NSString* sURL = (NSString*)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)input, NULL, NULL, kCFStringEncodingUTF8);
實現decode:
NSMutableString* inputStr = [NSMutableString stringWithString:input];
[inputStr replaceOccurrencesOfString:@"+" withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [inputStr length])];
NSString* sURl = [inputStr stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
· 獲得一個類的實例變量列表
unsigned int varCount;
Ivar *vars = class_copyIvarList([MyClass class], &varCount);
for (int i = 0; i < varCount; i++) {
Ivar var = vars[i];
const char* name = ivar_getName(var);
const char* typeEncoding = ivar_getTypeEncoding(var);
// do what you wish with the name and type here
}
free(vars);
· 連接NSSet元素,轉化為NSString類型
NSSet*set = [NSSet setWithObjects:@"String 1",@"String 2",@"String 3", nil];
NSString* string = [[set allObjects] componentsJoinedByString:@" "];
· Option+command拖動模擬器文件夾到桌面,創建快捷方式
· 在何處移除觀察者
The generic answer would be "as soon as you no longer need the notifications". This is obviously not a satisfying answer.
I'd recommend, that you add a call [notificationCenter removeObserver: self] in methoddealloc of those classes, which you intend to use as observers, as it is the last chance to unregister an observer cleanly. This will, however, only protect you against crashes due to the notification center notifying dead objects. It cannot protect your code against receiving notifications, when your objects are not yet/no longer in a state in which they can properly handle the notification. For this... See above.
-(void) dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
from: http://stackoverflow.com/questions/6469209/objective-c-where-to-remove-observer-for-nsnotification
如果出現在dealloc中移除通知,卻發現dealloc沒有調用,導致發一次通知會調用同樣一段代碼多次。這時候就要注意,因為很明顯當前類沒有被釋放。如果你選擇將添加通知放在viewWillAppear中,移除通知放在viewWillDisappear中,雖然暫時可以將多次調用解決掉。但是類沒有被釋放的問題還是沒有解決。而導致類沒有被釋放的原因很可能就是當前類雖然從navigationController中彈出了或者從父控制器dismiss了,但是還存在對當前類的strong引用,比如代理之類的引用。對於ARC來說,默認是strong引用。此時你只需要在其他類中將對當前類的引用改成weak就可以讓dealloc重新被調用了。有用的討論地址:http://stackoverflow.com/questions/8727316/arc-uinavigationcontroller-stack-not-getting-deallocated-when-presented-as-modal
· 添加通知
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self checkSyncStatus];
[[NSNotificationCenter defaultCenter] addObserverForName:@"observerKey" object:nil queue:nil usingBlock:^(NSNotification *note) {
[self loadRecordsFromCoreData];
[self.tableView reloadData];
}];
[[SDSyncEngine sharedEngine] addObserver:self forKeyPath:@"observerKey" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"SDSyncEngineSyncCompleted" object:nil];
[[SDSyncEngine sharedEngine] removeObserver:self forKeyPath:@"syncInProgress"];
}
(IBAction)refreshButtonTouched:(id)sender {
[[SDSyncEngine sharedEngine] startSync];
}
- (void)checkSyncStatus {
if ([[SDSyncEngine sharedEngine] syncInProgress]) {
[self replaceRefreshButtonWithActivityIndicator];
} else {
[self removeActivityIndicatorFromRefreshButton];
}
}
- (void)replaceRefreshButtonWithActivityIndicator {
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 25, 25)];
[activityIndicator setAutoresizingMask:(UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin)];
[activityIndicator startAnimating];
UIBarButtonItem *activityItem = [[UIBarButtonItem alloc] initWithCustomView:activityIndicator];
self.navigationItem.leftBarButtonItem = activityItem;
}
- (void)removeActivityIndicatorFromRefreshButton {
self.navigationItem.leftBarButtonItem = self.refreshButton;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"observerKey"]) {
[self checkSyncStatus];
}
}
· 獲取字符串中的數據
做法1:
NSString *logString = @"user logged (3 attempts)";
// stringByTrimmingCharactersInSet選取包含在指定字符集中的字符串,invertedSet方法用來獲取所有非數字的字符集
NSString *digits = [logString stringByTrimmingCharactersInSet: [[NSCharacterSet decimalDigitCharacterSet] invertedSet]]; NSLog(@"Attempts: %i", [digits intValue]);
輸出:Attempts: 3
做法2:
// 源字符串,觀察該字符串,會發現該字符串的分隔符包括分號和逗號,並且一段英文字符和三段數字分為一組,共分四組
// 我們的工作就是取出由分號和逗號分割的數據
NSString *sourceString = @"Los Angeles;8.25;0.580561574;1,Tokyo;1.9;0.643872234;1;Honolulu,0;0;0;Toronto;7.9;5.3322;3;";
// 創建一個行掃描器
NSScanner *myScanner = [NSScanner scannerWithString:sourceString];
NSString *stringValue;
float theRevenue;
float thePercent;
int theRank;
// 設置一個何時停止掃描的字符集,該字符集用於掃描器向前掃描時停止掃描的條件
NSCharacterSet *stopSet;
stopSet = [NSCharacterSet characterSetWithCharactersInString:@";,"];
// 判斷掃描器是否已經掃描到字符串末尾,到末尾返回YES
while ([myScanner isAtEnd] == NO) {
// 掃描器向前掃描源字符串,直到遇到stopSet包含的字符串位置,並將之前掃描到的字符串放入stringValue中
// 與之類似方法有scanUpToString: intoString:
if ( [myScanner scanUpToCharactersFromSet:stopSet intoString:&stringValue] ) {
NSLog (@"%@",stringValue);
}
// 跳過分號或者逗號字符串,也可以使用scanCharactersFromSet: intoString方法
if([myScanner scanString:@";" intoString:NULL] || [myScanner scanString:@"," intoString:NULL]);
// 獲取浮點數
if([myScanner scanFloat:&theRevenue])
NSLog(@"%lf",theRevenue);
if([myScanner scanString:@";" intoString:NULL] || [myScanner scanString:@"," intoString:NULL]);
if([myScanner scanFloat:&thePercent])
NSLog(@"%lf",thePercent);
if([myScanner scanString:@";" intoString:NULL] || [myScanner scanString:@"," intoString:NULL]);
if([myScanner scanInt:&theRank])
NSLog(@"%i",theRank);
if([myScanner scanString:@";" intoString:NULL] || [myScanner scanString:@"," intoString:NULL]);
}
· 獲取視圖的父視圖所對應的控制器
- (UIViewController*)viewControllerOfSuperView: (UIView*) subView {
for (UIView* next = [subView superview]; next; next = next.superview){
UIResponder* nextResponder = [next nextResponder];
if ([nextResponder isKindOfClass:[UIViewController class]]) {
return (UIViewController*)nextResponder;
}
}
return nil;
}
· 異步多任務完成后,執行指定操作
dispatch_group_t group = dispatch_group_create();
MyCoreDataObject *coreDataObject;
dispatch_group_enter(group);
AFHTTPRequestOperation *operation1 = [[AFHTTPRequestOperation alloc] initWithRequest:request1];
[operation1 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
coreDataObject.attribute1 = responseObject;
sleep(5);
dispatch_group_leave(group);
}];
[operation1 start];
dispatch_group_enter(group);
AFHTTPRequestOperation *operation2 = [[AFHTTPRequestOperation alloc] initWithRequest:request1];
[operation2 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
coreDataObject.attribute2 = responseObject;
sleep(10);
dispatch_group_leave(group);
}];
[operation2 start];
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(group);
[context save:nil];
· 數組過濾查找
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"type == %@", @"standard"];
NSArray *filteredArray = [myArray filteredArrayUsingPredicate:predicate];
id firstFoundObject = nil;
if ([filteredArray count] > 0) {
firstFoundObject = [filteredArray objectAtIndex:0];
}
· CAScrollLayer的使用
-(void) setupLayers{
CALayer* mainLayer = self.layer;
CGFloat midX = CGRectGetMidX( mainLayer.frame );
CGFloat midY = CGRectGetMidY( mainLayer.frame );
CAScrollLayer* contentContainer = [CAScrollLayer layer];
contentContainer.bounds = mainLayer.bounds;
currentX=contentContainer.bounds.origin.x;
contentContainer.anchorPoint = CGPointMake(0.5,0.5);
contentContainer.position = CGPointMake( midX, midY );
[self.layer addSublayer:contentContainer];
self.bookRootLayer = contentContainer;
contentContainer.name = @"scrollLayer";
contentContainer.scrollMode = kCAScrollHorizontally;
for (int i=0;i<[self.booksArray count];i++){
CALayer *singleLayer=[CALayer layer];
//homebrew shadow
CALayer *shadowLayer=[CALayer layer];
shadowLayer.contents=(id)[UIImage imageNamed:@"bookshadow.png"].CGImage;
shadowLayer.frame=CGRectMake(i*100, (self.frame.size.height-118), 91, 118);
shadowLayer.name=[NSString stringWithFormat:@"shadow-%d",i];
[self.bookRootLayer addSublayer:shadowLayer];
NSDictionary *singleBook=[self.booksArray objectAtIndex:i];
[singleLayer setContents:(id)[(UIImage*)[singleBook objectForKey:@"imgdata"] CGImage]];
singleLayer.frame=CGRectMake(i*100+4, (self.frame.size.height-115), 82, 110);
singleLayer.name=[NSString stringWithFormat:@"layer-%d",i];
[self.bookRootLayer addSublayer:singleLayer];
((CAScrollLayer*)self.bookRootLayer).frame =CGRectMake(0, (self.frame.size.height-110), (i+1)*100, 118);
}
}
· 移動CAScrollLayer
[self.bookRootLayer scrollToPoint:CGPointMake(100,0)];
· 選取特定Layer
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
CGPoint touchLocation = [[touches anyObject] locationInView:self];
CALayer *hitLayer=[self.bookRootLayer hitTest:touchLocation];
NSLog(@"LayerName: %@", [hitLayer name]);
}
· 點擊UITableViewCell上的UIButton控件,獲取指定的NSIndexPath
-(void)OnTouchBtnInCell:(UIButton *)btn
{
CGPoint point = btn.center;
point = [table convertPoint:point fromView:btn.superview];
NSIndexPath* indexpath = [table indexPathForRowAtPoint:point];
UITableViewCell *cell = [table cellForRowAtIndexPath:indexpath];
}
· 在滾動的時候降低圖片畫質,提升滾動時的渲染性能
UIImage* highResolution = [UIImage imageNamed:@"CuriousFrog.png"];
NSData* dateFromJPEG = UIImageJPEGRepresentation(highResolution, 0.1f);
UIImage* lowResolution = [UIImage imageWithData:dateFromJPEG];
NSLog(@"%d", [dateFromJPEG length]);
· NSTimer的用法
1) 預定計時器 & 使用選擇器
NSTimer*t =[NSTimer scheduledTimerWithTimeInterval:2.0
target: self
selector:@selector(onTick:)
userInfo: nil
repeats:NO];
· 如果將repeats參數設為NO,定時器將在等待2秒鍾之后執行選擇器,最后將停止。
· 如果repeats為YES,定時器將立即開始,並且每2秒調用一次選擇器。
· 通過調用定時器的實例方法invalidate,並將定時器置為nil。以停止定時器。
2) 自預定定時器
NSDate*d =[NSDate dateWithTimeIntervalSinceNow:60.0];
NSTimer*t =[[NSTimer alloc] initWithFireDate: d interval:1 target:self selector:@selector(onTick:)userInfo:nil repeats:YES];
NSRunLoop*runner =[NSRunLoop currentRunLoop];
[runner addTimer:t forMode:NSDefaultRunLoopMode];
這將創建一個在指定的日期內開始的定時器(上面例子中的定時器會在1分鍾之后開始),並會每秒鍾重復一次。
判斷針對當前app的定位服務是否開啟
[CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorized
· 取點擊的位置
CGPoint point1=[self.bookRootLayer convertPoint:touchLocation fromLayer:self.layer];
NSLog(@"click point: %f, %f",point1.x, point1.y);