diff --git a/.gitignore b/.gitignore index be20dd7b348..658fc447a0c 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,7 @@ DerivedData # Third Party /sdk + +# Generated +/target +/site diff --git a/FirebaseUI.podspec b/FirebaseUI.podspec index a0dec6735c8..ad4ff283944 100644 --- a/FirebaseUI.podspec +++ b/FirebaseUI.podspec @@ -1,17 +1,18 @@ Pod::Spec.new do |s| s.name = "FirebaseUI" - s.version = "0.1.2" + s.version = "0.2.0" s.summary = "UI binding libraries for Firebase." s.homepage = "https://github.com/firebase/FirebaseUI-iOS" s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { "Firebase" => "support@firebase.com" } - s.source = { :git => "https://github.com/firebase/FirebaseUI-iOS.git", :tag => 'v0.1.2' } + s.social_media_url = "https://twitter.com/firebase" + s.source = { :git => "https://github.com/firebase/FirebaseUI-iOS.git", :tag => 'v0.2.0' } s.source_files = "FirebaseUI/**/*.{h,m}" - s.dependency 'Firebase', '~> 2.3' + s.dependency "Firebase", "~> 2.2" s.platform = :ios - s.ios.deployment_target = '7.0' + s.ios.deployment_target = "7.0" s.libraries = "c++", "icucore" - s.ios.framework = "CFNetwork", "Security", "Firebase", "SystemConfiguration", "UIKit", "Foundation" - s.xcconfig = { 'FRAMEWORK_SEARCH_PATHS' => '"$(PODS_ROOT)/Firebase"'} + s.ios.framework = "UIKit", "Firebase", "Security", "CFNetwork", "SystemConfiguration" + s.xcconfig = { 'FRAMEWORK_SEARCH_PATHS' => '"$(PODS_ROOT)/Firebase"' } s.requires_arc = true end diff --git a/FirebaseUI.xcodeproj/project.pbxproj b/FirebaseUI.xcodeproj/project.pbxproj index e3cf091fb82..e5c7988805e 100644 --- a/FirebaseUI.xcodeproj/project.pbxproj +++ b/FirebaseUI.xcodeproj/project.pbxproj @@ -33,6 +33,8 @@ D8B6ACF81B583D3E005CDDB2 /* FirebaseUI.h in Headers */ = {isa = PBXBuildFile; fileRef = D8B6ACEB1B583C33005CDDB2 /* FirebaseUI.h */; settings = {ATTRIBUTES = (Public, ); }; }; D8B6ACF91B583D3E005CDDB2 /* FirebaseDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = D8B6ACED1B583C33005CDDB2 /* FirebaseDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; D8B6ACFB1B583D48005CDDB2 /* FirebaseArray.h in Headers */ = {isa = PBXBuildFile; fileRef = D8B6ACEC1B583C33005CDDB2 /* FirebaseArray.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D8DA10F11B7AC50400D00954 /* FirebaseCollectionViewDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = D8DA10F01B7AC50400D00954 /* FirebaseCollectionViewDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D8DF55621B742DB40030E996 /* FirebaseCollectionViewDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = D8DF55611B742DB40030E996 /* FirebaseCollectionViewDataSource.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -68,13 +70,10 @@ D8B6ACEF1B583C41005CDDB2 /* FirebaseArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FirebaseArray.m; path = Implementation/FirebaseArray.m; sourceTree = ""; }; D8B6ACF11B583C41005CDDB2 /* FirebaseTableViewDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FirebaseTableViewDataSource.m; path = Implementation/FirebaseTableViewDataSource.m; sourceTree = ""; }; D8B6ACF21B583C41005CDDB2 /* FirebaseDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FirebaseDataSource.m; path = Implementation/FirebaseDataSource.m; sourceTree = ""; }; - D8B6AD971B58D45F005CDDB2 /* libc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libc++.dylib"; path = "usr/lib/libc++.dylib"; sourceTree = SDKROOT; }; - D8B6AD991B58D486005CDDB2 /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = usr/lib/libicucore.dylib; sourceTree = SDKROOT; }; - D8B6AD9B1B58D48C005CDDB2 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - D8B6AD9D1B58D494005CDDB2 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; - D8B6AD9F1B58D49E005CDDB2 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; D8C579A61B57349000899F86 /* libFirebaseUI.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFirebaseUI.a; sourceTree = BUILT_PRODUCTS_DIR; }; D8C579BB1B5837DF00899F86 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + D8DA10F01B7AC50400D00954 /* FirebaseCollectionViewDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FirebaseCollectionViewDataSource.h; path = API/FirebaseCollectionViewDataSource.h; sourceTree = ""; }; + D8DF55611B742DB40030E996 /* FirebaseCollectionViewDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FirebaseCollectionViewDataSource.m; path = Implementation/FirebaseCollectionViewDataSource.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -95,11 +94,6 @@ isa = PBXGroup; children = ( D8124F401B72A90C003441AD /* Firebase.framework */, - D8B6AD9F1B58D49E005CDDB2 /* SystemConfiguration.framework */, - D8B6AD9D1B58D494005CDDB2 /* Security.framework */, - D8B6AD9B1B58D48C005CDDB2 /* CFNetwork.framework */, - D8B6AD991B58D486005CDDB2 /* libicucore.dylib */, - D8B6AD971B58D45F005CDDB2 /* libc++.dylib */, D8B6ACE61B583877005CDDB2 /* Foundation.framework */, D8C579BB1B5837DF00899F86 /* UIKit.framework */, ); @@ -114,6 +108,7 @@ D8B6ACEC1B583C33005CDDB2 /* FirebaseArray.h */, D8B6ACED1B583C33005CDDB2 /* FirebaseDataSource.h */, D8B6ACEE1B583C33005CDDB2 /* FirebaseTableViewDataSource.h */, + D8DA10F01B7AC50400D00954 /* FirebaseCollectionViewDataSource.h */, ); name = API; sourceTree = ""; @@ -121,6 +116,7 @@ D8B6ACEA1B5839F7005CDDB2 /* Implementation */ = { isa = PBXGroup; children = ( + D8DF55611B742DB40030E996 /* FirebaseCollectionViewDataSource.m */, D8B6ACEF1B583C41005CDDB2 /* FirebaseArray.m */, D8B6ACF21B583C41005CDDB2 /* FirebaseDataSource.m */, D8B6ACF11B583C41005CDDB2 /* FirebaseTableViewDataSource.m */, @@ -165,6 +161,7 @@ D8B6ACF91B583D3E005CDDB2 /* FirebaseDataSource.h in Headers */, D8784C401B719F280025587E /* FirebaseArrayDelegate.h in Headers */, D8124F431B72B347003441AD /* FirebaseTableViewDataSource.h in Headers */, + D8DA10F11B7AC50400D00954 /* FirebaseCollectionViewDataSource.h in Headers */, D8B6ACFB1B583D48005CDDB2 /* FirebaseArray.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -240,7 +237,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# Using the default Ray Wenderlich build script http://www.raywenderlich.com/65964/create-a-framework-for-ios\nset -e\n\nexport FRAMEWORK_LOCN=\"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework\"\n\n# Create the path to the real Headers die\nmkdir -p \"${FRAMEWORK_LOCN}/Versions/A/Headers\"\n\n# Create the required symlinks\n/bin/ln -sfh A \"${FRAMEWORK_LOCN}/Versions/Current\"\n/bin/ln -sfh Versions/Current/Headers \"${FRAMEWORK_LOCN}/Headers\"\n/bin/ln -sfh \"Versions/Current/${PRODUCT_NAME}\" \\\n\"${FRAMEWORK_LOCN}/${PRODUCT_NAME}\"\n\n# Copy the public headers into the framework\n/bin/cp -a \"${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/\" \\\n\"${FRAMEWORK_LOCN}/Versions/A/Headers\""; + shellScript = "set -e\n\nexport FRAMEWORK_LOCN=\"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework\"\n\n# Create the path to the real Headers die\nmkdir -p \"${FRAMEWORK_LOCN}/Versions/A/Headers\"\n\n# Create the required symlinks\n/bin/ln -sfh A \"${FRAMEWORK_LOCN}/Versions/Current\"\n/bin/ln -sfh Versions/Current/Headers \"${FRAMEWORK_LOCN}/Headers\"\n/bin/ln -sfh \"Versions/Current/${PRODUCT_NAME}\" \\\n\"${FRAMEWORK_LOCN}/${PRODUCT_NAME}\"\n\n# Copy the public headers into the framework\n/bin/cp -a \"${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/\" \\\n\"${FRAMEWORK_LOCN}/Versions/A/Headers\""; }; D8B6ADA91B58DCF9005CDDB2 /* MultiPlatform Build */ = { isa = PBXShellScriptBuildPhase; @@ -263,6 +260,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + D8DF55621B742DB40030E996 /* FirebaseCollectionViewDataSource.m in Sources */, D8B6ACF61B583C41005CDDB2 /* FirebaseDataSource.m in Sources */, D8B6ACF31B583C41005CDDB2 /* FirebaseArray.m in Sources */, D8124F421B72B344003441AD /* FirebaseTableViewDataSource.m in Sources */, @@ -283,6 +281,7 @@ D8B6ADA51B58DCDD005CDDB2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_MODULES_AUTOLINK = YES; OTHER_LDFLAGS = ""; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -291,6 +290,7 @@ D8B6ADA61B58DCDD005CDDB2 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_MODULES_AUTOLINK = YES; OTHER_LDFLAGS = ""; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -377,17 +377,19 @@ D8C579B01B57349000899F86 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_MODULES_AUTOLINK = YES; DEAD_CODE_STRIPPING = NO; + DEFINES_MODULE = YES; FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", - "$(PROJECT_DIR)/sdk", "$(DEVELOPER_FRAMEWORKS_DIR)", - "$(SDKROOT)/Developer/Library/Frameworks", + "$(PROJECT_DIR)/sdk", ); GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_PEDANTIC = YES; IPHONEOS_DEPLOYMENT_TARGET = 7.1; - OTHER_LDFLAGS = "-ObjC"; + OTHER_LDFLAGS = ""; PRODUCT_NAME = "$(TARGET_NAME)"; PUBLIC_HEADERS_FOLDER_PATH = "include/$(PROJECT_NAME)"; SKIP_INSTALL = YES; @@ -398,17 +400,19 @@ D8C579B11B57349000899F86 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_MODULES_AUTOLINK = YES; DEAD_CODE_STRIPPING = NO; + DEFINES_MODULE = YES; FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", - "$(PROJECT_DIR)/sdk", "$(DEVELOPER_FRAMEWORKS_DIR)", - "$(SDKROOT)/Developer/Library/Frameworks", + "$(PROJECT_DIR)/sdk", ); GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_PEDANTIC = YES; IPHONEOS_DEPLOYMENT_TARGET = 7.1; - OTHER_LDFLAGS = "-ObjC"; + OTHER_LDFLAGS = ""; PRODUCT_NAME = "$(TARGET_NAME)"; PUBLIC_HEADERS_FOLDER_PATH = "include/$(PROJECT_NAME)"; SKIP_INSTALL = YES; diff --git a/FirebaseUI/API/FirebaseArray.h b/FirebaseUI/API/FirebaseArray.h index c430e3c9edc..132bf7993b9 100644 --- a/FirebaseUI/API/FirebaseArray.h +++ b/FirebaseUI/API/FirebaseArray.h @@ -32,7 +32,11 @@ @class FQuery; @class Firebase; +@class FDataSnapshot; +/** + * FirebaseArray provides an array structure that is synchronized with a Firebase reference or query. It is useful for building custom data structures or sources, and provides the base for FirebaseDataSource. + */ @interface FirebaseArray : NSObject /** @@ -48,7 +52,7 @@ /** * The delegate object that array changes are surfaced to. */ -@property (strong, nonatomic) NSMutableArray *snapshots; +@property (strong, nonatomic) NSMutableArray *snapshots; #pragma mark - #pragma mark Initializer methods diff --git a/FirebaseUI/API/FirebaseCollectionViewDataSource.h b/FirebaseUI/API/FirebaseCollectionViewDataSource.h new file mode 100644 index 00000000000..1e0e7ba4a90 --- /dev/null +++ b/FirebaseUI/API/FirebaseCollectionViewDataSource.h @@ -0,0 +1,127 @@ +/* + * Firebase UI Bindings iOS Library + * + * Copyright © 2015 Firebase - All Rights Reserved + * https://www.firebase.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binaryform must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY FIREBASE AS IS AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL FIREBASE BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +#import "FirebaseDataSource.h" + +@class Firebase; + +/** + * FirebaseCollectionViewDataSource provides an class that conforms to the UICollcetionViewDataSource protocol which allows UICollectionViews to implement FirebaseCollectionViewDataSource in order to provide a UICollectionView synchronized to a Firebase reference or query. In addition to handling all Firebase child events (added, changed, removed, moved), FirebaseCollectionViewDataSource handles UITableViewCell creation, either with the default UICollectionViewCell, prototype cells, custom UICollectionViewCell subclasses, or custom XIBs, and provides a simple [FirebaseCollectionViewDataSource populateCellWithBlock:] method which allows developers to populate the cells created for them with desired data from Firebase. + */ +@interface FirebaseCollectionViewDataSource : FirebaseDataSource + +/** + * The model class to coerce FDataSnapshots to (if desired). For instance, if the modelClass is set to [Message class] in Obj-C or Message.self in Swift, then objects of type Message will be returned instead of type FDataSnapshot. + */ +@property (strong, nonatomic, nonnull) Class modelClass; + +/** + * The reuse identifier for cells in the UICollectionView. + */ +@property (strong, nonatomic, nonnull) NSString *reuseIdentifier; + +/** + * The UICollectionView instance that operations (inserts, removals, moves, etc.) are performed against. + */ +@property (strong, nonatomic, nonnull) UICollectionView *collectionView; + +/** + * The callback to populate a subclass of UICollectionViewCell with an object provided by the datasource. + */ +@property (strong, nonatomic, nonnull) void(^populateCell)(__nonnull __kindof UICollectionViewCell *cell, __nonnull __kindof NSObject *object); + +/** + * Initialize an instance of FirebaseCollectionViewDataSource that populates UICollectionViewCells with FDataSnapshots. + * @param ref A Firebase reference to bind the datasource to + * @param identifier A string to use as a CellReuseIdentifier + * @param collectionView An instance of a UICollectionView to bind to + * @return An instance of FirebaseCollectionViewDataSource that populates UICollectionViewCells with FDataSnapshots + */ +- (nonnull instancetype)initWithRef:(nonnull Firebase *)ref reuseIdentifier:(nonnull NSString *)identifier view:(nonnull UICollectionView *)collectionView; + +/** + * Initialize an instance of FirebaseCollectionViewDataSource that populates a custom subclass of UICollectionViewCell with FDataSnapshots. + * @param ref A Firebase reference to bind the datasource to + * @param cell A subclass of UICollectionViewCell used to populate the UICollectionView, defaults to UICollectionViewCell if nil + * @param identifier A string to use as a CellReuseIdentifier + * @param collectionView An instance of a UICollectionView to bind to + * @return An instance of FirebaseCollectionViewDataSource that populates a custom subclass of UICollectionViewCell with FDataSnapshots + */ +- (nonnull instancetype)initWithRef:(nonnull Firebase *)ref cellClass:(nullable Class)cell reuseIdentifier:(nonnull NSString *)identifier view:(nonnull UICollectionView *)collectionView; + +/** + * Initialize an instance of FirebaseCollectionViewDataSource that populates a custom xib with FDataSnapshots. + * @param ref A Firebase reference to bind the datasource to + * @param nibName The name of a xib file to create the layout for a UICollectionViewCell + * @param identifier A string to use as a CellReuseIdentifier + * @param collectionView An instance of a UICollectionView to bind to + * @return An instance of FirebaseCollectionViewDataSource that populates a custom xib with FDataSnapshots + */ +- (nonnull instancetype)initWithRef:(nonnull Firebase *)ref nibNamed:(nonnull NSString *)nibName reuseIdentifier:(nonnull NSString *)identifier view:(nonnull UICollectionView *)collectionView; + +/** + * Initialize an instance of FirebaseCollectionViewDataSource that populates UICollectionViewCells with a custom model class. + * @param ref A Firebase reference to bind the datasource to + * @param model A custom class that FDataSnapshots are coerced to, defaults to FDataSnapshot if nil + * @param identifier A string to use as a CellReuseIdentifier + * @param collectionView An instance of a UICollectionView to bind to + * @return An instance of FirebaseCollectionViewDataSource that populates UICollectionViewCells with a custom model class + */ +- (nonnull instancetype)initWithRef:(nonnull Firebase *)ref modelClass:(nullable Class)model reuseIdentifier:(nonnull NSString *)identifier view:(nonnull UICollectionView *)collectionView; + +/** + * Initialize an instance of FirebaseCollectionViewDataSource that populates a custom subclass of UICollectionViewCell with a custom model class. + * @param ref A Firebase reference to bind the datasource to + * @param model A custom class that FDataSnapshots are coerced to, defaults to FDataSnapshot if nil + * @param cell A subclass of UICollectionViewCell used to populate the UICollectionView, defaults to UICollectionViewCell if nil + * @param identifier A string to use as a CellReuseIdentifier + * @param collectionView An instance of a UICollectionView to bind to + * @return An instance of FirebaseCollectionViewDataSource that populates a custom subclass of UICollectionViewCell with a custom model class + */ +- (nonnull instancetype)initWithRef:(nonnull Firebase *)ref modelClass:(nullable Class)model cellClass:(nullable Class)cell reuseIdentifier:(nonnull NSString *)identifier view:(nonnull UICollectionView *)collectionView; + +/** + * Initialize an instance of FirebaseCollectionViewDataSource that populates a custom xib with a custom model class. + * @param ref A Firebase reference to bind the datasource to + * @param model A custom class that FDataSnapshots are coerced to, defaults to FDataSnapshot if nil + * @param nibName The name of a xib file to create the layout for a UICollectionViewCell + * @param identifier A string to use as a CellReuseIdentifier + * @param collectionView An instance of a UICollectionView to bind to + * @return An instance of FirebaseCollectionViewDataSource that populates a custom xib with a custom model class + */ +- (nonnull instancetype)initWithRef:(nonnull Firebase *)ref modelClass:(nullable Class)model nibNamed:(nonnull NSString *)nibName reuseIdentifier:(nonnull NSString *)identifier view:(nonnull UICollectionView *)collectionView; + +/** + * This method populates the fields of a UICollectionViewCell or subclass given an FDataSnapshot (or custom model object). + * @param callback A block which returns an initialized UICollectionViewCell (or subclass) and the corresponding object to populate the cell with. + */ +- (void)populateCellWithBlock:(nonnull void(^)(__nonnull __kindof UICollectionViewCell *cell, __nonnull __kindof NSObject *object))callback; + +@end diff --git a/FirebaseUI/API/FirebaseTableViewDataSource.h b/FirebaseUI/API/FirebaseTableViewDataSource.h index 4144a9cf8da..3bd97a533b5 100644 --- a/FirebaseUI/API/FirebaseTableViewDataSource.h +++ b/FirebaseUI/API/FirebaseTableViewDataSource.h @@ -32,27 +32,30 @@ @class Firebase; +/** + * FirebaseTableViewDataSource provides an class that conforms to the UITableViewDataSource protocol which allows UITableViews to implement FirebaseTableViewDataSource in order to provide a UITableView synchronized to a Firebase reference or query. In addition to handling all Firebase child events (added, changed, removed, moved), FirebaseTableViewDataSource handles UITableViewCell creation, either with the default UITableViewCell, prototype cells, custom UITableViewCell subclasses, or custom XIBs, and provides a simple [FirebaseTableViewDataSource populateCellWithBlock:] method which allows developers to populate the cells created for them with desired data from Firebase. + */ @interface FirebaseTableViewDataSource : FirebaseDataSource /** - * The model class to coerce FDataSnapshots to (if desired). For instance, if the modelClass is set to [Message class], then objects of type Message will be returned instead of type FDataSnapshot. + * The model class to coerce FDataSnapshots to (if desired). For instance, if the modelClass is set to [Message class] in Obj-C or Message.self in Swift, then objects of type Message will be returned instead of type FDataSnapshot. */ -@property (strong, nonatomic) Class modelClass; +@property (strong, nonatomic, nonnull) Class modelClass; /** * The reuse identifier for cells in the UITableView. */ -@property (strong, nonatomic) NSString *reuseIdentifier; +@property (strong, nonatomic, nonnull) NSString *reuseIdentifier; /** * The UITableView instance that operations (inserts, removals, moves, etc.) are performed against. */ -@property (strong, nonatomic) UITableView *tableView; +@property (strong, nonatomic, nonnull) UITableView *tableView; /** * The callback to populate a subclass of UITableViewCell with an object provided by the datasource. */ -@property (strong, nonatomic) void(^populateCell)(id cell, id object); +@property (strong, nonatomic, nonnull) void(^populateCell)(__nonnull __kindof UITableViewCell *cell, __nonnull __kindof NSObject *object); /** * Initialize an instance of FirebaseTableViewDataSource that populates UITableViewCells with FDataSnapshots. @@ -61,17 +64,17 @@ * @param tableView An instance of a UITableView to bind to * @return An instance of FirebaseTableViewDataSource that populates UITableViewCells with FDataSnapshots */ -- (instancetype)initWithRef:(Firebase *)ref reuseIdentifier:(NSString *)identifier view:(UITableView *)tableView; +- (nonnull instancetype)initWithRef:(nonnull Firebase *)ref reuseIdentifier:(nonnull NSString *)identifier view:(nonnull UITableView *)tableView; /** * Initialize an instance of FirebaseTableViewDataSource that populates a custom subclass of UITableViewCell with FDataSnapshots. * @param ref A Firebase reference to bind the datasource to - * @param cell A subclass of UITableViewCell that will + * @param cell A subclass of UITableViewCell used to populate the UITableView, defaults to UITableViewCell if nil * @param identifier A string to use as a CellReuseIdentifier * @param tableView An instance of a UITableView to bind to * @return An instance of FirebaseTableViewDataSource that populates a custom subclass of UITableViewCell with FDataSnapshots */ -- (instancetype)initWithRef:(Firebase *)ref cellClass:(Class)cell reuseIdentifier:(NSString *)identifier view:(UITableView *)tableView; +- (nonnull instancetype)initWithRef:(nonnull Firebase *)ref cellClass:(nullable Class)cell reuseIdentifier:(nonnull NSString *)identifier view:(nonnull UITableView *)tableView; /** * Initialize an instance of FirebaseTableViewDataSource that populates a custom xib with FDataSnapshots. @@ -81,45 +84,45 @@ * @param tableView An instance of a UITableView to bind to * @return An instance of FirebaseTableViewDataSource that populates a custom xib with FDataSnapshots */ -- (instancetype)initWithRef:(Firebase *)ref nibNamed:(NSString *)nibName reuseIdentifier:(NSString *)identifier view:(UITableView *)tableView; +- (nonnull instancetype)initWithRef:(nonnull Firebase *)ref nibNamed:(nonnull NSString *)nibName reuseIdentifier:(nonnull NSString *)identifier view:(nonnull UITableView *)tableView; /** * Initialize an instance of FirebaseTableViewDataSource that populates UITableViewCells with a custom model class. * @param ref A Firebase reference to bind the datasource to - * @param model A custom class that FDataSnapshots are coerced to + * @param model A custom class that FDataSnapshots are coerced to, defaults to FDataSnapshot if nil * @param identifier A string to use as a CellReuseIdentifier * @param tableView An instance of a UITableView to bind to * @return An instance of FirebaseTableViewDataSource that populates UITableViewCells with a custom model class */ -- (instancetype)initWithRef:(Firebase *)ref modelClass:(Class)model reuseIdentifier:(NSString *)identifier view:(UITableView *)tableView; +- (nonnull instancetype)initWithRef:(nonnull Firebase *)ref modelClass:(nullable Class)model reuseIdentifier:(nonnull NSString *)identifier view:(nonnull UITableView *)tableView; /** * Initialize an instance of FirebaseTableViewDataSource that populates a custom subclass of UITableViewCell with a custom model class. * @param ref A Firebase reference to bind the datasource to - * @param model A custom class that FDataSnapshots are coerced to - * @param cell A subclass of UITableViewCell that will + * @param model A custom class that FDataSnapshots are coerced to, defaults to FDataSnapshot if nil + * @param cell A subclass of UITableViewCell used to populate the UITableView, defaults to UITableViewCell if nil * @param identifier A string to use as a CellReuseIdentifier * @param tableView An instance of a UITableView to bind to * @return An instance of FirebaseTableViewDataSource that populates a custom subclass of UITableViewCell with a custom model class */ -- (instancetype)initWithRef:(Firebase *)ref modelClass:(Class)model cellClass:(Class)cell reuseIdentifier:(NSString *)identifier view:(UITableView *)tableView; +- (nonnull instancetype)initWithRef:(nonnull Firebase *)ref modelClass:(nullable Class)model cellClass:(nullable Class)cell reuseIdentifier:(nonnull NSString *)identifier view:(nonnull UITableView *)tableView; /** * Initialize an instance of FirebaseTableViewDataSource that populates a custom xib with a custom model class. * @param ref A Firebase reference to bind the datasource to - * @param model A custom class that FDataSnapshots are coerced to + * @param model A custom class that FDataSnapshots are coerced to, defaults to FDataSnapshot if nil * @param nibName The name of a xib file to create the layout for a UITableViewCell * @param identifier A string to use as a CellReuseIdentifier * @param tableView An instance of a UITableView to bind to * @return An instance of FirebaseTableViewDataSource that populates a custom xib with a custom model class */ -- (instancetype)initWithRef:(Firebase *)ref modelClass:(Class)model nibNamed:(NSString *)nibName reuseIdentifier:(NSString *)identifier view:(UITableView *)tableView; +- (nonnull instancetype)initWithRef:(nonnull Firebase *)ref modelClass:(nullable Class)model nibNamed:(nonnull NSString *)nibName reuseIdentifier:(nonnull NSString *)identifier view:(nonnull UITableView *)tableView; /** * This method populates the fields of a UITableViewCell or subclass given a model object (or FDataSnapshot). * @param callback A block which returns an initialized UITableViewCell (or subclass) and the corresponding object to populate the cell with. */ -- (void)populateCellWithBlock:(void(^)(id cell, id object))callback; +- (void)populateCellWithBlock:(nonnull void(^)(__nonnull __kindof UITableViewCell *cell, __nonnull __kindof NSObject *object))callback; @end diff --git a/FirebaseUI/API/FirebaseUI.h b/FirebaseUI/API/FirebaseUI.h index 9316c4c2406..1bd974bcab0 100644 --- a/FirebaseUI/API/FirebaseUI.h +++ b/FirebaseUI/API/FirebaseUI.h @@ -28,9 +28,10 @@ #import -#import -#import -#import +#import "FirebaseArray.h" +#import "FirebaseDataSource.h" +#import "FirebaseTableViewDataSource.h" +#import "FirebaseCollectionViewDataSource.h" @interface FirebaseUI : NSObject diff --git a/FirebaseUI/Implementation/FirebaseCollectionViewDataSource.m b/FirebaseUI/Implementation/FirebaseCollectionViewDataSource.m new file mode 100644 index 00000000000..a65dda1ddea --- /dev/null +++ b/FirebaseUI/Implementation/FirebaseCollectionViewDataSource.m @@ -0,0 +1,162 @@ +/* + * Firebase UI Bindings iOS Library + * + * Copyright © 2015 Firebase - All Rights Reserved + * https://www.firebase.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binaryform must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY FIREBASE AS IS AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL FIREBASE BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +#import "FirebaseCollectionViewDataSource.h" + +@implementation FirebaseCollectionViewDataSource + +#pragma mark - +#pragma mark FirebaseDataSource initializer methods + +- (instancetype)initWithRef:(Firebase *)ref reuseIdentifier:(NSString *)identifier view:(UICollectionView *)collectionView; +{ + return [self initWithRef:ref modelClass:nil cellClass:nil reuseIdentifier:identifier view:collectionView]; +} + +- (instancetype)initWithRef:(Firebase *)ref cellClass:(Class)cell reuseIdentifier:(NSString *)identifier view:(UICollectionView *)collectionView; +{ + return [self initWithRef:ref modelClass:nil cellClass:cell reuseIdentifier:identifier view:collectionView]; +} + +- (instancetype)initWithRef:(Firebase *)ref nibNamed:(NSString *)nibName reuseIdentifier:(NSString *)identifier view:(UICollectionView *)collectionView; +{ + return [self initWithRef:ref modelClass:nil nibNamed:nibName reuseIdentifier:identifier view:collectionView]; +} + +- (instancetype)initWithRef:(Firebase *)ref modelClass:(Class)model reuseIdentifier:(NSString *)identifier view:(UICollectionView *)collectionView; +{ + return [self initWithRef:ref modelClass:model cellClass:nil reuseIdentifier:identifier view:collectionView]; +} + +- (instancetype)initWithRef:(Firebase *)ref modelClass:(Class)model cellClass:(Class)cell reuseIdentifier:(NSString *)identifier view:(UICollectionView *)collectionView; +{ + FirebaseArray *array = [[FirebaseArray alloc] initWithRef:ref]; + self = [super initWithArray:array]; + if (self) { + + if (!model) { + model = [FDataSnapshot class]; + } + + if (!cell) { + cell = [UICollectionViewCell class]; + } + + self.collectionView = collectionView; + self.modelClass = model; + self.reuseIdentifier = identifier; + self.populateCell = ^(id cell, id object) {}; + + [self.collectionView registerClass:cell forCellWithReuseIdentifier:self.reuseIdentifier]; + } + return self; +} + +- (instancetype)initWithRef:(Firebase *)ref modelClass:(Class)model nibNamed:(NSString *)nibName reuseIdentifier:(NSString *)identifier view:(UICollectionView *)collectionView; +{ + FirebaseArray *array = [[FirebaseArray alloc] initWithRef:ref]; + self = [super initWithArray:array]; + if (self) { + + if (!model) { + model = [FDataSnapshot class]; + } + + self.collectionView = collectionView; + self.modelClass = model; + self.reuseIdentifier = identifier; + self.populateCell = ^(id cell, id object) {}; + + UINib *nib = [UINib nibWithNibName:nibName bundle:nil]; + [self.collectionView registerNib:nib forCellWithReuseIdentifier:self.reuseIdentifier]; + } + return self; +} + +#pragma mark - +#pragma mark FirebaseCollectionDelegate methods + +- (void)childAdded:(id)obj atIndex:(NSUInteger)index; +{ + [self.collectionView insertItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:index inSection:0]]]; +} + +- (void)childChanged:(id)obj atIndex:(NSUInteger)index; +{ + [self.collectionView reloadItemsAtIndexPaths:@[[NSIndexPath indexPathForRow:index inSection:0]]]; +} + +- (void)childRemoved:(id)obj atIndex:(NSUInteger)index; +{ + [self.collectionView deleteItemsAtIndexPaths:@[[NSIndexPath indexPathForRow:index inSection:0]]]; +} + +- (void)childMoved:(id)obj fromIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex; +{ + + [self.collectionView moveItemAtIndexPath:[NSIndexPath indexPathForRow:fromIndex inSection:0] toIndexPath:[NSIndexPath indexPathForRow:toIndex inSection:0]]; +} + +#pragma mark - +#pragma mark UICollectionViewDataSource methods + +-(nonnull UICollectionViewCell *)collectionView:(nonnull UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath; +{ + id cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:self.reuseIdentifier forIndexPath:indexPath]; + + FDataSnapshot *snap = [self.array objectAtIndex:indexPath.row]; + if (![self.modelClass isSubclassOfClass:[FDataSnapshot class]]) { + id model = [[self.modelClass alloc] init]; + // TODO: replace setValuesForKeysWithDictionary with client API valueAsObject method + [model setValuesForKeysWithDictionary:snap.value]; + self.populateCell(cell, model); + } else { + self.populateCell(cell, snap); + } + + return cell; +} + +-(NSInteger)numberOfSectionsInCollectionView:(nonnull UICollectionView *)collectionView; +{ + return 1; +} + +-(NSInteger)collectionView:(nonnull UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section; +{ + return [self.array count]; +} + +- (void)populateCellWithBlock:(nonnull void(^)(__nonnull __kindof UICollectionViewCell *cell, __nonnull __kindof NSObject *object))callback; +{ + self.populateCell = callback; +} + +@end diff --git a/FirebaseUI/Implementation/FirebaseTableViewDataSource.m b/FirebaseUI/Implementation/FirebaseTableViewDataSource.m index cc651a40509..303a23d0db3 100644 --- a/FirebaseUI/Implementation/FirebaseTableViewDataSource.m +++ b/FirebaseUI/Implementation/FirebaseTableViewDataSource.m @@ -37,22 +37,22 @@ @implementation FirebaseTableViewDataSource - (instancetype)initWithRef:(Firebase *)ref reuseIdentifier:(NSString *)identifier view:(UITableView *)tableView; { - return [self initWithRef:ref modelClass:[FDataSnapshot class] cellClass:[UITableViewCell class] reuseIdentifier:identifier view:tableView]; + return [self initWithRef:ref modelClass:nil cellClass:nil reuseIdentifier:identifier view:tableView]; } - (instancetype)initWithRef:(Firebase *)ref cellClass:(Class)cell reuseIdentifier:(NSString *)identifier view:(UITableView *)tableView; { - return [self initWithRef:ref modelClass:[FDataSnapshot class] cellClass:cell reuseIdentifier:identifier view:tableView]; + return [self initWithRef:ref modelClass:nil cellClass:cell reuseIdentifier:identifier view:tableView]; } - (instancetype)initWithRef:(Firebase *)ref nibNamed:(NSString *)nibName reuseIdentifier:(NSString *)identifier view:(UITableView *)tableView; { - return [self initWithRef:ref modelClass:[FDataSnapshot class] nibNamed:nibName reuseIdentifier:identifier view:tableView]; + return [self initWithRef:ref modelClass:nil nibNamed:nibName reuseIdentifier:identifier view:tableView]; } - (instancetype)initWithRef:(Firebase *)ref modelClass:(Class)model reuseIdentifier:(NSString *)identifier view:(UITableView *)tableView; { - return [self initWithRef:ref modelClass:model cellClass:[UITableViewCell class] reuseIdentifier:identifier view:tableView]; + return [self initWithRef:ref modelClass:model cellClass:nil reuseIdentifier:identifier view:tableView]; } - (instancetype)initWithRef:(Firebase *)ref modelClass:(Class)model cellClass:(Class)cell reuseIdentifier:(NSString *)identifier view:(UITableView *)tableView; @@ -60,6 +60,15 @@ - (instancetype)initWithRef:(Firebase *)ref modelClass:(Class)model cellClass:(C FirebaseArray *array = [[FirebaseArray alloc] initWithRef:ref]; self = [super initWithArray:array]; if (self) { + + if (!model) { + model = [FDataSnapshot class]; + } + + if (!cell) { + cell = [UITableViewCell class]; + } + self.tableView = tableView; self.modelClass = model; self.reuseIdentifier = identifier; @@ -77,6 +86,11 @@ - (instancetype)initWithRef:(Firebase *)ref modelClass:(Class)model nibNamed:(NS FirebaseArray *array = [[FirebaseArray alloc] initWithRef:ref]; self = [super initWithArray:array]; if (self) { + + if (!model) { + model = [FDataSnapshot class]; + } + self.tableView = tableView; self.modelClass = model; self.reuseIdentifier = identifier; @@ -124,7 +138,7 @@ - (void)childMoved:(id)obj fromIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)t #pragma mark - #pragma mark UITableViewDataSource methods -- (id)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +- (id)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; { id cell = [self.tableView dequeueReusableCellWithIdentifier:self.reuseIdentifier forIndexPath:indexPath]; @@ -141,12 +155,12 @@ - (id)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)in return cell; } -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; { return [self.array count]; } -- (void)populateCellWithBlock:(void(^)(id cell, id object))callback; +- (void)populateCellWithBlock:(nonnull void(^)(__nonnull __kindof UITableViewCell *cell, __nonnull __kindof NSObject *object))callback; { self.populateCell = callback; } diff --git a/README.md b/README.md index cdfb7b05c70..4041a6cf642 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,14 @@ We recommend using [CocoaPods](http://cocoapods.org/?q=firebaseui-ios), add the following to your `Podfile`: ``` -pod 'FirebaseUI', '~> 0.1' +pod 'FirebaseUI', '~> 0.2' +``` + +If you're including FirebaseUI in a Swift project, make sure you also have: + +``` +platform :ios, '8.0' +use_frameworks! ``` Otherwise, you can download the latest version of the [FirebaseUI.framework from the releases @@ -18,16 +25,6 @@ page](https://github.com/firebase/FirebaseUI-iOS/releases) or include the Fireba Xcode project from this repo in your project. You also need to [add the Firebase framework](https://www.firebase.com/docs/ios-quickstart.html?utm_source=firebaseui-ios) to your project. -### Using FirebaseUI with Swift - -In order to use FirebaseUI in a Swift project, you'll also need to setup a bridging -header, in addition to adding the Firebase and FirebaseUI frameworks -to your project. To do that, [follow these instructions](https://www.firebase.com/docs/ios/guide/setup.html#section-swift), and then add the following line to your bridging header: - -````objective-c -#import -```` - ## Getting Started with Firebase FirebaseUI requires Firebase in order to store location data. You can [sign up here for a free @@ -35,22 +32,31 @@ account](https://www.firebase.com/signup/?utm_source=firebaseui-ios). ## FirebaseUI for iOS Quickstart -This is a quickstart on how to use FirebaseUI's core features to speed up iOS development with Firebase. +This is a quickstart on how to use FirebaseUI's core features to speed up iOS development with Firebase. FirebaseUI includes the following features: + +Class | Description +------------- | ------------- +FirebaseTableViewDataSource | Data source to bind a Firebase query to a UITableView +FirebaseCollectionViewDataSource | Data source to bind a Firebase query to a UICollectionView +FirebaseArray | Keeps an array synchronized to a Firebase query +FirebaseDataSource | Generic superclass to create a custom data source + +For a more in-depth explanation of each of the above, check the usage instructions below: ### FirebaseTableViewDataSource -FirebaseTableViewDataSource implements the UITableViewDataSource protocol to automatically use Firebase as a DataSource for your UITableView. +`FirebaseTableViewDataSource` implements the `UITableViewDataSource` protocol to automatically use Firebase as a data source for your `UITableView`. -##### Objective-C +#### Objective-C ```objective-c -MyViewController.h +YourViewController.h ... -@property (strong, nonatomic) Firebase *ref; +@property (strong, nonatomic) Firebase *firebaseRef; @property (strong, nonatomic) FirebaseTableViewDataSource *dataSource; ``` ```objective-c -MyViewController.m +YourViewController.m ... self.firebaseRef = [[Firebase alloc] initWithUrl:@"https://.firebaseio.com/"]; self.dataSource = [[FirebaseTableViewDataSource alloc] initWithRef:firebaseRef reuseIdentifier:@"" view:self.tableView]; @@ -63,29 +69,81 @@ self.dataSource = [[FirebaseTableViewDataSource alloc] initWithRef:firebaseRef r [self.tableView setDataSource:self.dataSource]; ``` -## Creating Custom TableViews with FirebaseTableViewDataSource +#### Swift +```swift +YourViewController.swift +... +let firebaseRef = Firebase(url:"https://.firebaseio.com/") +let dataSource: FirebaseTableViewDataSource! +... +self.dataSource = FirebaseTableViewDataSource(ref: self.firebaseRef, reuseIdentifier: "", view: self.tableView) -You can use FirebaseTableViewDataSource in several ways to create custom UITableViews. For more information on how to create custom UITableViews, check out the following tutorial on [TutsPlus](http://code.tutsplus.com/tutorials/ios-sdk-crafting-custom-uitableview-cells--mobile-15702). +self.dataSource.populateCellWithBlock { (cell: UITableViewCell, obj: NSObject) -> Void in + let snap = obj as! FDataSnapshot -### Using the Default UITableViewCell Implementation + // Populate cell as you see fit, like as below + cell.textLabel?.text = snap.key as String +} -You can use the default UITableViewCell implementation to get up and running quickly. This allows for the `cell.textLabel` and the `cell.detailTextLabel` to be used directly out of the box. +self.tableView.dataSource = self.dataSource +``` + +### FirebaseCollectionViewDataSource + +`FirebaseCollectionViewDataSource` implements the `UICollectionViewDataSource` protocol to automatically use Firebase as a data source for your `UICollectionView`. + +#### Objective-C ```objective-c -self.dataSource = [[FirebaseTableViewDataSource alloc] initWithRef:firebaseRef reuseIdentifier:@"" view:self.tableView]; +YourViewController.h +... +@property (strong, nonatomic) Firebase *firebaseRef; +@property (strong, nonatomic) FirebaseCollectionViewDataSource *dataSource; +``` -[self.dataSource populateCellWithBlock:^(UITableViewCell *cell, FDataSnapshot *snap) { +```objective-c +YourViewController.m +... +self.firebaseRef = [[Firebase alloc] initWithUrl:@"https://.firebaseio.com/"]; +self.dataSource = [[FirebaseTableViewDataSource alloc] initWithRef:firebaseRef reuseIdentifier:@"" view:self.CollectionView]; + +[self.dataSource populateCellWithBlock:^(UICollectionViewCell *cell, FDataSnapshot *snap) { // Populate cell as you see fit, like as below - cell.textLabel.text = snap.key; + cell.backgroundColor = [UIColor blueColor]; }]; -[self.tableView setDataSource:self.dataSource]; +[self.collectionView setDataSource:self.dataSource]; ``` -### Using Storyboards and Prototype Cells +#### Swift +```swift +YourViewController.swift +... +let firebaseRef = Firebase(url: "https://.firebaseio.com/") +let dataSource: FirebaseCollectionViewDataSource! +... +self.dataSource = FirebaseCollectionViewDataSource(ref: self.firebaseRef, reuseIdentifier: "", view: self.collectionView) + +self.dataSource.populateCellWithBlock { (cell: UICollectionViewCell, obj: NSObject) -> Void in + let snap = obj as! FDataSnapshot + + // Populate cell as you see fit, like as below + cell.backgroundColor = UIColor.blueColor() +} + +self.collectionView.dataSource = self.dataSource + +``` + +## Customizing your UITableView or UICollectionView + +You can use `FirebaseTableViewDataSource` or `FirebaseCollectionViewDataSource` in several ways to create custom UITableViews or UICollectionViews. For more information on how to create custom UITableViews, check out the following tutorial on [TutsPlus](http://code.tutsplus.com/tutorials/ios-sdk-crafting-custom-uitableview-cells--mobile-15702). For more information on how to create custom UICollectionViews, particularly how to implement a UICollectionViewLayout, check out the following tutorial on Ray Wenderlich in [Objective-C](http://www.raywenderlich.com/22324/beginning-uicollectionview-in-ios-6-part-12) and [Swift](http://www.raywenderlich.com/78550/beginning-ios-collection-views-swift-part-1). -Create a storyboard that has either a UITableViewController or a UIViewController with a UITableView. Drag a prototype cell onto the UITableView and give it a custom ReuseIdentifier. Drag and other properties onto the cell and associate them with properties of a UITableViewCell subclass. +### Using the Default UI*ViewCell Implementation +You can use the default `UITableViewCell` or `UICollectionViewCell` implementations to get up and running quickly. For `UITableViewCell`s, this allows for the `cell.textLabel` and the `cell.detailTextLabel` to be used directly out of the box. For `UICollectionViewCell`s, you will have to add subviews to the contentView in order for it to be useful. + +#### Objective-C UITableView and UICollectionView with Default UI*ViewCell ```objective-c self.dataSource = [[FirebaseTableViewDataSource alloc] initWithRef:firebaseRef reuseIdentifier:@"" view:self.tableView]; @@ -97,57 +155,171 @@ self.dataSource = [[FirebaseTableViewDataSource alloc] initWithRef:firebaseRef r [self.tableView setDataSource:self.dataSource]; ``` -### Using a Custom Subclass of UITableViewCell +```objective-c +self.dataSource = [[FirebaseCollectioneViewDataSource alloc] initWithRef:firebaseRef reuseIdentifier:@"" view:self.CollectionView]; -Create a custom subclass of UITableViewCell, with or without the XIB file. Make sure to instantiate `-initWithStyle: reuseIdentifier:` to instantiate the Cells. You can then hook the custom class up to the implementation of FirebaseTableViewDataSource. +[self.dataSource populateCellWithBlock:^(UICollectionViewCell *cell, FDataSnapshot *snap) { + // Populate cell as you see fit by adding subviews as appropriate + [cell.contentView addSubview:customView]; +}]; +[self.collectionView setDataSource:self.dataSource]; +``` + +#### Swift UITableView and UICollectionView with Default UI*ViewCell +```swift +self.dataSource = FirebaseTableViewDataSource(ref: firebaseRef reuseIdentifier: @"" view: self.tableView) + +self.dataSource.populateCellWithBlock { (cell: UITableViewCell, obj: NSObject) -> Void in + // Populate cell as you see fit, like as below + cell.textLabel.text = snap.key; +} + +self.tableView.dataSource = self.dataSource; +``` + +```swift +self.dataSource = FirebaseCollectionViewDataSource(ref: firebaseRef reuseIdentifier: @"" view: self.collectionView) + +self.dataSource.populateCellWithBlock { (cell: UICollectionViewCell, obj: NSObject) -> Void in + // Populate cell as you see fit by adding subviews as appropriate + cell.contentView.addSubview(customView) +} + +self.collectionView.dataSource = self.dataSource; +``` + +### Using Storyboards and Prototype Cells + +Create a storyboard that has either a `UITableViewController`, `UICollectionViewController` or a `UIViewController` with a `UITableView` or `UICollectionView`. Drag a prototype cell onto the `UITableView` or `UICollectionView` and give it a custom reuse identifier which matches the reuse identifier being used when instantiating the `Firebase*ViewDataSource`. Drag and other properties onto the cell and associate them with properties of a `UITableViewCell` or `UICollectionViewCell` subclass. Code samples are similar to the above. + +### Using a Custom Subclass of UI*ViewCell + +Create a custom subclass of `UITableViewCell` or `UICollectionViewCell`, with or without the XIB file. Make sure to instantiate `-initWithStyle: reuseIdentifier:` to instantiate a `UITableViewCell` or `-initWithFrame:` to instantiate a `UICollectionViewCell`. You can then hook the custom class up to the implementation of `FirebaseTableViewDataSource`. + +#### Objective-C UITableView and UICollectionView with Custom Subclasses of UI*ViewCell ```objective-c -self.dataSource = [[FirebaseTableViewDataSource alloc] initWithRef:firebaseRef cellClass:[YourCustomCell class] reuseIdentifier:@"" view:self.tableView]; +self.dataSource = [[FirebaseTableViewDataSource alloc] initWithRef:firebaseRef cellClass:[YourCustomClass class] reuseIdentifier:@"" view:self.tableView]; -[self.dataSource populateCellWithBlock:^(YourCustomCell *cell, FDataSnapshot *snap) { - // Populate your custom cell as you see fit, like as below - cell.customLabel.text = snap.key; +[self.dataSource populateCellWithBlock:^(YourCustomClass *cell, FDataSnapshot *snap) { + // Populate custom cell as you see fit, like as below + cell.yourCustomLabel.text = snap.key; }]; [self.tableView setDataSource:self.dataSource]; ``` +```objective-c +self.dataSource = [[FirebaseCollectioneViewDataSource alloc] initWithRef:firebaseRef cellClass:[YourCustomClass class] reuseIdentifier:@"" view:self.CollectionView]; + +[self.dataSource populateCellWithBlock:^(YourCustomClass *cell, FDataSnapshot *snap) { + // Populate cell as you see fit + cell.customView = customView; +}]; + +[self.collectionView setDataSource:self.dataSource]; +``` + +#### Swift UITableView and UICollectionView with Custom Subclasses of UI*ViewCell +```swift +self.dataSource = FirebaseTableViewDataSource(ref: firebaseRef cellClass: YourCustomClass.self reuseIdentifier: @"" view: self.tableView) + +self.dataSource.populateCellWithBlock { (cell: YourCustomClass, obj: NSObject) -> Void in + // Populate cell as you see fit, like as below + cell.yourCustomLabel.text = snap.key; +} + +self.tableView.dataSource = self.dataSource; +``` + +```swift +self.dataSource = FirebaseCollectionViewDataSource(ref: firebaseRef cellClass: YourCustomClass.self reuseIdentifier: @"" view: self.collectionView) + +self.dataSource.populateCellWithBlock { (cell: YourCustomClass, obj: NSObject) -> Void in + // Populate cell as you see fit + cell.customView = customView; +} + +self.collectionView.dataSource = self.dataSource; +``` + ### Using a Custom XIB -Create a custom XIB file and add it to the cell prototype. You can then use this like any other UITableViewCell, though with custom tags if desired. +Create a custom XIB file and hook it up to the prototype cell. You can then use this like any other UITableViewCell, either using custom tags or by using the custom class associated with the XIB. +#### Objective-C UITableView and UICollectionView with Custom XIB ```objective-c self.dataSource = [[FirebaseTableViewDataSource alloc] initWithRef:firebaseRef nibNamed:@"" reuseIdentifier:@"" view:self.tableView]; [self.dataSource populateCellWithBlock:^(UITableViewCell *cell, FDataSnapshot *snap) { - // Populate your cell as you see fit, like as below - cell.textLabel.text = snap.key; + // Use tags to populate custom properties, or use properties of a custom cell, if applicable + UILabel *yourCustomLabel = (UILabel *)[cell.contentView viewWithTag:]; + yourCustomLabel.text = snap.key +}]; + +[self.tableView setDataSource:self.dataSource]; +``` + +```objective-c +self.dataSource = [[FirebaseCollectionViewDataSource alloc] initWithRef:firebaseRef nibNamed:@"" reuseIdentifier:@"" view:self.collectionView]; - // Use tags to populate custom properties - UILabel *myCustomLabel = (UILabel *)[cell.contentView viewWithTag:]; - myCustomLabel.text = snap.key +[self.dataSource populateCellWithBlock:^(UICollectionViewCell *cell, FDataSnapshot *snap) { + // Use tags to populate custom properties, or use properties of a custom cell, if applicable + UILabel *yourCustomLabel = (UILabel *)[cell.contentView viewWithTag:]; + yourCustomLabel.text = snap.key }]; [self.tableView setDataSource:self.dataSource]; ``` +#### Swift UITableView and UICollectionView with Custom XIB +```swift +self.dataSource = FirebaseTableViewDataSource(ref: firebaseRef nibNamed: "" reuseIdentifier: @"" view: self.tableView) + +self.dataSource.populateCellWithBlock { (cell: UITableViewCell, obj: NSObject) -> Void in + // Use tags to populate custom properties, or use properties of a custom cell, if applicable + let yourCustomLabel: UILabel = cell.contentView.viewWithTag() as! UILabel + yourCustomLabel.text = snap.key +} + +self.tableView.dataSource = self.dataSource; +``` + +```swift +self.dataSource = FirebaseCollectionViewDataSource(ref: firebaseRef cellClass: YourCustomClass.self reuseIdentifier: @"" view: self.collectionView) + +self.dataSource.populateCellWithBlock { (cell: YourCustomClass, obj: NSObject) -> Void in + // Use tags to populate custom properties, or use properties of a custom cell, if applicable + let yourCustomLabel: UILabel = cell.contentView.viewWithTag() as! UILabel + yourCustomLabel.text = snap.key +} + +self.collectionView.dataSource = self.dataSource; +``` + ## Understanding FirebaseUI's Internals -FirebaseUI has several building blocks that developers should understand before building additional functionality on top of FirebaseUI, including a synchronized array `FirebaseArray.*` and a generic data source superclass `FirebaseDataSource.*` from which FirebaseTableViewDataSource or other custom view classes subclass. +FirebaseUI has several building blocks that developers should understand before building additional functionality on top of FirebaseUI, including a synchronized array `FirebaseArray` and a generic data source superclass `FirebaseDataSource` from which `FirebaseTableViewDataSource` and `FirebaseCollectionViewDataSource` or other custom view classes subclass. ### FirebaseArray and the FirebaseArrayDelegate Protocol -FirebaseArray is synchronized array connecting a Firebase Ref with an array. It surfaces Firebase events through the FirebaseArrayDelegate Protocol. It is generally recommended that developers not directly access FirebaseArray without routing it through a custom data source. +`FirebaseArray` is synchronized array connecting a Firebase Ref with an array. It surfaces Firebase events through the FirebaseArrayDelegate Protocol. It is generally recommended that developers not directly access `FirebaseArray` without routing it through a custom data source, though if this is desired, check out `FirebaseDataSource` below. -##### Objective-C +#### Objective-C ```objective-c -FirebaseArray *array = [[FirebaseArray alloc] initWithRef:@"https://.firebaseio.com/"]; +Firebase *firebaseRef = [[Firebase alloc] initWithUrl:@"https://.firebaseio.com/"]; +FirebaseArray *array = [[FirebaseArray alloc] initWithRef:firebaseRef]; +``` +#### Swift +```swift +let firebaseRef = Firebase(url: "https://.firebaseio.com/") +let array = FirebaseArray(ref: firebaseRef) ``` ### FirebaseDataSource -FirebaseDataSource acts as a generic data source by providing common information, such as the count of objects in the data source, and by requiring subclasses to implement FirebaseArrayDelegate methods as appropriate to the view. This class should never be instantiated, but should be subclassed when creating a specific adapter for a View. [FirebaseTableViewDataSource](https://github.com/firebase/FirebaseUI-iOS/blob/master/FirebaseUI/Implementation/FirebaseTableViewDataSource.m) is an example of this. +FirebaseDataSource acts as a generic data source by providing common information, such as the count of objects in the data source, and by requiring subclasses to implement FirebaseArrayDelegate methods as appropriate to the view. This class should never be instantiated, but should be subclassed when creating a specific adapter for a View. [FirebaseTableViewDataSource](https://github.com/firebase/FirebaseUI-iOS/blob/master/FirebaseUI/Implementation/FirebaseTableViewDataSource.m) and [FirebaseCollectionViewDataSource](https://github.com/firebase/FirebaseUI-iOS/blob/master/FirebaseUI/Implementation/FirebaseCollectionViewDataSource.m) are examples of this. FirebaseDataSource is essentially a wrapper around a FirebaseArray. ## Local Setup @@ -160,11 +332,14 @@ $ cd FirebaseUI-iOS $ ./setup.sh ``` +FirebaseUI makes use of XCode 7 features such as lightweight generics and `__kindof` annotations, so please ensure you're using the latest version of XCode beta for development. + ## Deployment - `git pull` to update the master branch - tag and push the tag for this release - `./build.sh` to build a binary +- `./create-docs.sh` to generate docs - From your macbook that already has been granted permissions to FirebaseUI Cocoapods, do `pod trunk push` - Update [firebase-versions](https://github.com/firebase/firebase-clients/blob/master/versions/firebase-versions.json) with the changelog for this release. diff --git a/create-docs.sh b/create-docs.sh new file mode 100755 index 00000000000..64e36f413c9 --- /dev/null +++ b/create-docs.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -e + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +echo "Generating appledocs..." +appledoc --project-name "FirebaseUI for iOS" \ +--project-company "Firebase" \ +--company-id com.firebase \ +--no-create-docset \ +--create-html \ +--keep-intermediate \ +--output ./docs/output/ \ +--templates=./docs/template/ \ +--output "$DIR/site/" \ +--search-undocumented-doc \ +--exit-threshold 2 \ +"$DIR"/FirebaseUI/API/*.h diff --git a/docs/template/docset/Contents/Resources/Documents/documents-template b/docs/template/docset/Contents/Resources/Documents/documents-template new file mode 100644 index 00000000000..078aab97fb6 --- /dev/null +++ b/docs/template/docset/Contents/Resources/Documents/documents-template @@ -0,0 +1 @@ +This is used only as placeholder for location of Documents directory! \ No newline at end of file diff --git a/docs/template/docset/Contents/Resources/nodes-template.xml b/docs/template/docset/Contents/Resources/nodes-template.xml new file mode 100644 index 00000000000..2db5e406c07 --- /dev/null +++ b/docs/template/docset/Contents/Resources/nodes-template.xml @@ -0,0 +1,131 @@ + + + + + {{projectName}} + {{indexFilename}} + + {{#hasDocs}} + + {{strings.docset.docsTitle}} + {{indexFilename}} + + {{#docs}}{{>NodeRef}} + {{/docs}} + + + {{/hasDocs}} + {{#hasClasses}} + + {{strings.docset.classesTitle}} + {{indexFilename}} + + {{#classes}}{{>NodeRef}} + {{/classes}} + + + {{/hasClasses}} + {{#hasCategories}} + + {{strings.docset.categoriesTitle}} + {{indexFilename}} + + {{#categories}}{{>NodeRef}} + {{/categories}} + + + {{/hasCategories}} + {{#hasProtocols}} + + {{strings.docset.protocolsTitle}} + {{indexFilename}} + + {{#protocols}}{{>NodeRef}} + {{/protocols}} + + + {{/hasProtocols}} + {{#hasConstants}} + + {{strings.docset.constantsTitle}} + {{indexFilename}} + + {{#constants}}{{>NodeRef}} + {{/constants}} + + + {{/hasConstants}} + {{#hasBlocks}} + + {{strings.docset.blocksTitle}} + {{indexFilename}} + + {{#blocks}}{{>NodeRef}} + {{/blocks}} + + + {{/hasBlocks}} + + + + + {{#docs}}{{>Node}} + {{/docs}} + {{#classes}}{{>Node}} + {{/classes}} + {{#categories}}{{>Node}} + {{/categories}} + {{#protocols}}{{>Node}} + {{/protocols}} + {{#constants}}{{>Node}} + {{/constants}} + {{#blocks}}{{>Node}} + {{/blocks}} + + + +Section Node + + {{name}} + {{path}} + {{#hasSubNodes}} + + + {{path}} + Overview + overview + + + {{path}} + Tasks + tasks + + {{#hasProperties}} + + {{path}} + Properties + properties + + {{/hasProperties}} + {{#hasClassMethods}} + + {{path}} + Class Methods + class_methods + + {{/hasClassMethods}} + {{#hasInstanceMethods}} + + {{path}} + Instance Methods + instance_methods + + {{/hasInstanceMethods}} + + {{/hasSubNodes}} + +EndSection + +Section NodeRef + +EndSection diff --git a/docs/template/docset/Contents/Resources/tokens-template.xml b/docs/template/docset/Contents/Resources/tokens-template.xml new file mode 100755 index 00000000000..5ac05c2a879 --- /dev/null +++ b/docs/template/docset/Contents/Resources/tokens-template.xml @@ -0,0 +1,93 @@ + + + + {{#object}} + + {{>TokenIdentifier}} + {{>Abstract}} + {{>DeclaredIn}} + {{>Availability}} + {{>RelatedTokens}} + {{#refid}}{{/refid}} + + {{/object}} + {{#members}} + + {{>TokenIdentifier}} + {{>Abstract}} + {{>DeclaredIn}} + {{>RelatedTokens}} + {{>MethodDeclaration}} + {{#hasParameters}} + {{#parameters}} + {{name}} + {{>Abstract}} + {{/parameters}} + {{/hasParameters}} + {{#returnValue}}{{>Abstract}}{{/returnValue}} + {{#anchor}}{{anchor}}{{/anchor}} + {{#refid}}{{/refid}} + + {{/members}} + {{#constants}} + + {{>TokenIdentifier}} + {{>Abstract}} + {{declaration}} + {{>Availability}} + {{>DeclaredIn}} + {{>RelatedTokens}} + {{>Reference}} + + {{/constants}} + {{#blocks}} + + {{>TokenIdentifier}} + {{>Abstract}} + {{declaration}} + {{>Availability}} + {{>DeclaredIn}} + {{>RelatedTokens}} + {{>Reference}} + + {{/blocks}} + + + +Section TokenIdentifier + {{identifier}} +EndSection + +Section DeclaredIn + {{declaredin}} +EndSection + +Section RelatedTokens + {{#hasRelatedTokens}} + + {{#relatedTokens}}{{.}} + {{/relatedTokens}} + + {{/hasRelatedTokens}} +EndSection + +Section Abstract +{{#abstract}}{{>GBCommentComponentsList}}{{/abstract}} +EndSection + +Section Availability +{{#availability}}{{>GBCommentComponentsList}}{{/availability}} +EndSection + +Section Reference +{{#refid}}{{/refid}} +EndSection + +Section MethodDeclaration +{{#formattedComponents}}{{value}}{{/formattedComponents}} +EndSection + +Section GBCommentComponentsList +{{#components}}{{textValue}}{{/components}} +EndSection + diff --git a/docs/template/docset/Contents/info-template.plist b/docs/template/docset/Contents/info-template.plist new file mode 100644 index 00000000000..26de4711d59 --- /dev/null +++ b/docs/template/docset/Contents/info-template.plist @@ -0,0 +1,40 @@ + + + + + CFBundleDevelopmentRegion + en + {{#bundleIdentifier}}CFBundleIdentifier + {{bundleIdentifier}}{{/bundleIdentifier}} + {{#bundleName}}CFBundleName + {{bundleName}}{{/bundleName}} + {{#bundleVersion}}CFBundleShortVersionString + {{bundleVersion}} + CFBundleVersion + {{bundleVersion}}{{/bundleVersion}} + {{#certificateIssuer}}DocSetCertificateIssuer + {{certificateIssuer}}{{/certificateIssuer}} + {{#certificateSigner}}DocSetCertificateSigner + {{certificateSigner}}{{/certificateSigner}} + {{#description}}DocSetDescription + {{description}}{{/description}} + {{#fallbackURL}}DocSetFallbackURL + {{fallbackURL}}{{/fallbackURL}} + {{#feedName}}DocSetFeedName + {{feedName}}{{/feedName}} + {{#feedURL}}DocSetFeedURL + {{feedURL}}{{/feedURL}} + {{#minimumXcodeVersion}}DocSetMinimumXcodeVersion + {{minimumXcodeVersion}}{{/minimumXcodeVersion}} + {{#platformFamily}}DocSetPlatformFamily + {{platformFamily}}{{/platformFamily}} + {{#dashPlatformFamily}}DashDocSetFamily + {{dashPlatformFamily}}{{/dashPlatformFamily}} + {{#publisherIdentifier}}DocSetPublisherIdentifier + {{publisherIdentifier}}{{/publisherIdentifier}} + {{#publisherName}}DocSetPublisherName + {{publisherName}}{{/publisherName}} + {{#copyrightMessage}}NSHumanReadableCopyright + {{copyrightMessage}}{{/copyrightMessage}} + + diff --git a/docs/template/html/css/scss/_index.scss b/docs/template/html/css/scss/_index.scss new file mode 100644 index 00000000000..7e98029dde0 --- /dev/null +++ b/docs/template/html/css/scss/_index.scss @@ -0,0 +1,13 @@ +.index-container { + display: flex; + flex-direction: row; + flex-wrap: wrap; + + @media (max-width: $mobile-max-width) { + flex-direction: column; + } + + .index-column { + flex: 1 1 33%; + } +} diff --git a/docs/template/html/css/scss/_layout.scss b/docs/template/html/css/scss/_layout.scss new file mode 100644 index 00000000000..40bd6d4aec7 --- /dev/null +++ b/docs/template/html/css/scss/_layout.scss @@ -0,0 +1,303 @@ +* { + box-sizing: border-box; +} + +.clear { + clear: both; +} + +.clearfix { + &:before, &:after { + clear: both; + display: table; + content: ""; + } +} + +.xcode .hide-in-xcode { + display: none; +} + +body { + font: 62.5% $body-font; + background: $body-background; +} + +h1, h2, h3 { + font-weight: 300; + color: #808080; +} + +h1 { + font-size: 2em; + color: #000; +} + +h4 { + font-size: 13px; + line-height: 1.5; + margin: 21px 0 0 0; +} + +a { + color: $tint-color; + text-decoration: none; +} + +pre, code { + font-family: $code-font; + word-wrap: break-word; +} + +pre > code, .method-declaration code { + display: inline-block; + font-size: .85em; + padding: 4px 0 4px 10px; + border-left: 5px solid rgba(0, 155, 51, .2); + + &:before { + content: "Objective-C"; + display: block; + + font: 9px/1 $body-font; + color: #009b33; + text-transform: uppercase; + letter-spacing: 2px; + padding-bottom: 6px; + } +} + +pre > code { + font-size: inherit; +} + +table, th, td { + border: 1px solid #e9e9e9; +} + +table { + width: 100%; +} + +th, td { + padding: 7px; + + > :first-child { + margin-top: 0; + } + + > :last-child { + margin-bottom: 0; + } +} + +.container { + @extend .clearfix; + + max-width: 980px; + padding: 0 10px; + margin: 0 auto; + + @media (max-width: $mobile-max-width) { + padding: 0; + } +} + +header { + position: fixed; + top: 0; + left: 0; + width: 100%; + z-index: 2; + + background: #414141; + color: #fff; + font-size: 1.1em; + line-height: 25px; + letter-spacing: .05em; + + #library-title { + float: left; + } + + #developer-home { + float: right; + } + + h1 { + font-size: inherit; + font-weight: inherit; + margin: 0; + } + + p { + margin: 0; + } + + h1, a { + color: inherit; + } + + @media (max-width: $mobile-max-width) { + position: absolute; + + .container { + padding: 0 10px; + } + } +} + +aside { + position: fixed; + top: 25px; + left: 0; + width: 100%; + height: 25px; + z-index: 2; + + font-size: 1.1em; + + @media (max-width: $mobile-max-width) { + position: absolute; + } + + #header-buttons { + background: rgba(255, 255, 255, .8); + margin: 0 1px; + padding: 0; + list-style: none; + text-align: right; + line-height: 32px; + + li { + display: inline-block; + cursor: pointer; + padding: 0 10px; + } + + label, select { + cursor: inherit; + } + + #on-this-page { + position: relative; + + .chevron { + display: inline-block; + width: 14px; + height: 4px; + position: relative; + + .chevy { + background: #878787; + height: 2px; + position: absolute; + width: 10px; + + &.chevron-left { + left: 0; + transform: rotateZ(45deg) scale(0.6); + } + + &.chevron-right { + right: 0; + transform: rotateZ(-45deg) scale(0.6); + } + } + } + + #jump-to { + opacity: 0; + font-size: 16px; + + position: absolute; + top: 5px; + left: 0; + width: 100%; + height: 100%; + } + } + } +} + +article { + margin-top: 25px; + + #content { + @extend .clearfix; + + background: $content-background; + border: 1px solid $content-border; + padding: 15px 25px 30px 25px; + + font-size: 1.4em; + line-height: 1.45; + + position: relative; + + @media (max-width: $mobile-max-width) { + padding: 15px 10px 20px 10px; + } + + .navigation-top { + position: absolute; + top: 15px; + right: 25px; + } + + .title { + margin: 21px 0 0 0; + padding: 15px 0; + } + + p { + color: #414141; + margin: 0 0 15px 0; + } + + th, td { + p:last-child { + margin-bottom: 0; + } + } + + main { + ul { + list-style: none; + margin-left: 24px; + margin-bottom: 12px; + padding: 0; + + li { + position: relative; + padding-left: 1.3em; + + &:before { + content: "\02022"; + + color: #414141; + font-size: 1.08em; + line-height: 1; + + position: absolute; + left: 0; + padding-top: 2px; + } + } + } + } + + footer { + @extend .clearfix; + + .footer-copyright { + margin: 70px 25px 10px 0; + } + + p { + font-size: .71em; + color: #a0a0a0; + } + } + } +} diff --git a/docs/template/html/css/scss/_normalize.scss b/docs/template/html/css/scss/_normalize.scss new file mode 100644 index 00000000000..9b8848a5cf1 --- /dev/null +++ b/docs/template/html/css/scss/_normalize.scss @@ -0,0 +1,581 @@ +/* ========================================================================== + Normalize.scss settings + ========================================================================== */ +/** + * Includes legacy browser support IE6/7 + * + * Set to false if you want to drop support for IE6 and IE7 + */ + +$legacy_browser_support: false !default; + +/* Base + ========================================================================== */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + * 3. Corrects text resizing oddly in IE 6/7 when body `font-size` is set using + * `em` units. + */ + +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ + @if $legacy_browser_support { + *font-size: 100%; /* 3 */ + } +} + +/** + * Remove default margin. + */ + +body { + margin: 0; +} + +/* HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} + +/** + * 1. Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ + +audio, +canvas, +progress, +video { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ + @if $legacy_browser_support { + *display: inline; + *zoom: 1; + } +} + +/** + * Prevents modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a { + &:active, &:hover { + outline: 0; + }; +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +@if $legacy_browser_support { + blockquote { + margin: 1em 40px; + } +} + +/** + * Address styling not present in Safari and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +@if $legacy_browser_support { + h2 { + font-size: 1.5em; + margin: 0.83em 0; + } + + h3 { + font-size: 1.17em; + margin: 1em 0; + } + + h4 { + font-size: 1em; + margin: 1.33em 0; + } + + h5 { + font-size: 0.83em; + margin: 1.67em 0; + } + + h6 { + font-size: 0.67em; + margin: 2.33em 0; + } +} + +/** + * Addresses styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +@if $legacy_browser_support { + + /** + * Addresses margins set differently in IE 6/7. + */ + + p, + pre { + *margin: 1em 0; + } + + /* + * Addresses CSS quotes not supported in IE 6/7. + */ + + q { + *quotes: none; + } + + /* + * Addresses `quotes` property not supported in Safari 4. + */ + + q:before, + q:after { + content: ''; + content: none; + } +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +@if $legacy_browser_support { + + /* ========================================================================== + Lists + ========================================================================== */ + + /* + * Addresses margins set differently in IE 6/7. + */ + + dl, + menu, + ol, + ul { + *margin: 1em 0; + } + + dd { + *margin: 0 0 0 40px; + } + + /* + * Addresses paddings set differently in IE 6/7. + */ + + menu, + ol, + ul { + *padding: 0 0 0 40px; + } + + /* + * Corrects list images handled incorrectly in IE 7. + */ + + nav ul, + nav ol { + *list-style: none; + *list-style-image: none; + } + +} + +/* Embedded content + ========================================================================== */ + +/** + * 1. Remove border when inside `a` element in IE 8/9/10. + * 2. Improves image quality when scaled in IE 7. + */ + +img { + border: 0; + @if $legacy_browser_support { + *-ms-interpolation-mode: bicubic; /* 2 */ + } +} + +/** + * Correct overflow not hidden in IE 9/10/11. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Grouping content + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari. + */ + +figure { + margin: 1em 40px; +} + +/** + * Address differences between Firefox and other browsers. + */ + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +/** + * Contain overflow in all browsers. + */ + +pre { + overflow: auto; +} + +/** + * Address odd `em`-unit font size rendering in all browsers. + * Correct font family set oddly in IE 6, Safari 4/5, and Chrome. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + @if $legacy_browser_support { + _font-family: 'courier new', monospace; + } + font-size: 1em; +} + +/* Forms + ========================================================================== */ + +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ + +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + * 4. Improves appearance and consistency in all browsers. + */ + +button, +input, +optgroup, +select, +textarea { + color: inherit; /* 1 */ + font: inherit; /* 2 */ + margin: 0; /* 3 */ + @if $legacy_browser_support { + vertical-align: baseline; /* 3 */ + *vertical-align: middle; /* 3 */ + } +} + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ + +button { + overflow: visible; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + * 4. Removes inner spacing in IE 7 without affecting normal text inputs. + * Known issue: inner spacing remains in IE 6. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ + @if $legacy_browser_support { + *overflow: visible; /* 4 */ + } +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +input { + line-height: normal; +} + +/** + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + * Known issue: excess padding remains in IE 6. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ + @if $legacy_browser_support { + *height: 13px; /* 3 */ + *width: 13px; /* 3 */ + } +} + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + * 3. Corrects text not wrapping in Firefox 3. + * 4. Corrects alignment displayed oddly in IE 6/7. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ + @if $legacy_browser_support { + white-space: normal; /* 3 */ + *margin-left: -7px; /* 4 */ + } +} + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ + +textarea { + overflow: auto; +} + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ + +optgroup { + font-weight: bold; +} + +/* Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { + padding: 0; +} diff --git a/docs/template/html/css/scss/_object.scss b/docs/template/html/css/scss/_object.scss new file mode 100644 index 00000000000..22eebd87d03 --- /dev/null +++ b/docs/template/html/css/scss/_object.scss @@ -0,0 +1,89 @@ +.section-specification { + table { + width: auto; + + th { + text-align: left; + } + } +} + +.method-title { + margin-left: -15px; + margin-bottom: 8px; + transition: margin-left .3s ease-out; + + .section-method.hide & { + margin-left: 0; + } + + code { + font-weight: 400; + font-size: .85em; + } +} + +.method-info { + background: $object-background; + border-bottom: 1px solid $object-border; + margin: 0 -25px; + padding: 20px 25px 0 25px; + transition: height .3s ease-out; + + position: relative; + + .pointy-thing { + background: $content-background; + height: 10px; + border-bottom: 1px solid $object-border; + margin: -20px -25px 16px -25px; + + &:before { + display: inline-block; + content: ""; + + background: $object-background; + border: 1px solid $object-border; + border-bottom: 0; + border-right: 0; + + position: absolute; + left: 21px; + top: 3px; + width: 12px; + height: 12px; + transform: rotate(45deg); + } + } + + .method-subsection { + margin-bottom: 15px; + + .argument-name { + width: 1px; + text-align: right; + + code { + color: #808080; + font-style: italic; + font-weight: 400; + } + } + } +} + +.section-method { + &.hide .method-info { + height: 0 !important; + overflow: hidden; + display: none; + } + + &.hide.animating .method-info { + display: block; + } + + &.animating .method-info { + overflow: hidden; + } +} diff --git a/docs/template/html/css/scss/_print.scss b/docs/template/html/css/scss/_print.scss new file mode 100644 index 00000000000..61bdf99f868 --- /dev/null +++ b/docs/template/html/css/scss/_print.scss @@ -0,0 +1,42 @@ +@media print { + body { + background: #fff; + padding: 8px; + } + + header { + position: static; + background: #fff; + color: #000; + } + + aside { + display: none; + } + + .container { + max-width: none; + padding: 0; + } + + article { + margin-top: 0; + + #content { + border: 0; + background: #fff; + padding: 15px 0 0 0; + + .title { + margin-top: 0; + padding-top: 0; + } + } + } + + .method-info { + &, & .pointy-thing { + background: #fff; + } + } +} diff --git a/docs/template/html/css/scss/_variables.scss b/docs/template/html/css/scss/_variables.scss new file mode 100644 index 00000000000..cbaff3cf5c2 --- /dev/null +++ b/docs/template/html/css/scss/_variables.scss @@ -0,0 +1,11 @@ +$body-font: -apple-system-font, "Helvetica Neue", Helvetica, sans-serif; +$code-font: "Source Code Pro", Monaco, Menlo, Consolas, monospace; + +$body-background: #f2f2f2; +$content-background: #fff; +$content-border: #e9e9e9; +$tint-color: #08c; +$object-background: #f9f9f9; +$object-border: #e9e9e9; + +$mobile-max-width: 650px; diff --git a/docs/template/html/css/scss/_xcode.scss b/docs/template/html/css/scss/_xcode.scss new file mode 100644 index 00000000000..340b1f6b804 --- /dev/null +++ b/docs/template/html/css/scss/_xcode.scss @@ -0,0 +1,29 @@ +.xcode { + header, aside { + display: none; + } + + .container { + padding: 0; + } + + article { + margin-top: 0; + + #content { + border: 0; + margin: 0; + } + } + + .method-info { + &, .section-method.hide & { + max-height: auto; + overflow: visible; + + &.hiding { + display: block; + } + } + } +} diff --git a/docs/template/html/css/scss/style.scss b/docs/template/html/css/scss/style.scss new file mode 100644 index 00000000000..648a6086bad --- /dev/null +++ b/docs/template/html/css/scss/style.scss @@ -0,0 +1 @@ +@import "variables", "normalize", "layout", "index", "object", "print", "xcode"; diff --git a/docs/template/html/css/style.css b/docs/template/html/css/style.css new file mode 100644 index 00000000000..2e0648e3f22 --- /dev/null +++ b/docs/template/html/css/style.css @@ -0,0 +1,2 @@ +html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}*{box-sizing:border-box}.clear{clear:both}.clearfix:before,.container:before,article #content:before,article #content footer:before,.clearfix:after,.container:after,article #content:after,article #content footer:after{clear:both;display:table;content:""}.xcode .hide-in-xcode{display:none}body{font:62.5% -apple-system-font,"Helvetica Neue",Helvetica,sans-serif;background:#f2f2f2}h1,h2,h3{font-weight:300;color:gray}h1{font-size:2em;color:#000}h4{font-size:13px;line-height:1.5;margin:21px 0 0}a{color:#08c;text-decoration:none}pre,code{font-family:Source Code Pro,Monaco,Menlo,Consolas,monospace;word-wrap:break-word}pre>code,.method-declaration code{display:inline-block;font-size:.85em;padding:4px 0 4px 10px;border-left:5px solid rgba(0,155,51,.2)}pre>code:before,.method-declaration code:before{content:"Objective-C";display:block;font:9px/1 -apple-system-font,"Helvetica Neue",Helvetica,sans-serif;color:#009b33;text-transform:uppercase;letter-spacing:2px;padding-bottom:6px}pre>code{font-size:inherit}table,th,td{border:1px solid #e9e9e9}table{width:100%}th,td{padding:7px}th>:first-child,td>:first-child{margin-top:0}th>:last-child,td>:last-child{margin-bottom:0}.container{max-width:980px;padding:0 10px;margin:0 auto}@media(max-width:650px){.container{padding:0}}header{position:fixed;top:0;left:0;width:100%;z-index:2;background:#414141;color:#fff;font-size:1.1em;line-height:25px;letter-spacing:.05em}header #library-title{float:left}header #developer-home{float:right}header h1{font-size:inherit;font-weight:inherit;margin:0}header p{margin:0}header h1,header a{color:inherit}@media(max-width:650px){header{position:absolute}header .container{padding:0 10px}}aside{position:fixed;top:25px;left:0;width:100%;height:25px;z-index:2;font-size:1.1em}aside #header-buttons{background:rgba(255,255,255,.8);margin:0 1px;padding:0;list-style:none;text-align:right;line-height:32px}aside #header-buttons li{display:inline-block;cursor:pointer;padding:0 10px}aside #header-buttons label,aside #header-buttons select{cursor:inherit}aside #header-buttons #on-this-page{position:relative}aside #header-buttons #on-this-page .chevron{display:inline-block;width:14px;height:4px;position:relative}aside #header-buttons #on-this-page .chevron .chevy{background:#878787;height:2px;position:absolute;width:10px}aside #header-buttons #on-this-page .chevron .chevy.chevron-left{left:0;-webkit-transform:rotateZ(45deg) scale(.6);transform:rotateZ(45deg) scale(.6)}aside #header-buttons #on-this-page .chevron .chevy.chevron-right{right:0;-webkit-transform:rotateZ(-45deg) scale(.6);transform:rotateZ(-45deg) scale(.6)}aside #header-buttons #on-this-page #jump-to{opacity:0;filter:alpha(opacity=0);font-size:16px;position:absolute;top:5px;left:0;width:100%;height:100%}article{margin-top:25px}article #content{background:#fff;border:1px solid #e9e9e9;padding:15px 25px 30px;font-size:1.4em;line-height:1.45;position:relative}@media(max-width:650px){article #content{padding:15px 10px 20px}}article #content .navigation-top{position:absolute;top:15px;right:25px}article #content .title{margin:21px 0 0;padding:15px 0}article #content p{color:#414141;margin:0 0 15px}article #content th p:last-child,article #content td p:last-child{margin-bottom:0}article #content main ul{list-style:none;margin-left:24px;margin-bottom:12px;padding:0}article #content main ul li{position:relative;padding-left:1.3em}article #content main ul li:before{content:"\02022";color:#414141;font-size:1.08em;line-height:1;position:absolute;left:0;padding-top:2px}article #content footer .footer-copyright{margin:70px 25px 10px 0}article #content footer p{font-size:.71em;color:#a0a0a0}.index-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}@media(max-width:650px){.index-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}}.index-container .index-column{-webkit-box-flex:1;-webkit-flex:1 1 33%;-ms-flex:1 1 33%;flex:1 1 33%}.section-specification table{width:auto}.section-specification table th{text-align:left}.method-title{margin-left:-15px;margin-bottom:8px;-webkit-transition:margin-left .3s ease-out;transition:margin-left .3s ease-out}.section-method.hide .method-title{margin-left:0}.method-title code{font-weight:400;font-size:.85em}.method-info{background:#f9f9f9;border-bottom:1px solid #e9e9e9;margin:0 -25px;padding:20px 25px 0;-webkit-transition:height .3s ease-out;transition:height .3s ease-out;position:relative}.method-info .pointy-thing{background:#fff;height:10px;border-bottom:1px solid #e9e9e9;margin:-20px -25px 16px}.method-info .pointy-thing:before{display:inline-block;content:"";background:#f9f9f9;border:1px solid #e9e9e9;border-bottom:0;border-right:0;position:absolute;left:21px;top:3px;width:12px;height:12px;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg)}.method-info .method-subsection{margin-bottom:15px}.method-info .method-subsection .argument-name{width:1px;text-align:right}.method-info .method-subsection .argument-name code{color:gray;font-style:italic;font-weight:400}.section-method.hide .method-info{height:0!important;overflow:hidden;display:none}.section-method.hide.animating .method-info{display:block}.section-method.animating .method-info{overflow:hidden}@media print{body{background:#fff;padding:8px}header{position:static;background:#fff;color:#000}aside{display:none}.container{max-width:none;padding:0}article{margin-top:0}article #content{border:0;background:#fff;padding:15px 0 0}article #content .title{margin-top:0;padding-top:0}.method-info,.method-info .pointy-thing{background:#fff}}.xcode header,.xcode aside{display:none}.xcode .container{padding:0}.xcode article{margin-top:0}.xcode article #content{border:0;margin:0}.xcode .section-method.hide .method-info,.xcode .section-method.hide.animating .method-info,.xcode .section-method.animating .method-info{height:auto!important;overflow:visible;display:block}.xcode .section-method.hide .method-title{margin-left:-15px} +/*# sourceMappingURL=to.css.map */ \ No newline at end of file diff --git a/docs/template/html/document-template.html b/docs/template/html/document-template.html new file mode 100755 index 00000000000..6875f3cf818 --- /dev/null +++ b/docs/template/html/document-template.html @@ -0,0 +1,75 @@ + + + + + + {{page.title}} + + + + {{#strings.appledocData}}{{/strings.appledocData}} + + +
+ +
+ + + +
+
+
+
+

