iOS快速開發必備
原文 http://segmentfault.com/a/1190000003520629
前言
個人github: https://github.com/xfxfxf
當前移動互聯網行業太火爆,移動端的需求日益增長,很多開發人員每天都應對著各種需求,作為一名iOS開發人員,對于需求來說,我們要做到的是實現,而對于自己來說,我們需要做到的是寫出高質量的代碼。
于是,全球的大神們開源了很多高質量、可復用的代碼,給予了蕓蕓眾生(心中一萬個感謝)。例如我們常用的 AFNetworking,SDWebImage,Masonry 等等,這些第三方庫內容強大,性能很高,為大家帶來了很多福利。
在開發過程當中,適當合理的使用這些第三方庫能幫我們節省很多的時間。這些優秀的第三方庫就如同教科書一樣,當我們深入挖掘的時候,才能獲得更高的提升。
好了,吹了半天牛,我們現在到底要做什么呢?其實我想說的是,合理的使用第三方庫能大大的提升開發效率,也許我們自己研究做動畫弄半天,還不如開源動畫好用,這樣的情況很多時候我們是不得不承認的。與其與之較勁,不如我們先使用它們的框架,然后再做深入探究,這樣方能更好的掌握。
網上很多好的整理,我這里引用一下: 剛剛在線 博客,里面有很多整理好的內容,非常好的干貨。感謝原作者的內容,其中有一個整理的是iOS開發好用的 category,能幫我們節省很多精力,接下來我就先一一分析github上面這些category,翻譯其中重要的內容。
聲明:本人翻譯并不能做到百分之百準確,內容如果有誤,歡迎下方評論指導,謝謝!
UIImageView_FaceAwareFill
簡介
地址: https://github.com/Julioacarrettoni/UIImageView_FaceAwareFill
This category applies Aspect Fill content mode to an image and if faces are detected it centers them instead of centering the image just by its geometrical center.這個 category 使用了 Aspect Fill 的模式來顯示圖片并且當人臉被檢測到時,它會就以臉部中心替代圖片的集合中心。
使用
pch 文件中直接導入
#import "UIImageView+UIImageView_FaceAwareFill.h"
設置完一個UIImageView的屬性以后直接
[self.imageView faceAwareFill];
然后就完了。。。。。
個人評價
看到沒有,大神的提供的方法就是如此狂拽炫酷叼霸天,就是如此的簡單。
NSRegularEx+ObjCRegex
This project simplifies regular expressions in Objective-C and Swift.
這個猛,直接把objective-c和swift里面的正則表達式給整合了。
這是一組對比
// Without this library NSString* string = @"I have 2 dogs."; NSRegularExpression *regex = [NSRegularExpression regular ExpressionWithPattern:@"\\d+" options:NSRegularExpressionCaseInsensitive error:&error]; NSTextCheckingResult *match = [regex firstMatchInString:string options:0 range:NSMakeRange(0, [string length])]; BOOL isMatch = match != nil; // With this library BOOL isMatch = [@"I have 2 dogs." isMatch:RX(@"\\d+")];
使用
安裝過程就不贅述了,要么是cocoapods,要么直接拖進去。
老規矩,在 pch 文件中添加:
#ifdef __OBJC__ /* ...other references... */ #import "RegExCategories.h" #endif
當然,你的工程需要開啟ARC。
Swift支持
這個就需要一個橋接文件,百度即可,Swift引用 OC 的三方都是需要一個橋接文件。
后面的教程就不翻譯了,直接去看代碼吧,少年。
個人評價還在為正則表達式而糾結嗎?還在調試正則表達式問題嗎?沒錯,走過路過不要錯誤,這里有你想要的一切。
NSObject+AutoCoding
簡介
地址: https://github.com/nicklockwood/AutoCoding
這個是一個NSObject的 category,提供了對NSCoding和NSCopying的自動支持。這意味著你不要寫initWithCoder:和encodeWithCoder:了,這個直接承包了。
當然,怎么用還是要看自己的,它并不能讀懂你的思維。還有舉個例子,你應該避免使用結構體因為它并不遵循NSCoding協議,而是通過NSValue。
支持很多版本
支持ARC和MRC
線程安全
使用
直接把AutoCoding.h和AutoCoding.m拖進工程。
其實自己寫歸檔和反歸檔也沒有那么復雜,這里就不做詳細介紹了。
個人評價
這個其實還好,不過其中的機制很不錯,值得一看,后面有時間我再翻譯。
UILabel-ContentSize
簡介
來源: https://github.com/mergesort/UILabel-ContentSize
使用
通過傳入的字符串來改變UILabel的Size。
直接把.h和.m文件導入工程吧。
個人評價
正如同作者所說的,總是會忘記操作細節,不如直接寫成 category。
UIViewController-Swizzled
簡介
來源: https://github.com/RuiAAPeres/UIViewController-Swizzled
這個能幫你管理你的應用。當你正在做復雜的行為以及剛接手工程的時候這個會變得特別好用。使用這個 category 能看到你現在所在的UIViewController,還有展示你進入的層次。
使用
老規矩,要么直接拖入,要么用cocoapods。
需要導入鏈接庫:
libobjc.dylib
然后導入頭文件:
#import "UIViewController+Swizzled.h"
在AppDelegate中,你需要在方法- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法里面加入SWIZZ_IT開啟。如果因為什么原因你想要停止,只需要添加UN_SWIZZ_IT。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { SWIZZ_IT; self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; [self.window makeKeyAndVisible]; // Your code... return YES; }
然后就能看到輸出:
2013-09-09 18:58:42.360 Testing[25399:c07] -> UINavigationController 2013-09-09 18:58:42.361 Testing[25399:c07] ---> RPViewController 2013-09-09 18:59:55.072 Testing[25399:c07] -----> RPSecondViewController 2013-09-09 18:59:57.367 Testing[25399:c07] -------> RPThirdViewController 2013-09-09 18:59:58.801 Testing[25399:c07] -----> RPSecondViewController 2013-09-09 19:00:00.282 Testing[25399:c07] -------> RPThirdViewController 2013-09-09 19:00:01.906 Testing[25399:c07] ---------> RPViewController 2013-09-09 19:00:03.515 Testing[25399:c07] -------> RPThirdViewController 2013-09-09 19:00:04.267 Testing[25399:c07] -----> RPSecondViewController 2013-09-09 19:00:05.041 Testing[25399:c07] ---> RPViewController 2013-09-09 19:00:07.193 Testing[25399:c07] -----> RPSecondViewController 2013-09-09 19:00:08.312 Testing[25399:c07] -------> RPThirdViewController 2013-09-09 19:00:09.396 Testing[25399:c07] ---------> RPViewController 2013-09-09 19:00:10.183 Testing[25399:c07] -----------> RPSecondViewController 2013-09-09 19:00:10.905 Testing[25399:c07] -------------> RPThirdViewController 2013-09-09 19:00:12.141 Testing[25399:c07] ---------------> RPViewController 2013-09-09 19:00:13.156 Testing[25399:c07] -----------------> RPSecondViewController
個人評價
當你剛接手一個新的項目的時候,無數個文件。
這是什么鬼?程序怎么運行的?那個類是干嘛用的?為什么運行到了這里,還有,文件怎么找?要瘋掉了。。。
有了此神器,天黑都不怕,一步一步是爪牙,是魔鬼的步伐,程序的運行一清二楚,簡直出門旅行,居家必備之良藥。
你值得擁有!
NSDate-Escort
簡介
來源: https://github.com/azu/NSDate-Escort
加強NSDate
使用
/** Returns the calendarIdentifier of calendars that is used by this library for date calculation. @see AZ_setDefaultCalendarIdentifier: for more details. */ + (NSString *)AZ_defaultCalendarIdentifier; /** Sets the calendarIdentifier of calendars that is used by this library for date calculation. You can specify any calendarIdentifiers predefined by NSLocale. If you provide nil, the library uses [NSCalendar currentCalendar]. Default value is nil. You can't provide individual calendars for individual date objects. If you need to perform such complicated date calculations, you should rather create calendars on your own. */ + (void)AZ_setDefaultCalendarIdentifier:(NSString *)calendarIdentifier; #pragma mark - Relative dates from the current date - (BOOL)isYesterday; - (BOOL)isSameWeekAsDate:(NSDate *) aDate; - (BOOL)isThisWeek; - (BOOL)isNextWeek; - (BOOL)isLastWeek; - (BOOL)isSameMonthAsDate:(NSDate *) aDate; - (BOOL)isThisMonth; - (BOOL)isSameYearAsDate:(NSDate *) aDate; - (BOOL)isThisYear; - (BOOL)isNextYear; - (BOOL)isLastYear; - (BOOL)isEarlierThanDate:(NSDate *) aDate; - (BOOL)isLaterThanDate:(NSDate *) aDate; - (BOOL)isEarlierThanOrEqualDate:(NSDate *) aDate; - (BOOL)isLaterThanOrEqualDate:(NSDate *) aDate; - (BOOL)isInFuture; - (BOOL)isInPast; #pragma mark - Date roles - (BOOL)isTypicallyWorkday; - (BOOL)isTypicallyWeekend; #pragma mark - Adjusting dates - (NSDate *)dateByAddingYears:(NSInteger) dYears; - (NSDate *)dateBySubtractingYears:(NSInteger) dYears; - (NSDate *)dateByAddingMonths:(NSInteger) dMonths; - (NSDate *)dateBySubtractingMonths:(NSInteger) dMonths; - (NSDate *)dateByAddingDays:(NSInteger) dDays; - (NSDate *)dateBySubtractingDays:(NSInteger) dDays; - (NSDate *)dateByAddingHours:(NSInteger) dHours; - (NSDate *)dateBySubtractingHours:(NSInteger) dHours; - (NSDate *)dateByAddingMinutes:(NSInteger) dMinutes; - (NSDate *)dateBySubtractingMinutes:(NSInteger) dMinutes; - (NSDate *)dateAtStartOfDay; - (NSDate *)dateAtEndOfDay; - (NSDate *)dateAtStartOfWeek; - (NSDate *)dateAtEndOfWeek; - (NSDate *)dateAtStartOfMonth; - (NSDate *)dateAtEndOfMonth; - (NSDate *)dateAtStartOfYear; - (NSDate *)dateAtEndOfYear; #pragma mark - Retrieving intervals - (NSInteger)minutesAfterDate:(NSDate *) aDate; - (NSInteger)minutesBeforeDate:(NSDate *) aDate; - (NSInteger)hoursAfterDate:(NSDate *) aDate; - (NSInteger)hoursBeforeDate:(NSDate *) aDate; - (NSInteger)daysAfterDate:(NSDate *) aDate; - (NSInteger)daysBeforeDate:(NSDate *) aDate; - (NSInteger)monthsAfterDate:(NSDate *) aDate; - (NSInteger)monthsBeforeDate:(NSDate *) aDate; /** * return distance days */ - (NSInteger)distanceInDaysToDate:(NSDate *) aDate; #pragma mark - Decomposing dates /** * return nearest hour */ @property(readonly) NSInteger nearestHour; @property(readonly) NSInteger hour; @property(readonly) NSInteger minute; @property(readonly) NSInteger seconds; @property(readonly) NSInteger day; @property(readonly) NSInteger month; @property(readonly) NSInteger week; // in the Gregorian calendar, n is 7 and Sunday is represented by 1. @property(readonly) NSInteger weekday; @property(readonly) NSInteger firstDayOfWeekday; @property(readonly) NSInteger lastDayOfWeekday; // e.g. 2nd Tuesday of the month == 2 @property(readonly) NSInteger nthWeekday;
個人評價
無需多說,看方法名字就知道有什么作用了,回想起之前處理時間的日子。。。多么痛的領悟,果然那句話很對:磨刀不誤砍柴工。
UIView+Toast
簡介
來源: https://github.com/scalessec/Toast
使用
注意導入QuartzCore
圖片已經實例代碼源地址都有,就幾個參數
-
makeToast要顯示的內容
-
duration持續時間
-
position放置的位置
-
title標題
-
image放置的圖片
-
makeToastActivity顯示 toast
個人評價
簡單好用,清晰明了。
NYXImagesKit
簡介
來源: https://github.com/Nyx0uf/NYXImagesKit
NYXImagesKit是一個重組了多個有用的UIImage categories的iOS項目,可對圖像/圖片進行多個處理,比如篩選、模糊、優化、蒙版、調整大小、旋轉以及保存等等。同時還提供了一個UIImageView子類從URL異步加載圖片,并在下載完畢時展示圖片。
使用
首先打開NYXImagesKit.xcodeproj然后運行庫,之后把庫和頭文件導入到你的工程里面,最后要鏈接以下的框架:
-
Accelerate
-
AssetsLibrary
-
ImageIO
-
MobileCoreServices
-
QuartzCore
-
CoreImage
UIImage+Blurring
模糊效果
[myImage gaussianBlurWithBias:0];
UIImage+Masking
蒙板效果
UIImage* masked = [myImage maskWithImage:[UIImage imageNamed:@"mask.png"]];
UIImage+Resizing
重置尺寸
-
上左
-
上中
-
上右
-
下左
-
下中
-
下右
-
左中
-
右中
-
中間
UIImage* cropped = [myImage cropToSize:(CGSize){width, height} usingMode:NYXCropModeCenter];
NYXCropMode是一個枚舉類型,能在頭文件里面找到,表示不同的類型
Scaling
縮放
你有兩種方法來縮放圖片,這兩種方法都能保持原圖片比例
UIImage* scaled1 = [myImage scaleByFactor:0.5f]; UIImage* scaled2 = [myImage scaleToFitSize:(CGSize){width, height}];
UIImage+Rotating
旋轉
UIImage* rotated1 = [myImage rotateInDegrees:217.0f]; UIImage* rotated2 = [myImage rotateInRadians:M_PI_2]; UIImage* flipped1 = [myImage verticalFlip]; UIImage* flipped2 = [myImage horizontalFlip];
UIImage+Reflection
重構圖片
UIImage* reflected = [myImage reflectedImageWithHeight:myImage.size.height fromAlpha:0.0f toAlpha:0.5f];
UIImage+Enhancing
提升
[myImage autoEnhance]; [myImage redEyeCorrection];
UIImage+Saving
保存類型
這個能把圖片存到一個地址或者相冊,支持五種類型
-
BMP
-
GIF
-
JPG
-
PNG
-
TIFF
要用這個就必須導入ImageIO.framework,MobileCoreServices.framework還有AssertsLibrary.framework。
[myImage saveToURL:url type:NYXImageTypeJPEG backgroundFillColor:nil]; [myImage saveToPath:path type:NYXImageTypeTIFF backgroundFillColor:[UIColor yellowColor]]; [myImage saveToPhotosAlbum];
NYXProgressiveImageView
這個是繼承UIImageView的一個類,能異步加載圖片和緩存。
當然,我們可以使用SDWebImage。
個人評價
這個針對于圖片處理,很好很強大。
MJPopupViewController
簡介
來源: https://github.com/martinjuhasz/MJPopupViewController
這個是給UIViewController提供過渡效果的。
使用
把Source目錄下的文件夾拖入工程,然后導入QuartzCore.framework。
引入文件
#import "UIViewController+MJPopupViewController.h"
簡單添加
[self presentPopupViewController:detailViewController animationType:MJPopupViewAnimationFade];
如果要消失
[self dismissPopupViewControllerWithanimationType:MJPopupViewAnimationFade];
在實例工程中可以看到更多的使用方法。
個人評價
一個非常簡單容易使用的過渡效果,有需求的時候可以使用。
UIColor+Colours
簡介
來源: https://github.com/bennyguitar/Colours
為UIColor提供更多顏色支持
使用
cocoapods安裝,或者拖入文件
顏色過多,就不一一列舉了。
RGBA
通過數組可以取出UIColor的四個參數,都是NSNumber類型,記得他們都是0-1的數,不是0-255
NSArray *colorArray = [[UIColor seafoamColor] rgbaArray]; UIColor *newColor = [UIColor colorFromRGBAArray:colorArray];
字典也能取到值
-
kColoursRGBA_R
-
kColoursRGBA_G
-
kColoursRGBA_B
-
kColoursRGBA_A
NSDictionary *colorDict = [[UIColor seafoamColor] rgbaDictionary]; UIColor *newColor = [UIColor colorFromRGBADictionary:colorDict]; // You can also get a single component like so: NSNumber *r = colorDict[kColoursRGBA_R];
后面還有很多方法,不一一列舉了。
個人評價
實際開發中,一般 UI 設計出來各種顏色,位置都確定了,所以不好說這個用的多不多。
NSDate+Helper
簡介
來源: https://github.com/billymeltdown/nsdate-helper
這也是一個擴展NSDate的 category
使用
使用方便,stringForDisplayFromDate能非常便捷的顯示出很多信息。
NSString *displayString = [NSDate stringForDisplayFromDate:date];
這能顯示出很多信息
-
‘3:42 AM’ – 如果時間是在今天半夜
-
‘Tuesday’ – 如果時間是在這個星期
-
‘Mar 1’ – 如果日期是在今年
-
‘Mar 1, 2008’ – else ;-)
另外的方法能顯示幾天之前這樣的信息
NSDate *date = [NSDate date]; [date daysAgo]; // provides an NSComponent-based NSUInteger describing days ago. [date daysAgoAgainstMidnight]; // better version of daysAgo, works off midnight (hat-tip: "sburlot":http://github.com/sburlot) [date stringDaysAgo]; // 'Today', 'Yesterday', or 'N days ago'.
構造date formatters很糾結?缺少to_s(:db)?我也是,NSDate (Helper)有些靜態方法能夠在兩者之間轉換,而且能支持數據庫的時間戳。
NSDate *date = [NSDate dateFromString:@"2009-03-01 12:15:23"]; NSString *dbDateString = [NSDate stringFromDate:date]; // returns '2009-03-01 12:15:23'
還有
NSString *otherDateString = [NSDate stringFromDate:date withFormat:@"EEEE"]; // use any format you like
個人評價
這個也不錯,更多功能可以在.h文件里面找,命名很規范。
ObjectiveSugar
簡介
來源: https://github.com/supermarin/ObjectiveSugar
語法糖功能
使用
使用cocoapods,然后導入頭文件#import <ObjectiveSugar/ObjectiveSugar.h>
NSNumber
[@3 times:^{ NSLog(@"Hello!"); }]; // Hello! // Hello! // Hello! [@3 timesWithIndex:^(NSUInteger index) { NSLog(@"Another version with number: %d", index); }]; // Another version with number: 0 // Another version with number: 1 // Another version with number: 2 [@1 upto:4 do:^(NSInteger numbah) { NSLog(@"Current number.. %d", numbah); }]; // Current number.. 1 // Current number.. 2 // Current number.. 3 // Current number.. 4 [@7 downto:4 do:^(NSInteger numbah) { NSLog(@"Current number.. %d", numbah); }]; // Current number.. 7 // Current number.. 6 // Current number.. 5 // Current number.. 4 NSDate *firstOfDecember = [NSDate date]; // let's pretend it's 1st of December NSDate *firstOfNovember = [@30.days since:firstOfDecember]; // 2012-11-01 00:00:00 +0000 NSDate *christmas = [@7.days until:newYearsDay]; // 2012-12-25 00:00:00 +0000 NSDate *future = @24.days.fromNow; // 2012-12-25 20:49:05 +0000 NSDate *past = @1.month.ago; // 2012-11-01 20:50:28 +00:00
NSArray / NSSet
// All of these methods return a modified copy of the array. // They're not modifying the source array. NSArray *cars = @[@"Testarossa", @"F50", @"F458 Italia"]; // or NSSet [cars each:^(id object) { NSLog(@"Car: %@", object); }]; // Car: Testarossa // Car: F50 // Car: F458 Italia [cars eachWithIndex:^(id object, NSUInteger index) { NSLog(@"Car: %@ index: %i", object, index); }]; // Car: Testarossa index: 0 // Car: F50 index: 1 // Car: F458 Italia index: 2 [cars each:^(id object) { NSLog(@"Car: %@", object); } options:NSEnumerationReverse]; // Car: F458 Italia // Car: F50 // Car: Testarossa [cars eachWithIndex:^(id object, NSUInteger index) { NSLog(@"Car: %@ index: %i", object, index); } options:NSEnumerationReverse]; // Car: F458 Italia index: 2 // Car: F50 index: 1 // Car: Testarossa index: 0 [cars map:^(NSString* car) { return car.lowercaseString; }]; // testarossa, f50, f458 italia // Or, a more common example: [cars map:^(NSString* carName) { return [[Car alloc] initWithName:carName]; }]; // array of Car objects NSArray *mixedData = @[ @1, @"Objective Sugar!", @"Github", @4, @"5"]; [mixedData select:^BOOL(id object) { return ([object class] == [NSString class]); }]; // Objective Sugar, Github, 5 [mixedData reject:^BOOL(id object) { return ([object class] == [NSString class]); }]; // 1, 4 NSArray *numbers = @[ @5, @2, @7, @1 ]; [numbers sort]; // 1, 2, 5, 7 cars.sample // 458 Italia cars.sample // F50
NSArrayonly
NSArray *numbers = @[@1, @2, @3, @4, @5, @6]; // index from 2 to 4 numbers[@"2..4"]; // [@3, @4, @5] // index from 2 to 4 (excluded) numbers[@"2...4"]; // [@3, @4] // With NSRange location: 2, length: 4 numbers[@"2,4"]; // [@3, @4, @5, @6] NSValue *range = [NSValue valueWithRange:NSMakeRange(2, 4)]; numbers[range]; // [@3, @4, @5, @6] [numbers reverse]; // [@6, @5, @4, @3, @2, @1] NSArray *fruits = @[ @"banana", @"mango", @"apple", @"pear" ]; [fruits includes:@"apple"]; // YES [fruits take:3]; // banana, mango, apple [fruits takeWhile:^BOOL(id fruit) { return ![fruit isEqualToString:@"apple"]; }]; // banana, mango NSArray *nestedArray = @[ @[ @1, @2, @3 ], @[ @4, @5, @6, @[ @7, @8 ] ], @9, @10 ]; [nestedArray flatten]; // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 NSArray *abc = @[ @"a", @"b", @"c" ]; [abc join]; // abc [abc join:@"-"]; // a-b-c NSArray *mixedData = @[ @1, @"Objective Sugar!", @"Github", @4, @"5"]; [mixedData detect:^BOOL(id object) { return ([object class] == [NSString class]); }]; // Objective Sugar // TODO: Make a better / simpler example of this NSArray *landlockedCountries = @[ @"Bolivia", @"Paraguay", @"Austria", @"Switzerland", @"Hungary" ]; NSArray *europeanCountries = @[ @"France", @"Germany", @"Austria", @"Spain", @"Hungary", @"Poland", @"Switzerland" ]; [landlockedCountries intersectionWithArray:europeanCountries]; // landlockedEuropeanCountries = Austria, Switzerland, Hungary [landlockedCountries unionWithArray:europeanCountries]; // landlockedOrEuropean = Bolivia, Paraguay, Austria, Switzerland, Hungary, France, Germany, Spain, Poland [landlockedCountries relativeComplement:europeanCountries]; // nonEuropeanLandlockedCountries = Bolivia, Paraguay [europeanCountries relativeComplement:landlockedCountries]; // notLandlockedEuropeanCountries = France, Germany, Spain, Poland [landlockedCountries symmetricDifference:europeanCountries]; // uniqueCountries = Bolivia, Paraguay, France, Germany, Spain, Poland
NSMutableArray
NSMutableArray *people = @[ @"Alice", @"Benjamin", @"Christopher" ]; [people push:@"Daniel"]; // Alice, Benjamin, Christopher, Daniel [people pop]; // Daniel // people = Alice, Benjamin, Christopher [people pop:2]; // Benjamin, Christopher // people = Alice [people concat:@[ @"Evan", @"Frank", @"Gavin" ]]; // people = Alice, Evan, Frank, Gavin [people keepIf:^BOOL(id object) { return [object characterAtIndex:0] == 'E'; }]; // people = Evan
NSDictionary
NSDictionary *dict = @{ @"one" : @1, @"two" : @2, @"three" : @3 }; [dict each:^(id key, id value){ NSLog(@"Key: %@, Value: %@", key, value); }]; // Key: one, Value: 1 // Key: two, Value: 2 // Key: three, Value: 3 [dict eachKey:^(id key) { NSLog(@"Key: %@", key); }]; // Key: one // Key: two // Key: three [dict eachValue:^(id value) { NSLog(@"Value: %@", value); }]; // Value: 1 // Value: 2 // Value: 3 NSDictionary *errors = @{ @"username" : @[ @"already taken" ], @"password" : @[ @"is too short (minimum is 8 characters)", @"not complex enough" ], @"email" : @[ @"can't be blank" ]; }; [errors map:^(id attribute, id reasons) { return NSStringWithFormat(@"%@ %@", attribute, [reasons join:@", "]); }]; // username already taken // password is too short (minimum is 8 characters), not complex enough // email can't be blank [errors hasKey:@"email"] // true [errors hasKey:@"Alcatraz"] // false
NSString
NSString *sentence = NSStringWithFormat(@"This is a text-with-argument %@", @1234); // This is a text-with-argument 1234 [sentence split]; // array = this, is, a, text-with-argument, 1234 [sentence split:@"-"] // array = this is a text, with, argument 1234 [sentence containsString:@"this is a"]; // YES
C
unless(_messages) { // The body is only executed if the condition is false _messages = [self initializeMessages]; } int iterations = 10; until(iterations == 0) { // The body is executed until the condition is false // 10 9 8 7 6 5 4 3 2 1 printf("%d ", iterations); iterations--; } printf("\n"); iterations = 10; do { // The body is executed at least once until the condition is false // Will print: Executed! printf("Executed!\n"); } until(true);
個人評價
這是什么黑科技,簡直改變 OC 語法,簡化更多語法,簡直停不下來。
Kiwi
簡介
來源: https://github.com/kiwi-bdd/Kiwi
Kiwi的作用是用來過來更方便的測試程序,可讀性更高。
使用
pod "Kiwi"
詳細需要看文檔。
個人評價
又是一個黑科技,用的時候再查看文檔吧。
ViewUtils
簡介
來源: https://github.com/nicklockwood/ViewUtils
目的
擴展UIView的 category,有幾個方面:
-
載入Nib- 不需要UIViewController就能載入視圖
-
布局 - 能獨立設置位置或者寬/高
-
搜索 - 檢索子視圖,通過類,tag 或者正則表達式
-
響應者 - 找到一個 view 的第一響應者
線程安全
這個只能在主線程使用
使用
把兩個文件拖入工程
方法封裝了系統的UIView,很多都是非常實用且增加了安全性能。
還能單獨修改frame的值。
個人評價
封裝UIView的通用功能,安全性得到提高,還能單獨修改frame,增加了很多便利。
NSDate-TimeAgo
簡介
來源: https://github.com/kevinlawler/NSDate-TimeAgo
可以顯示當前時間是多久以前,不過這個已經并入了另一個庫里面
使用
導入#import "NSDate+TimeAgo.h"
NSDate *date = [[NSDate alloc] initWithTimeIntervalSince1970:0]; NSString *ago = [date timeAgo]; NSLog(@"Output is: \"%@\"", ago); 2011-11-12 17:19:25.608 Proj[0:0] Output is: "41 years ago"
還有兩種方法
-
dateTimeAgo - 返回{value} {unit} ago這種格式
-
dateTimeUntilNow - 返回昨天/今早/上個星期/這個月,沒有上面的精確但是更自然。
個人評價
如果只需要很簡單的功能,這個就能滿足,如果需要對時間更強大處理
訪問: https://github.com/MatthewYork/DateTools
iOS-FontAwesome
簡介
來源: https://github.com/alexdrone/ios-fontawesome
添加字體,還有圖片
使用
首先,在工程里面必須有FontAwesome.ttf,而且在plist文件中的UIAppFonts必須包換一個String item名字叫FontAwesome.ttf
然后再導入NSString+FontAwesome
UILabel *label = [...] label.font = [UIFont fontWithName:kFontAwesomeFamilyName size:20];
還能使用枚舉
label.text = [NSString fontAwesomeIconStringForEnum:FAGithub];
當然,最重要還是查看文檔,里面提供各種字體。
個人評價
確實很不錯,很多種類型的字體,還有圖片的,總之很給力。
NSObject-AutoDescription
簡介
來源: https://github.com/djmadcat/NSObject-AutoDescription
增加對NSArray,NSDictionary還有NSSet的描述支持
使用
#import "NAUser.h" #import "NSObject+AutoDescription.h" @implementation NAUser - (NSString *)description { return [self autoDescription]; } @end
個人評價
小而美,有需求的話可以用下。
CGRectPositioning
簡介
來源: https://github.com/mvx24/CGRectPositioning
這個是個宏文件
可以對CGRect很方便的處理
使用
看名字就能知道了,把CGRectPositioning.h導入工程,里面全是宏
個人評價
代碼布局的時候,使用這個就能很方便
總結
先從學習使用開始,到研究分析如何實現,才是大智慧。