From 80ab7ce2beac4c9ac2f19c1bdf97d1f7305b6d95 Mon Sep 17 00:00:00 2001 From: BB9z Date: Tue, 22 May 2018 16:44:21 +0800 Subject: [PATCH 1/6] New UIPickerView extension. --- RFKit.h | 2 +- RFKit.podspec | 9 +++++- RFKitDefaultCategories.h | 1 + Test/RFKit.xcodeproj/project.pbxproj | 4 +++ Test/Supporting Files/OCBridgingHeader.h | 1 + Test/Test/Swift/SwiftNameTest.swift | 5 ++++ Test/Test/iOS/UIPickerView+RFKitTests.m | 35 ++++++++++++++++++++++++ category/UIKit/UIPickerView+RFKit.h | 29 ++++++++++++++++++++ category/UIKit/UIPickerView+RFKit.m | 12 ++++++++ 9 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 Test/Test/iOS/UIPickerView+RFKitTests.m create mode 100644 category/UIKit/UIPickerView+RFKit.h create mode 100644 category/UIKit/UIPickerView+RFKit.m diff --git a/RFKit.h b/RFKit.h index 503a9df..19ea182 100644 --- a/RFKit.h +++ b/RFKit.h @@ -10,7 +10,7 @@ */ #ifndef RFKit_h -#define RFKit_h 2.1 +#define RFKit_h 2.2 #import "RFRuntime.h" #import "RFGeometry.h" diff --git a/RFKit.podspec b/RFKit.podspec index b88fee0..dd74c7d 100644 --- a/RFKit.podspec +++ b/RFKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'RFKit' - s.version = '2.1.0' + s.version = '2.2.0' s.summary = 'Tool kit for daily cocoa development.' s.homepage = 'https://github.com/BB9z/RFKit' s.license = { :type => 'MIT', :file => 'LICENSE' } @@ -135,6 +135,7 @@ Pod::Spec.new do |s| ssp.ios.dependency 'RFKit/Category/UIAlertView' ssp.ios .dependency 'RFKit/Category/NSLayoutConstraint' ssp.tvos.dependency 'RFKit/Category/NSLayoutConstraint' + ssp.ios .dependency 'RFKit/Category/UIPickerView' ssp.ios .dependency 'RFKit/Category/UIScrollView+RFScrolling' ssp.tvos.dependency 'RFKit/Category/UIScrollView+RFScrolling' ssp.ios .dependency 'RFKit/Category/UISearchBar' @@ -267,6 +268,12 @@ Pod::Spec.new do |s| ssp.dependency 'RFKit/Category/NSArray' ssp.source_files = 'category/UIKit/UINavigationController+*' end + + ss.subspec 'UIPickerView' do |ssp| + ssp.ios.deployment_target = '6.0' + ssp.dependency 'RFKit/Foundation' + ssp.source_files = 'category/UIKit/UIPickerView+*' + end ss.subspec 'UIResponder' do |ssp| ssp.ios.deployment_target = '6.0' diff --git a/RFKitDefaultCategories.h b/RFKitDefaultCategories.h index 7a39463..7767ee4 100644 --- a/RFKitDefaultCategories.h +++ b/RFKitDefaultCategories.h @@ -30,6 +30,7 @@ #import "UIDevice+RFKit.h" #import "UIImage+RFKit.h" #import "UINavigationController+RFKit.h" +//#import "UIPickerView+RFKit.h" #import "UIResponder+RFKit.h" //#import "UIScrollView+RFScrolling.h" //#import "UISearchBar+RFKit.h" diff --git a/Test/RFKit.xcodeproj/project.pbxproj b/Test/RFKit.xcodeproj/project.pbxproj index 11455ec..b4a0df7 100644 --- a/Test/RFKit.xcodeproj/project.pbxproj +++ b/Test/RFKit.xcodeproj/project.pbxproj @@ -57,6 +57,7 @@ D5CE8EC5203FADC6000F1C0E /* NSBundle+RFKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D5CE8EC4203FADC6000F1C0E /* NSBundle+RFKitTests.m */; }; D5CE8EC6203FADC6000F1C0E /* NSBundle+RFKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D5CE8EC4203FADC6000F1C0E /* NSBundle+RFKitTests.m */; }; D5CE8EC7203FADC6000F1C0E /* NSBundle+RFKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D5CE8EC4203FADC6000F1C0E /* NSBundle+RFKitTests.m */; }; + D5D6630020B40A4200E55EEB /* UIPickerView+RFKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D5D662FF20B40A4200E55EEB /* UIPickerView+RFKitTests.m */; }; D5F50AC22035E3BA0054518C /* NSDateFormatter+RFKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D5F50AC12035E3BA0054518C /* NSDateFormatter+RFKitTests.m */; }; D5F50AC32035E3BA0054518C /* NSDateFormatter+RFKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D5F50AC12035E3BA0054518C /* NSDateFormatter+RFKitTests.m */; }; D5F50AC42035E3BA0054518C /* NSDateFormatter+RFKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D5F50AC12035E3BA0054518C /* NSDateFormatter+RFKitTests.m */; }; @@ -117,6 +118,7 @@ D5C6F59D20328F7000D1E8DF /* Target_watchOS.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Target_watchOS.m; sourceTree = ""; }; D5C6F5A72032D39500D1E8DF /* NSArray+RFKitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSArray+RFKitTests.m"; sourceTree = ""; }; D5CE8EC4203FADC6000F1C0E /* NSBundle+RFKitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSBundle+RFKitTests.m"; sourceTree = ""; }; + D5D662FF20B40A4200E55EEB /* UIPickerView+RFKitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIPickerView+RFKitTests.m"; sourceTree = ""; }; D5F50AC12035E3BA0054518C /* NSDateFormatter+RFKitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDateFormatter+RFKitTests.m"; sourceTree = ""; }; FB69B17BD7CB0E4ADC9CB6BD /* Pods-Test-tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Test-tvOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-Test-tvOS/Pods-Test-tvOS.release.xcconfig"; sourceTree = ""; }; FEAF0D436A19807484DA91EC /* libPods-Target-watchOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Target-watchOS.a"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -169,6 +171,7 @@ D513B0E62031917C00C62520 /* iOS */ = { isa = PBXGroup; children = ( + D5D662FF20B40A4200E55EEB /* UIPickerView+RFKitTests.m */, D513B0E92031917C00C62520 /* Info.plist */, D57E75D3203EFCB6001BB427 /* UIView+RFKitTests.m */, ); @@ -606,6 +609,7 @@ D5722FB1203DAC4800C610E2 /* NSError+RFKitTests.m in Sources */, D513B0FF2031D0BB00C62520 /* NSFileManager+RFKitTests.m in Sources */, D57E75C6203E49CF001BB427 /* NSJSONSerialization+RFKitTests.m in Sources */, + D5D6630020B40A4200E55EEB /* UIPickerView+RFKitTests.m in Sources */, D594688220327D8F00A1AE3D /* NSObject+RFKitTests.m in Sources */, D57E75CC203E9C0A001BB427 /* NSString+RFKitTests.m in Sources */, D57E75D0203EB350001BB427 /* NSURL+RFKitTests.m in Sources */, diff --git a/Test/Supporting Files/OCBridgingHeader.h b/Test/Supporting Files/OCBridgingHeader.h index 322f329..df8ec54 100644 --- a/Test/Supporting Files/OCBridgingHeader.h +++ b/Test/Supporting Files/OCBridgingHeader.h @@ -18,6 +18,7 @@ #import #import #import +#import #import #import #import diff --git a/Test/Test/Swift/SwiftNameTest.swift b/Test/Test/Swift/SwiftNameTest.swift index 408ed62..e31c38b 100644 --- a/Test/Test/Swift/SwiftNameTest.swift +++ b/Test/Test/Swift/SwiftNameTest.swift @@ -161,6 +161,11 @@ class SwiftNameTest: XCTestCase { nav.setTopView(nil, animated: false) } + func testUIPickerView() { + let v = UIPickerView() + v.rf_selectRow(0, inComponent: 0, animated: false) + } + func testUIResponder() { let v = UIView() let _ = v.viewController diff --git a/Test/Test/iOS/UIPickerView+RFKitTests.m b/Test/Test/iOS/UIPickerView+RFKitTests.m new file mode 100644 index 0000000..7824a34 --- /dev/null +++ b/Test/Test/iOS/UIPickerView+RFKitTests.m @@ -0,0 +1,35 @@ +// +// UIPickerView+RFKitTests.m +// RFKit +// +// Created by BB9z on 2018/5/22. +// Copyright © 2018 RFUI. All rights reserved. +// + +#import +#import "UIPickerView+RFKit.h" + +@interface RTUIPickerView : XCTestCase < + UIPickerViewDataSource +> + +@end + +@implementation RTUIPickerView + +- (void)testSelectRow { + UIPickerView *p = UIPickerView.alloc.init; + p.dataSource = self; + XCTAssertThrows([p selectRow:-1 inComponent:NSNotFound animated:YES]); + XCTAssertNoThrow([p rf_selectRow:5 inComponent:5 animated:YES]); +} + +- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { + return 2; +} + +- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { + return 2; +} + +@end diff --git a/category/UIKit/UIPickerView+RFKit.h b/category/UIKit/UIPickerView+RFKit.h new file mode 100644 index 0000000..d411f12 --- /dev/null +++ b/category/UIKit/UIPickerView+RFKit.h @@ -0,0 +1,29 @@ +/*! + UIPickerView extension + RFKit + + Copyright (c) 2018 BB9z + https://github.com/BB9z/RFKit + + The MIT License (MIT) + http://www.opensource.org/licenses/mit-license.php + */ +#import "RFFoundation.h" +#import + +@interface UIPickerView (RFKit) + +/** + Safely selects a row in a specified component of the picker view. + + If any index is not in the legal range, this method do nothing. + + @param row A zero-indexed number identifying a row of component. + + @param component A zero-indexed number identifying a component of the picker view. + + @param animated `YES` to animate the selection by spinning the wheel (component) to the new value; if you specify `NO`, the new selection is shown immediately. + */ +- (void)rf_selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated API_AVAILABLE(ios(2.0)); + +@end diff --git a/category/UIKit/UIPickerView+RFKit.m b/category/UIKit/UIPickerView+RFKit.m new file mode 100644 index 0000000..a2504ab --- /dev/null +++ b/category/UIKit/UIPickerView+RFKit.m @@ -0,0 +1,12 @@ + +#import "UIPickerView+RFKit.h" + +@implementation UIPickerView (RFKit) + +- (void)rf_selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated { + if (component < 0 || component >= self.numberOfComponents) return; + if (row <0 || row >= [self numberOfRowsInComponent:component]) return; + [self selectRow:row inComponent:component animated:animated]; +} + +@end From 099b6d46dd5dfcacc09d9a7e3ddc3b317455d42a Mon Sep 17 00:00:00 2001 From: BB9z Date: Tue, 22 May 2018 17:13:58 +0800 Subject: [PATCH 2/6] Add RFDebugger(). --- dout.h | 12 ++++++++++-- dout.m | 13 +++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/dout.h b/dout.h index aac6606..f375506 100755 --- a/dout.h +++ b/dout.h @@ -10,7 +10,7 @@ */ #ifndef DOUT_H -#define DOUT_H 2.10 +#define DOUT_H 2.11 #import "RFRuntime.h" @@ -193,8 +193,16 @@ #define _dout_warning(...) #define _dout_error(...) +/** + Debugger() for all platform. + + This methiod simulate Debugger() behavior by throwing objective-c exception. + So you should set an exception breakpoint to use it. + */ +FOUNDATION_EXPORT void RFDebugger(NSString *_Nullable format, ...) NS_FORMAT_FUNCTION(1, 2); + void DoutLogString(NSString *string); -NSString * DoutCurrentThreadOrQueueName(void); +NSString *DoutCurrentThreadOrQueueName(void); void _dout_log_config(void); #endif diff --git a/dout.m b/dout.m index 6814ff9..c8b0933 100755 --- a/dout.m +++ b/dout.m @@ -2,6 +2,19 @@ #import "dout.h" #import +void RFDebugger(NSString *format, ...) { + if (format) { + va_list args; + va_start(args, format); + NSLogv(format, args); + va_end(args); + } + @try { + @throw [NSException exceptionWithName:@"pause" reason:@"debug" userInfo:nil]; + } + @catch (__unused NSException *exception) { } +} + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunreachable-code" From cab49fe9a525a0b73146f55601c9ed7dc37fed82 Mon Sep 17 00:00:00 2001 From: BB9z Date: Tue, 22 May 2018 19:45:27 +0800 Subject: [PATCH 3/6] #ci lint takes too much time. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index faf4f25..24bd8ca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,6 @@ matrix: env: RFCI_TASK="Xcode8" before_install: - pod repo update master --silent -script: ./.travis.sh MAIN +script: travis_wait ./.travis.sh MAIN after_success: ./.travis.sh SUCCESS after_failure: ./.travis.sh FAILURE From 369ed1aca08dac5a01f98ad55a439624ba851030 Mon Sep 17 00:00:00 2001 From: BB9z Date: Sun, 10 Jun 2018 17:38:46 +0800 Subject: [PATCH 4/6] RFFoundation, NS_STRING_ENUM, NS_EXTENSIBLE_STRING_ENUM guard define. --- RFFoundation.h | 46 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/RFFoundation.h b/RFFoundation.h index 407fa4b..b8284b1 100644 --- a/RFFoundation.h +++ b/RFFoundation.h @@ -21,12 +21,17 @@ #pragma mark Xcode 9 -// Memo: +// Xcode 9.3 +// SE-0075: #if canImport() +// SE-0190: #if targetEnvironment() + +// Xcode 9.0 +// SE–0168: multiline string literals """ +// SE–0161: type-safe key path literals \BaseType.propertyName // 7184689: @available in Objective-C +// 21359084: #pragma pack #pragma mark Xcode 8 -// Xcode 8, with macOS 10.12 and iOS 10 SDK -// https://developer.apple.com/library/content/releasenotes/Miscellaneous/RN-Foundation-OSX10.12/index.html #ifndef NS_NOESCAPE # if __has_attribute(noescape) @@ -36,6 +41,14 @@ # endif #endif +#ifndef NS_STRING_ENUM +# define NS_STRING_ENUM +#endif + +#ifndef NS_EXTENSIBLE_STRING_ENUM +# define NS_EXTENSIBLE_STRING_ENUM +#endif + // API available #ifndef API_AVAILABLE # define API_AVAILABLE(...) @@ -61,14 +74,25 @@ # define TARGET_OS_TV 0 #endif -// Memo: -// 23891898: class properties -// 26921435: __swift__ macro +// Xcode 8, with macOS 10.12 and iOS 10 SDK +// https://developer.apple.com/library/content/releasenotes/Miscellaneous/RN-Foundation-OSX10.12/index.html + +// Xcode 8.3 +// SE-0141, SR-2709: @available + +// Xcode 8.1 // 28694859: __weak in MRC +// 26921435: __swift__ macro + +// Xcode 8.0 +// 23891898: class properties +// SE-0064: property getter or setter in #selector +// SE-0062: #keyPath +// SE-0034: #sourceLocation #pragma mark Xcode 7 -// Xcode 7: 19240897 +// Xcode 7.0: 19240897 #ifndef NS_SWIFT_NAME # define NS_SWIFT_NAME(...) #endif @@ -76,6 +100,14 @@ // Xcode release note // https://developer.apple.com/library/content/releasenotes/DeveloperTools/RN-Xcode/Chapters/Introduction.html +// Xcode 7.3 +// SE-0020: #if swift +// SE-0028: #file, #line, #column, #function +// SE-0022: #selector + +// Xcode 7.0 +// 19589424: __kindof + #pragma mark Unknow // Introduction version Unknow From 9a5f1f7c00535ded6ca97bdbfeec201303fa6b8d Mon Sep 17 00:00:00 2001 From: BB9z Date: Sun, 10 Jun 2018 17:50:35 +0800 Subject: [PATCH 5/6] #doc update changelog. --- Changelog.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Changelog.md b/Changelog.md index 997cae5..04051b5 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,12 @@ # RFKit Changelog +## 2.2.0 + +* API Enhancements: + * RFFoundation, add guard define for `NS_STRING_ENUM` and `NS_EXTENSIBLE_STRING_ENUM`. + * dout, add `RFDebugger()` as an alternative to Debugger(). + * New UIPickerView+RFKit, with `rf_selectRow:inComponent:animated:`. + ## 2.1.0 * **Breaking Changes:** From da2d57bd66706bce2822801dcf6955cbecded19e Mon Sep 17 00:00:00 2001 From: BB9z Date: Sun, 10 Jun 2018 18:20:07 +0800 Subject: [PATCH 6/6] dout, add missing nullability specifiers. --- dout.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dout.h b/dout.h index f375506..5112bf8 100755 --- a/dout.h +++ b/dout.h @@ -199,10 +199,10 @@ This methiod simulate Debugger() behavior by throwing objective-c exception. So you should set an exception breakpoint to use it. */ -FOUNDATION_EXPORT void RFDebugger(NSString *_Nullable format, ...) NS_FORMAT_FUNCTION(1, 2); +FOUNDATION_EXPORT void RFDebugger(NSString *__nullable format, ...) NS_FORMAT_FUNCTION(1, 2); -void DoutLogString(NSString *string); -NSString *DoutCurrentThreadOrQueueName(void); +void DoutLogString(NSString *__nullable string); +NSString *__nonnull DoutCurrentThreadOrQueueName(void); void _dout_log_config(void); #endif