{{page.title}}

+ + {{#object.comment}}{{#longDescription}}{{>GBCommentComponentsList}}{{/longDescription}}{{/object.comment}} + +
+ +
+
+
+
+
+ + + + + + +Section GBCommentComponentsList +{{#components}}{{>GBCommentComponent}}{{/components}} +EndSection + +Section GBCommentComponent +{{&htmlValue}} +EndSection + +Section Navigation +
  • Home
  • +EndSection diff --git a/docs/template/html/hierarchy-template.html b/docs/template/html/hierarchy-template.html new file mode 100755 index 00000000000..a9126b6c20c --- /dev/null +++ b/docs/template/html/hierarchy-template.html @@ -0,0 +1,110 @@ + + + + + + {{page.title}} + + + + {{#strings.appledocData}}{{/strings.appledocData}} + + +
    + +
    + + + +
    +
    +
    +
    +

    {{page.title}}

    + + {{#hasClasses}} +
    +

    {{strings.hierarchyPage.classesTitle}}

    + {{>Classes}} +
    + {{/hasClasses}} + + {{#hasProtocolsOrCategories}} +
    + {{#hasProtocols}} +

    {{strings.hierarchyPage.protocolsTitle}}

    +
      + {{#protocols}} +
    • {{title}}
    • + {{/protocols}} +
    + {{/hasProtocols}} + {{#hasConstants}} +

    {{strings.hierarchyPage.constantsTitle}}

    +
      + {{#constants}} +
    • {{title}}
    • + {{/constants}} +
    + {{/hasConstants}} + {{#hasCategories}} +

    {{strings.hierarchyPage.categoriesTitle}}

    +
      + {{#categories}} +
    • {{title}}
    • + {{/categories}} +
    + {{/hasCategories}} +
    + {{/hasProtocolsOrCategories}} + +
    + +
    +
    +
    +
    +
    + + + + + +Section Classes +{{#hasClasses}} + +{{/hasClasses}} +EndSection + +Section Navigation +
  • Home
  • +EndSection diff --git a/docs/template/html/img/button_bar_background.png b/docs/template/html/img/button_bar_background.png new file mode 100644 index 00000000000..71d1019bc0c Binary files /dev/null and b/docs/template/html/img/button_bar_background.png differ diff --git a/docs/template/html/img/disclosure.png b/docs/template/html/img/disclosure.png new file mode 100644 index 00000000000..4c5cbf44560 Binary files /dev/null and b/docs/template/html/img/disclosure.png differ diff --git a/docs/template/html/img/disclosure_open.png b/docs/template/html/img/disclosure_open.png new file mode 100644 index 00000000000..82396fed296 Binary files /dev/null and b/docs/template/html/img/disclosure_open.png differ diff --git a/docs/template/html/img/library_background.png b/docs/template/html/img/library_background.png new file mode 100644 index 00000000000..3006248afe8 Binary files /dev/null and b/docs/template/html/img/library_background.png differ diff --git a/docs/template/html/img/title_background.png b/docs/template/html/img/title_background.png new file mode 100644 index 00000000000..846e4968d04 Binary files /dev/null and b/docs/template/html/img/title_background.png differ diff --git a/docs/template/html/index-template.html b/docs/template/html/index-template.html new file mode 100755 index 00000000000..ecede052912 --- /dev/null +++ b/docs/template/html/index-template.html @@ -0,0 +1,129 @@ + + + + + + {{page.title}} + + + + {{#strings.appledocData}}{{/strings.appledocData}} + + +
    + +
    + + + +
    +
    +
    +
    +

    {{page.title}}

    + + {{#indexDescription}} +
    + {{#comment}} + {{#hasLongDescription}} + {{#longDescription}}{{#components}}{{&htmlValue}}{{/components}}{{/longDescription}} + {{/hasLongDescription}} + {{/comment}} +
    + {{/indexDescription}} + +
    + {{#hasDocs}} +
    +

    {{page.docsTitle}}

    + +
    + {{/hasDocs}} + + {{#hasClasses}} +
    +

    {{strings.indexPage.classesTitle}}

    +
      + {{#classes}} +
    • {{title}}
    • + {{/classes}} +
    +
    + {{/hasClasses}} + + {{#hasProtocolsOrCategories}} +
    + {{#hasProtocols}} +

    {{strings.indexPage.protocolsTitle}}

    +
      + {{#protocols}} +
    • {{title}}
    • + {{/protocols}} +
    + {{/hasProtocols}} + + {{#hasConstants}} +

    {{strings.indexPage.constantsTitle}}

    +
      + {{#constants}} +
    • {{title}}
    • + {{/constants}} +
    + {{/hasConstants}} + + {{#hasCategories}} +

    {{strings.indexPage.categoriesTitle}}

    +
      + {{#categories}} +
    • {{title}}
    • + {{/categories}} +
    + {{/hasCategories}} +
    + {{/hasProtocolsOrCategories}} +
    + +
    + +
    +
    +
    +
    +
    + + + + + +Section Navigation +
  • Hierarchy
  • +EndSection diff --git a/docs/template/html/js/script.js b/docs/template/html/js/script.js new file mode 100644 index 00000000000..cff22145b9a --- /dev/null +++ b/docs/template/html/js/script.js @@ -0,0 +1,71 @@ +function $() { + return document.querySelector.apply(document, arguments); +} + +if (navigator.userAgent.indexOf("Xcode") != -1) { + document.documentElement.classList.add("xcode"); +} + +var jumpTo = $("#jump-to"); + +if (jumpTo) { + jumpTo.addEventListener("change", function(e) { + location.hash = this.options[this.selectedIndex].value; + }); +} + +function hashChanged() { + if (/^#\/\/api\//.test(location.hash)) { + var element = document.querySelector("a[name='" + location.hash.substring(1) + "']"); + + if (!element) { + return; + } + + element = element.parentNode; + + element.classList.remove("hide"); + fixScrollPosition(element); + } +} + +function fixScrollPosition(element) { + var scrollTop = element.offsetTop - 150; + document.documentElement.scrollTop = scrollTop; + document.body.scrollTop = scrollTop; +} + +[].forEach.call(document.querySelectorAll(".section-method"), function(element) { + element.classList.add("hide"); + + element.querySelector(".method-title a").addEventListener("click", function(e) { + var info = element.querySelector(".method-info"), + infoContainer = element.querySelector(".method-info-container"); + + element.classList.add("animating"); + info.style.height = (infoContainer.clientHeight + 40) + "px"; + fixScrollPosition(element); + element.classList.toggle("hide"); + if (element.classList.contains("hide")) { + e.preventDefault(); + } + setTimeout(function() { + element.classList.remove("animating"); + }, 300); + }); +}); + +window.addEventListener("hashchange", hashChanged); +hashChanged(); + +// firebase analytics +!function(){ + var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","group","track","ready","alias","page","once","off","on"];analytics.factory=function(t){return function(){var e=Array.prototype.slice.call(arguments);e.unshift(t);analytics.push(e);return analytics}};for(var t=0;t + + + + + {{page.title}} + + + + {{#strings.appledocData}}{{/strings.appledocData}} + + +
    + +
    + + + +
    +
    +
    +
    +

    {{page.title}}

    + + {{#page.specifications}} + {{#used}}
    {{/used}} + {{#values}}{{>ObjectSpecification}}{{/values}} + {{#used}}
    {{/used}} + {{/page.specifications}} + + {{#object.comment}} + {{#hasLongDescription}} +
    + +

    {{strings.objectOverview.title}}

    + {{#longDescription}}{{>GBCommentComponentsList}}{{/longDescription}} +
    + {{/hasLongDescription}} + {{/object.comment}} + + {{#object.methods}} + {{#hasSections}} +
    + + {{#sections}} + + {{#sectionName}}{{/sectionName}} + {{>TaskTitle}} +
    + {{#methods}}{{>Method}}{{/methods}} +
    + {{/sections}} +
    + {{/hasSections}} + {{/object.methods}} + + {{#typedefEnum}} +

    {{nameOfEnum}}

    + {{#comment}} + {{#hasLongDescription}} +
    + {{#longDescription}}{{>GBCommentComponentsList}}{{/longDescription}} +
    + {{/hasLongDescription}} + {{/comment}} +
    + + {{#constants}} +

    Definition

    + typedef {{enumStyle}}({{enumPrimitive}}, {{nameOfEnum}} ) {
    + {{#constants}} +    {{name}}{{#hasAssignedValue}} = {{assignedValue}}{{/hasAssignedValue}},
    + {{/constants}} + };
    + {{/constants}} +
    + {{#constants}} +
    +

    Constants

    +
    + {{#constants}} + {{>Constant}} + {{/constants}} +
    +
    + {{/constants}} + + {{#comment}} + {{#hasAvailability}} +
    +

    {{strings.objectMethods.availability}}

    + {{#availability}}{{>GBCommentComponentsList}}{{/availability}} +
    + {{/hasAvailability}} + + {{#hasRelatedItems}} +
    +

    {{strings.objectMethods.seeAlsoTitle}}

    +
      + {{#relatedItems.components}} +
    • {{>GBCommentComponent}}
    • + {{/relatedItems.components}} +
    +
    + {{/hasRelatedItems}} + + {{#prefferedSourceInfo}} +
    +

    {{strings.objectMethods.declaredInTitle}}

    +

    {{filename}}

    +
    + {{/prefferedSourceInfo}} + {{/comment}} + {{/typedefEnum}} + + {{#typedefBlock}} + +

    {{strings.objectMethods.blockDefTitle}}

    + {{>BlocksDefList}} + {{/typedefBlock}} +
    + +
    + +
    +
    +
    +
    + + + + + + +Section Method +
    + +

    {{>TaskMethod}}

    + +
    +
    + +
    + {{#comment}} + {{#hasShortDescription}} +
    + {{#shortDescription}}{{>GBCommentComponent}}{{/shortDescription}} +
    + {{/hasShortDescription}} + {{/comment}} + +
    {{>MethodDeclaration}}
    + + {{#comment}} + {{#hasMethodParameters}} +
    +

    {{strings.objectMethods.parametersTitle}}

    + + {{#methodParameters}} + + + + + {{/methodParameters}} +
    {{argumentName}}{{#argumentDescription}}{{>GBCommentComponentsList}}{{/argumentDescription}}
    +
    + {{/hasMethodParameters}} + + {{#hasMethodResult}} +
    +

    {{strings.objectMethods.resultTitle}}

    + {{#methodResult}}{{>GBCommentComponentsList}}{{/methodResult}} +
    + {{/hasMethodResult}} + + {{#hasAvailability}} +
    +

    {{strings.objectMethods.availability}}

    + {{#availability}}{{>GBCommentComponentsList}}{{/availability}} +
    + {{/hasAvailability}} + + {{#hasLongDescription}} +
    +

    {{strings.objectMethods.discussionTitle}}

    + {{#longDescription}}{{>GBCommentComponentsList}}{{/longDescription}} +
    + {{/hasLongDescription}} + + {{#hasMethodExceptions}} +
    +

    {{strings.objectMethods.exceptionsTitle}}

    + + {{#methodExceptions}} + + + + + {{/methodExceptions}} +
    {{argumentName}}{{#argumentDescription}}{{>GBCommentComponentsList}}{{/argumentDescription}}
    +
    + {{/hasMethodExceptions}} + + {{#hasRelatedItems}} +
    +

    {{strings.objectMethods.seeAlsoTitle}}

    +
      + {{#relatedItems.components}} +
    • {{>GBCommentComponent}}
    • + {{/relatedItems.components}} +
    +
    + {{/hasRelatedItems}} + + {{#prefferedSourceInfo}} +
    +

    {{strings.objectMethods.declaredInTitle}}

    +

    {{filename}}

    +
    + {{/prefferedSourceInfo}} + {{/comment}} +
    +
    +
    +EndSection + +Section MethodDeclaration +{{#formattedComponents}}{{#emphasized}}{{/emphasized}}{{#href}}{{/href}}{{value}}{{#href}}{{/href}}{{#emphasized}}{{/emphasized}}{{/formattedComponents}} +EndSection + + +Section TaskTitle +{{#hasMultipleSections}}

    {{#sectionName}}{{.}}{{/sectionName}}{{^sectionName}}{{strings.objectTasks.otherMethodsSectionName}}{{/sectionName}}

    {{/hasMultipleSections}} +{{^hasMultipleSections}}{{#sectionName}}

    {{.}}

    {{/sectionName}}{{/hasMultipleSections}} +EndSection + +Section TaskMethod +{{>TaskSelector}} +{{#isRequired}}{{strings.objectTasks.requiredMethod}}{{/isRequired}} +EndSection + +Section TaskSelector +{{#isInstanceMethod}}–{{/isInstanceMethod}}{{#isClassMethod}}+{{/isClassMethod}}{{#isProperty}} {{/isProperty}} {{methodSelector}} +EndSection + + +Section GBCommentComponentsList +{{#components}}{{>GBCommentComponent}}{{/components}} +EndSection + +Section BlocksDefList +

    {{nameOfBlock}}

    +{{#comment}} +{{#hasShortDescription}} +
    + {{#shortDescription}}{{>GBCommentComponent}}{{/shortDescription}} +
    +{{/hasShortDescription}} +{{/comment}} + +typedef {{returnType}} (^{{nameOfBlock}}) ({{&htmlParameterList}}) + + {{#comment}} + {{#hasLongDescription}} +
    +

    {{strings.objectMethods.discussionTitle}}

    + {{#longDescription}}{{>GBCommentComponentsList}}{{/longDescription}} +
    + {{/hasLongDescription}} + {{/comment}} + + {{#comment}} + {{#hasAvailability}} +
    +

    {{strings.objectMethods.availability}}

    + {{#availability}}{{>GBCommentComponentsList}}{{/availability}} +
    + {{/hasAvailability}} + + {{#hasRelatedItems}} +
    +

    {{strings.objectMethods.seeAlsoTitle}}

    +
      + {{#relatedItems.components}} +
    • {{>GBCommentComponent}}
    • + {{/relatedItems.components}} +
    +
    + {{/hasRelatedItems}} + + {{#prefferedSourceInfo}} +
    +

    {{strings.objectMethods.declaredInTitle}}

    + {{filename}}
    +
    + {{/prefferedSourceInfo}} + {{/comment}} + EndSection + +Section Constant +
    {{name}}
    +
    +{{#comment}} +{{#hasShortDescription}} +{{#shortDescription}}{{>GBCommentComponent}}{{/shortDescription}} +{{/hasShortDescription}} + +{{#hasAvailability}} +

    Available in {{#availability}}{{#components}}{{stringValue}}{{/components}}{{/availability}}

    +{{/hasAvailability}} + +{{/comment}} + {{#prefferedSourceInfo}} +

    + {{strings.objectMethods.declaredInTitle}} {{filename}}. +

    + {{/prefferedSourceInfo}} +
    +EndSection + +Section GBCommentComponent +{{&htmlValue}} +EndSection + +Section ObjectSpecification + + {{title}} + {{#values}}{{#href}}{{/href}}{{string}}{{#href}}{{/href}}{{&delimiter}}{{/values}} + +EndSection + + +Section Navigation +
  • Index
  • +
  • Hierarchy
  • +EndSection + +Section JumpTo + +EndSection + +Section TableOfContents +{{#object.comment}} +
  • {{strings.objectOverview.title}}
  • +{{/object.comment}} + +{{#object.methods}} +{{#hasSections}} +
  • {{strings.objectTasks.title}}
  • +{{/hasSections}} +{{/object.methods}} + +{{#object.methods}} +{{#hasProperties}} +
  • {{strings.objectMethods.propertiesTitle}}
  • +{{/hasProperties}} + +{{#hasClassMethods}} +
  • {{strings.objectMethods.classMethodsTitle}}
  • +{{/hasClassMethods}} + +{{#hasInstanceMethods}} +
  • {{strings.objectMethods.instanceMethodsTitle}}
  • +{{/hasInstanceMethods}} +{{/object.methods}} +EndSection diff --git a/docs/template/publish/xml-template.xml b/docs/template/publish/xml-template.xml new file mode 100644 index 00000000000..cd79c3e05fd --- /dev/null +++ b/docs/template/publish/xml-template.xml @@ -0,0 +1,4 @@ + + ${DOCSET_FEED_VERSION} + ${DOCSET_PACKAGE_URL} + \ No newline at end of file