2014/02/01 @ GREE
ެ։༻ͷObjective-Cͷॻ͖ํ@_ishkawa
View Slide
ࣗݾհ
GHFeed
ISISDiskCacheISMemoryCacheISHTTPOperationISRemoveNullISPersistentStackISMethodSwizzlingISBackGestureISRefreshControlISColumnsControllerISRevealControllerISCyclicPagesViewISFakeInterfaceOrientationISInteractiveEdgesNavigationBarISAlternativeRefreshControl
8 Pods551 Stars
τʔΫ֓ཁ
“ެ։༻”| |ଞਓ͏ίʔυ
͔ࣗ͠৮Δ͜ͱͷͳ͍ΞϓϦͷίʔυ͖ͳΑ͏ʹॻ͚͍͍(ࣗݾͰ)
͔͠͠ɺଞਓ৮ΔՄೳੑ͕͋Δ߹
✓ ୭Ͱ؆୯ʹಋೖͰ͖Δ✓ ୭Ͱਖ਼͘͠ѻ͏͜ͱ͕Ͱ͖Δ✓ ଞͷίʔυͷ෭࡞༻͕ͳ͍✓ γϯϘϧϦιʔε͕িಥ͠ͳ͍ͱ͍ͬͨ͜ͱ͕ٻΊΒΕΔͷͰɺࠓͦͷΛ͠·͢ɻ
1.ΞϓϦͱͷিಥ2.ྑ͍@interface3.ϢχοτςεττʔΫ֓ཁ
1.ΞϓϦͱͷিಥ
2छྨͷিಥ✗ γϯϘϧͷিಥ✗ Ϧιʔεͷিಥ
1.1.γϯϘϧͷিಥ
✗ Ϋϥεͷিಥ✗ ΧςΰϦͷϝιουͷিಥ✗ ఆͷিಥ
Duplicated Symbol !!!
γϯϘϧͷিಥ໋໊نଇͰ͙͜ͱ͕Ͱ͖Δʢେͷ߹ʣ
1.1.1.Ϋϥεͷ໋໊نଇ
✓ 3จࣈͷେจࣈprefixΛ͚ͭΔ@interface ISHObject : NSObject!@end
Objective-CʹΑΔϓϩάϥϛϯά (p.127)“ಠࣗͷΫϥεʹ3จࣈͷϓϨϑΟοΫεΛ͚͍ͭͯͩ͘͞ɻ ձ໊ࣾΞϓϦέʔγϣϯ໊ʹͪͳΜͩͷͰɺॏཁͳίϯϙʔωϯτʹ༝དྷ͢ΔͷͰߏ͍·ͤΜɻ”“ͨͱ͑ɺձ໊͕ࣾWhispering Oakɺ։ൃ͢ΔήʔϜͷ໊લ͕ZebraSurpriseͰ͋Εɺ WZSWOZͱ͍ͬͨϓϨϑΟοΫεʹ͢ΔͱΑ͍͔͠Ε·ͤΜɻ”
Objective-CʹΑΔϓϩάϥϛϯά (p.126)“2จࣈͷϓϨϑΟοΫεɺϑϨʔϜϫʔΫΫϥεʹ͏ͨΊɺApple͕༧͍ͯ͠·͢ɻ”✗ IS✓ NJK
1.1.2.ΧςΰϦͷϝιουͷ໋໊نଇ
✓ 3จࣈͷখจࣈprefixΛ͚ͭΔ@interface NSObject (ISHAdditions)!- (void)ish_additionalMethod;!@end
Objective-CʹΑΔϓϩάϥϛϯά (p.74)“Ϋϥε໊ͷϓϨϑΟοΫεͱಉ͡3จࣈͷจࣈྻΛɺϝιου໊ͷنʹैͬͯখจࣈʹ͠ɺΞϯμʔείΞΛ͞ΜͰϝιου໊ͱ࿈͍݁ͯͩ͘͠͞ɻ”“ಈ࡞͕ෆఆʹͳΔ͜ͱΛճආ͢ΔͨΊɺϑϨʔϜϫʔΫΫϥεʹΧςΰϦΛఆٛͯ͠ϝιουΛՃ ͢Δࡍɺ໊લʹϓϨϑΟοΫεΛ͚ͭΔΑ͏ʹ͢ΔͱΑ͍Ͱ͠ΐ͏ɻ”
App LibrarymethodA methodAͲͪΒͷmethodAͷ࣮͕࣮ߦ͞ΕΔͷ͔ෆఆ
App LibrarymethodA ish_methodA
1.1.3.ఆͷ໋໊نଇ
✓ ؔ࿈͢ΔΫϥε໊Λ಄ʹ͚ͭΔextern NSString *const ISHObjectGlobalConstant;!@interface ISHObject : NSObject!@endISHObject.hISHObject.mNSString *const ISHObjectGlobalConstant = @"Foo";!@implementation ISHObject!@end
✓ ֎෦͔Βෆཁͳఆඇެ։ʹ͢ΔISHObject.mstatic NSString *const ISHLocalConstant = @"Foo";!@implementation ISHObject!@end
1.1.4.Α͋͘ΔγϯϘϧͷিಥ
ϥΠϒϥϦ͕ґଘ͢ΔϥΠϒϥϦ͕2ॏʹϏϧυλʔήοτʹՃ͞Ε͍ͯΔLibrary A Library BLibrary C Library C
ϥΠϒϥϦ͕ϥΠϒϥϦʹґଘ͢Δ͜ͱѱ͍͜ͱͰͳ͍͕ɺར༻ଆͰিಥ͕ى͖ͳ͍Α͏ʹཹҙ͢Δ͖
✓ ֎෦ͷϥΠϒϥϦʹґଘ͢Δ͜ͱΛ໌ه͢Δ✓ CocoaPodsͳͲͷґଘཧΛਪ͢Δ
1.1.Ϧιʔεͷিಥ
దʹϥΠϒϥϦͷϦιʔεΛѻ͏ͱར༻͢ΔΞϓϦͷϦιʔεͱিಥ͢Δ
[UIImage imageNamed:@"Foo"];NSLocalizedString(@"Foo", nil);
NSBundle *bundle = [NSBundle mainBundle];NSString *filePath = [bundle pathForResource:@"foo" ofType:@"png"];[UIImage imageWithContentsOfFile:filePath];NSBundle *bundle = [NSBundle mainBundle];[bundle localizedStringForKey:@"foo" value:@"" table:nil];ϝΠϯόϯυϧͷϦιʔεΛಡΜͰ͍Δ
main bundlefoo.png foo.pngfoo.pngmain bundleʹ1ݸ͔͠ଘࡏͰ͖ͳ͍?App Library
Main bundlefoo.pngfoo.pngϥΠϒϥϦ༻ʹbundleΛͭ͘ΕղܾLibrary bundle
✓ ϝΠϯόϯυϧʹΞΫηε͢Δͷʹҙ✓ ϦιʔεϥΠϒϥϦઐ༻ͷNSBundleʹೖΕΔ
2.ྑ͍ @Interface
✓ Θ͔Γ͍͢
✓ ࣮ΛਪଌͰ͖Δ✓ ޡ༻Λͤ͞ͳ͍
@interface ISHCache : NSObject!@property (nonatomic) NSUInteger size;@property (nonatomic) NSUInteger limit;!- (id)get:(id)key;- (void)set:(id)object key:(id)key;- (void)remove:(id)key;- (void)removeAll;!@end✗
@interface ISHCache : NSObject!@property (nonatomic, readonly) NSUInteger currentSize;@property (nonatomic, readwrite) NSUInteger sizeLimit;!- (id)objectForKey:(id)key;- (void)setObject:(id)object forKey:(id)key;- (void)removeObjectForKey:(id)key;- (void)removeAllObjects;!@end✓
✓ ྑ͍ @property✓ ྑ͍௨ύλʔϯτϐοΫແݶ͋Δ͕ಛʹॏཁͳ2ͭ
2.1.ྑ͍ @property
✓ มߋͷՄ൱Λ໌֬ʹ͢Δ✓ ϥΠϒϥϦͷར༻ʹඞཁͳใ༩͑Δ✓ ϥΠϒϥϦͷར༻ʹෆཁͳใΛ༩͑ͳ͍
1.1.3.readwrite vs readonly
readwrite✓ มߋ͢Δඞཁ͕͋ΔϓϩύςΟ
readwrite͍͔ͳΔλΠϛϯάʹมߋ͞ΕͯΦϒδΣΫτͷ߹ੑΛอͯΔ͜ͱ͕·͍͠
ྫ
@interface ISHCache : NSObject!@property (nonatomic, readonly) NSUInteger currentSize;@property (nonatomic, readwrite) NSUInteger sizeLimit;!- (id)objectForKey:(id)key;- (void)setObject:(id)object forKey:(id)key;- (void)removeObjectForKey:(id)key;- (void)removeAllObjects;!@endcurrentSize < sizeLimit
- (void)setSizeLimit:(NSUInteger)sizeLimit{_sizeLimit = sizeLimit;!if (self.currentSize > sizeLimit) {[self removeAllObjects];}}currentSize < sizeLimit ΛอͭͨΊʹ͜ͷΑ͏ͳ࣮͕ظ͞ΕΔNSCache͜͏͍͏ڍಈʹͳ͍ͬͯΔ
͜͏͍࣮͕ͬͨ໘Ͱɺͦͦมߋ͢Δඞཁͳ͍߹?
readonly✓ มߋ͢Δඞཁ͕ͳ͍ϓϩύςΟ✓ มߋΛېࢭ͍ͨ͠ϓϩύςΟ
readonlyมߋΛؾʹ͠ͳͯ͘ࡁΉ
@interface ISHCache : NSObject!@property (nonatomic, readonly) NSUInteger currentSize;@property (nonatomic, readonly) NSUInteger sizeLimit;!- (instancetype)initWithSizeLimit:(NSUInteger)sizeLimit;!- (id)objectForKey:(id)key;- (void)setObject:(id)object forKey:(id)key;- (void)removeObjectForKey:(id)key;- (void)removeAllObjects;!@end
- (instancetype)initWithSizeLimit:(NSUInteger)sizeLimit{self = [super init];if (self) {_sizeLimit = sizeLimit;}return self;}มߋͰ͖ͳ͍ΘΓʹॳظԽ࣌ʹΛ͢
·ͱΊΔͱ
readwrite✓ มߋ͢Δඞཁ͕͋ΔϓϩύςΟ✓ มߋ͞Εͯ߹ੑ͕อͨΕΔreadonly✓ มߋ͢Δඞཁ͕ͳ͍ϓϩύςΟ✓ มߋΛېࢭ͍ͨ͠ϓϩύςΟ
2.2.ྑ͍௨ύλʔϯ
✓ blocks✓ delegate✓ NSNotification✓ KVO
2.2.1.blocks
✓ ௨͕ಛఆͷϝιουʹ݁ͼͭ͘✓ ௨ͷछྨ͕গͳ͍߹ద͍ͯ͠ΔέʔεUIDocument *document;[document openWithCompletionHandler:^(BOOL success) {// completed}];
✓ Ҿʹ݁ՌΛ͢✓ Τϥʔ͕ఆ͞ΕΔ߹NSError͢࡞๏GKTurnBasedMatch *match;[match acceptInviteWithCompletionHandler:^(GKTurnBasedMatch *match, NSError *error) {;}];
blocksͷߏจҟ༷ʹෳࡶ
✓ http://fuckingblocksyntax.com✓ Ѫ͕͋Εͳ͍
2.2.2.delegate
✓ ௨͕ಛఆͷΦϒδΣΫτʹ݁ͼͭ͘✓ ௨ͷछྨ͕ଟ͍✓ ௨ͷड͚ख͕1͔ͭ͠ͳ͍ద͍ͯ͠Δέʔε@optional!- (void)scrollViewDidScroll:(UIScrollView *)scrollView;- (void)scrollViewDidZoom:(UIScrollView *)scrollView;- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView;໋໊نଇʹ͍ͭͯCocoa͚ίʔσΟϯάΨΠυϥΠϯ, p.15Λࢀর
2.2.3.NSNotification
✓ ௨ͷड͚ख͕ଟ͍✓ ௨ͷૹ৴ݩͱड͚ख͕ԕ͍ͱ͖ద͍ͯ͠Δέʔεάϩʔόϧͳ௨ʹͳΔͷͰ҆қʹ࠾༻ͤͣɺઌʹdelegate, BlocksͰ࣮ݱͰ͖ͳ͍͔ݕ౼͢Δɻ
2.3.ྑ͍@interface·ͱΊ
✓ దࡐదॴreadwritereadonly✓ blocks✓ delegate✓ NSNotification✓ KVO
3.Ϣχοτςετ
3.1.ςετΛॻ͘ཧ༝
ςετΛॻ͍ͨํ͕։ൃ͕͍Օॴ͕͋Δ(σϞΞϓϦͰσόοά͢ΔΑΓ)
@interface ISHCache : NSObject!@property (nonatomic, readonly) NSUInteger currentSize;@property (nonatomic, readwrite) NSUInteger sizeLimit;!- (id)objectForKey:(id)key;- (void)setObject:(id)object forKey:(id)key;- (void)removeObjectForKey:(id)key;- (void)removeAllObjects;!@end
- (void)testSetObjectForKey{id object = [[NSObject alloc] init];id key = @"foo";![cache setObject:object forKey:key];!XCTAssertEqual(cache.currentSize, 1U);XCTAssertEqualObjects([cache objectForKey:key], object);}
✓ setObject:forKey:ͷ࣮ߦ࣌ʹsizeLimitΛ͑Δ߹ʁ✓ setObject:forKey:ͷ࣮ߦޙʹsizeLimitΛখͨ͘͞͠߹ʁ✓ removeAllObjectsͷ࣮ߦޙͷcurrentSizeʁͱ͍͏݅ΛσϞΞϓϦ্Ͱຖճσόοά͢ΔඇৗʹͭΒ͍͕ɺϢχοτςετ1ॻ͚܁Γฦ࣮͠ߦͰ͖Δɻ
ίʔυ͕յΕ͍ͯΔ͜ͱΛ͙͢ʹൃݟͰ͖ΔظʹΘͨͬͯෳਓ͕ϝϯςφϯε͢ΔϓϩάϥϜյΕ͍͢ςετϓϩάϥϜ͕ਖ਼͍͜͠ͱͷূ໌Ͱͳ͍
✓ setObject:forKey:ͷ࣮ߦ࣌ʹsizeLimitΛ͑Δ߹ʁ✓ setObject:forKey:ͷ࣮ߦޙʹsizeLimitΛখͨ͘͞͠߹ʁ✓ removeAllObjectsͷ࣮ߦޙͷcurrentSizeʁͲΕ͔1͚ͭͩյΕͨ͜ͱΛσϞΞϓϦ্Ͱݕ͢Δ͜ͱ͍͕͠ɺϢχοτςετͳΒ؆୯
ϥΠϒϥϦͷςετͷϝϦοτίετʹݟ߹͏͜ͱ͕ଟ͍ΞϓϦͱൺ༷ͯมߋ͕͘͢ͳ͍ͷͰɺςετίʔυ͕ΰϛʹͳΔ͕͍֬
ϥΠϒϥϦʹର͢ΔϢχοτςετΛॻ͘ཧ༝े
3.2.CIΛಋೖ͢Δ
͔ͤͬ͘ςετΛॻ͍ͨͷͰ࣮֬ʹ࣮ߦ͍ͨ͠git pushͷલʹඞͣςετΛ࣮ߦͰ͖Δਓؒগͳ͍
Git repository CI serverDevelopergit push git hookBuild reportCI
git push͢ΔͱΕͳ͘Ϩϙʔτ͕Β͑ΔΈ✓ ϏϧυͰ͖Δ͔ʁ✓ ςετ௨͔ͬͨʁ✓ ίʔυΧόϨοδʁ
3.2.1.CIͷηοτΞοϓ
࠷ϧʔτ: λʔϛφϧ͔ΒϏϧυͰ͖ΔΑ͏ʹ
xcodebuild clean test \-sdk iphonesimulator \-workspace ISDiskCache.xcworkspace \-scheme ISDiskCache \-configuration Debug \-destination "name=iPhone Retina (4-inch),OS=7.0"ཁ͢ΔʹΫϦʔϯͯ͠ςετͯ͠ͶͬͯίϚϯυ͋ͱ͜ΕΛCIαʔόʔʹ͑Δ͚ͩͰOK
3.2.2.WebαʔϏε
CI αʔϏε
Git repository CI serverDevelopergit push git hookBuild report
GitHubDevelopergit push git hookBuild report
✓ public repositoryແྉ✓ GitHub࿈ܞ✓ status badge
֘ίϛοτͷϏϧυͷঢ়ଶ͕Θ͔Δ !!!
ίʔυΧόϨοδදࣔαʔϏε
֘ίϛοτͷίʔυΧόϨοδ͕Θ͔Δ
GitHubDevelopergit push git hookBuild reportCoverage report
྆ํηοτΞοϓ͢Δͱ͜Μͳײ͡
https://github.com/ishkawa/ISDiskCache/
3.3.Ϣχοτςετ·ͱΊ
✓ ςετͷಋೖͰ։ൃ͕͘ͳΔՕॴ͋Δ✓ յΕͨՕॴΛൃݟ͘͢͠ͳΔ✓ ϥΠϒϥϦͷςετΞϓϦͷςετΑΓߴCP✓ CIͰৗʹςετ͞Εͨঢ়ଶΛอͭ͜ͱ͕Ͱ͖Δ
·ͱΊ
1.ಋೖઌͷΞϓϦͱͷিಥʹؾΛ͚ͭΔ2.ଞਓʹΘ͔Γ͍͢ΠϯλʔϑΣʔεʹ͢Δ3.࣭͕མͪʹ͍͘ΈΛಋೖ͢ΔϥΠϒϥϦΛެ։͢Δͱ͖….