├── .gitignore ├── .swift-version ├── .travis.yml ├── CHANGELOG.md ├── Images ├── 5th.PNG └── demo.gif ├── LICENSE ├── Package.swift ├── README.md ├── YNExpandableCell.podspec ├── YNExpandableCell.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ └── YNExpandableCell.xcscheme ├── YNExpandableCell ├── Info.plist ├── YNExpandableCell.h ├── YNExpandableCell.swift ├── YNExpandableCell.xcassets │ ├── Contents.json │ ├── yn_nor.imageset │ │ ├── Contents.json │ │ ├── filter_type_more_nor.png │ │ ├── filter_type_more_nor@2x.png │ │ └── filter_type_more_nor@3x.png │ └── yn_sel.imageset │ │ ├── Contents.json │ │ ├── filter_type_close_nor.png │ │ ├── filter_type_close_nor@2x.png │ │ └── filter_type_close_nor@3x.png ├── YNExpandableDeprecated.swift ├── YNTableView.swift ├── YNTableViewCell.swift ├── YNTableViewDelegate.swift └── YNTableViewExtenstion.swift └── YNExpandableCellDemo ├── AppDelegate.swift ├── Assets.xcassets └── AppIcon.appiconset │ ├── Contents.json │ ├── Icon-App-20x20@1x.png │ ├── Icon-App-20x20@2x.png │ ├── Icon-App-20x20@3x.png │ ├── Icon-App-29x29@1x.png │ ├── Icon-App-29x29@2x.png │ ├── Icon-App-29x29@3x.png │ ├── Icon-App-40x40@1x.png │ ├── Icon-App-40x40@2x.png │ ├── Icon-App-40x40@3x.png │ ├── Icon-App-57x57@1x.png │ ├── Icon-App-57x57@2x.png │ ├── Icon-App-60x60@2x.png │ ├── Icon-App-60x60@3x.png │ ├── Icon-App-72x72@1x.png │ ├── Icon-App-72x72@2x.png │ ├── Icon-App-76x76@1x.png │ ├── Icon-App-76x76@2x.png │ ├── Icon-App-83.5x83.5@2x.png │ ├── Icon-Small-50x50@1x.png │ └── Icon-Small-50x50@2x.png ├── Base.lproj ├── LaunchScreen.xib └── Main.storyboard ├── Info.plist ├── ViewController.swift ├── YNExpandableCellEx.xib ├── YNExpandableCells.swift ├── YNSegmentCell.xib └── YNSliderCell.xib /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | ## Playgrounds 31 | timeline.xctimeline 32 | playground.xcworkspace 33 | 34 | # Swift Package Manager 35 | # 36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 37 | # Packages/ 38 | .build/ 39 | 40 | # CocoaPods 41 | # 42 | # We recommend against adding the Pods directory to your .gitignore. However 43 | # you should judge for yourself, the pros and cons are mentioned at: 44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 45 | # 46 | # Pods/ 47 | 48 | # Carthage 49 | # 50 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 51 | # Carthage/Checkouts 52 | 53 | Carthage/Build 54 | 55 | # fastlane 56 | # 57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 58 | # screenshots whenever they are needed. 59 | # For more information about the recommended setup visit: 60 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 61 | 62 | fastlane/report.xml 63 | fastlane/Preview.html 64 | fastlane/screenshots 65 | fastlane/test_output 66 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 4.2 -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode8 3 | script: 4 | - xcodebuild -scheme 'YNExpandableCell' -sdk iphonesimulator CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO test | xcpretty -c 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Updates 2 | ## [v1.1.0](https://github.com/younatics/YNExpandableCell/releases/tag/1.1.0) 3 | * Bug fixed 4 | 5 | ## [v1.0.1](https://github.com/younatics/YNExpandableCell/releases/tag/1.0.1) 6 | * Bug fixed 7 | 8 | ## [v1.0.0](https://github.com/younatics/YNExpandableCell/releases/tag/1.0.0) 9 | * Add `func tableView(_ tableView: YNTableView, expandCellWithHeightAt indexPath: IndexPath) -> YNTableViewCell?` method 10 | 11 | ## [v0.9.0](https://github.com/younatics/YNExpandableCell/releases/tag/0.9.0) 12 | * Add UITest 13 | 14 | ## [v0.8.0](https://github.com/younatics/YNExpandableCell/releases/tag/0.8.0) 15 | * Change `didSelectRowAt` method 16 | * Change `didDeselectRowAt` method 17 | 18 | ## [v0.7.0](https://github.com/younatics/YNExpandableCell/releases/tag/0.7.0) 19 | * Add `expandAll` method 20 | * Add `collapseAll` method 21 | 22 | ## [v0.6.0](https://github.com/younatics/YNExpandableCell/releases/tag/0.6.0) 23 | * Add override tableview `reloadData` method 24 | * Fix bug 25 | 26 | ## [v0.5.1](https://github.com/younatics/YNExpandableCell/releases/tag/0.5.1) 27 | * Update Readme 28 | 29 | ## [v0.5.0](https://github.com/younatics/YNExpandableCell/releases/tag/0.5.0) 30 | * Add didDeselectRowAt method in `YNDelegate` [#1](https://github.com/younatics/YNExpandableCell/issues/1) 31 | * Change didSelectRowAt method to optional 32 | 33 | ## [v0.4.0](https://github.com/younatics/YNExpandableCell/releases/tag/0.4.0) 34 | * Public to Open class [#3](https://github.com/younatics/YNExpandableCell/issues/3) 35 | 36 | ## [v0.3.1](https://github.com/younatics/YNExpandableCell/releases/tag/0.3.1) 37 | * Change podspec image 38 | 39 | ## [v0.3.0](https://github.com/younatics/YNExpandableCell/releases/tag/0.3.0) 40 | * Add didSelectRowAt method in `YNDelegate` [#1](https://github.com/younatics/YNExpandableCell/issues/1) 41 | 42 | ## [v0.2.0](https://github.com/younatics/YNExpandableCell/releases/tag/0.2.0) 43 | * Update docs 44 | 45 | ## [v0.1.1](https://github.com/younatics/YNExpandableCell/releases/tag/0.1.1) 46 | * Update pod spec 47 | 48 | ## [v0.1.0](https://github.com/younatics/YNExpandableCell/releases/tag/0.1.0) 49 | * Initial Pod Commit 50 | 51 | -------------------------------------------------------------------------------- /Images/5th.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/Images/5th.PNG -------------------------------------------------------------------------------- /Images/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/Images/demo.gif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Seungyoun Yi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | import PackageDescription 2 | 3 | let package = Package( 4 | name: "YNExpandableCell" 5 | ) 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # USE [ExpandableCell](https://github.com/younatics/ExpandableCell). New version of this library. 2 | # YNExpandableCell 3 | 4 | [![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/sindresorhus/awesome) 5 | [![Version](https://img.shields.io/cocoapods/v/YNExpandableCell.svg?style=flat)](http://cocoapods.org/pods/YNExpandableCell) 6 | [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 7 | [![CocoaPods](https://img.shields.io/cocoapods/metrics/doc-percent/YNExpandableCell.svg)](http://cocoadocs.org/docsets/YNExpandableCell) 8 | [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/younatics/YNExpandableCell/blob/master/LICENSE) 9 | [![Build Status](https://travis-ci.org/younatics/YNExpandableCell.svg?branch=master)](https://travis-ci.org/younatics/YNExpandableCell) 10 | [![Platform](https://img.shields.io/cocoapods/p/YNExpandableCell.svg?style=flat)](http://cocoapods.org/pods/YNExpandableCell) 11 | [![Swift 4.2](https://img.shields.io/badge/Swift-4.2-orange.svg?style=flat)](https://developer.apple.com/swift/) 12 | 13 | ## Updates 14 | See [CHANGELOG](https://github.com/younatics/YNExpandableCell/blob/master/CHANGELOG.md) for details 15 | 16 | ## Intoduction 17 | Easiest usage of expandable & collapsible cell for iOS, written in Swift 4.2 You can customize expandable `UITableViewCell` whatever you like. `YNExpandableCell` is made because `insertRows` and `deleteRows` is hard to use. You can just inheirt `YNTableViewDelegate` and add one more method `func tableView(_ tableView: YNTableView, expandCellAt indexPath) -> UITableViewCell?` 18 | 19 | ![demo](Images/demo.gif) 20 | 21 | ## Requirements 22 | 23 | `YNExpandableCell` written in Swift 3. Compatible with iOS 8.0+ 24 | 25 | ## Installation 26 | 27 | ### Cocoapods 28 | 29 | YNExpandableCell is available through [CocoaPods](http://cocoapods.org). To install 30 | it, simply add the following line to your Podfile: 31 | 32 | ```ruby 33 | pod 'YNExpandableCell' 34 | ``` 35 | ### Carthage 36 | ``` 37 | github "younatics/YNExpandableCell" 38 | ``` 39 | ## Usage 40 | ```swift 41 | import YNExpandableCell 42 | ``` 43 | 44 | Make `YNTableView` in Storyboard or in code 45 | ```swift 46 | @IBOutlet var ynTableView: YNTableView! 47 | ``` 48 | 49 | Inherit `YNTableViewDelegate` 50 | ```swift 51 | class ViewController: UIViewController, YNTableViewDelegate 52 | ``` 53 | 54 | Set delegate and register cells 55 | ```swift 56 | self.ynTableView.ynDelegate = self 57 | 58 | let cells = ["YNExpandableCellEx","YNSliderCell","YNSegmentCell"] 59 | self.ynTableView.registerCellsWith(nibNames: cells, and: cells) 60 | self.ynTableView.registerCellsWith(cells: [UITableViewCell.self as AnyClass], and: ["YNNonExpandableCell"]) 61 | ``` 62 | 63 | #### Use one of required method 64 | Set expandable cell in `YNTableViewDelegate` method (Required) 65 | ```swift 66 | func tableView(_ tableView: YNTableView, expandCellAt indexPath: IndexPath) -> UITableViewCell? { 67 | let ynSliderCell = tableView.dequeueReusableCell(withIdentifier: YNSliderCell.ID) as! YNSliderCell 68 | if indexPath.section == 0 && indexPath.row == 1 { 69 | return ynSliderCell 70 | } 71 | return nil 72 | } 73 | ``` 74 | 75 | Set expandable cell with height in `YNTableViewDelegate` method using `YNTableViewCell` object (Required) 76 | ```swift 77 | func tableView(_ tableView: YNTableView, expandCellWithHeightAt indexPath: IndexPath) -> YNTableViewCell? { 78 | let ynSliderCell = YNTableViewCell() 79 | ynSliderCell.cell = tableView.dequeueReusableCell(withIdentifier: YNSliderCell.ID) as! YNSliderCell 80 | ynSliderCell.height = 142 81 | 82 | if indexPath.section == 0 && indexPath.row == 1 { 83 | return ynSliderCell 84 | } 85 | return nil 86 | } 87 | ``` 88 | 89 | Get didSelectRowAt in `YNTableViewDelegate` method (Optional) 90 | ```swift 91 | func tableView(_ tableView: YNTableView, didSelectRowAt indexPath: IndexPath, isExpandableCell: Bool, isExpandedCell: Bool) { 92 | print("Selected Section: \(indexPath.section) Row: \(indexPath.row) isExpandableCell: \(isExpandableCell) isExpandedCell: \(isExpandedCell)") 93 | } 94 | 95 | ``` 96 | 97 | Get didDeselectRowAt in `YNTableViewDelegate` method (Optional) 98 | ```swift 99 | func tableView(_ tableView: YNTableView, didDeselectRowAt indexPath: IndexPath, isExpandableCell: Bool, isExpandedCell: Bool) { 100 | print("Deselected Section: \(indexPath.section) Row: \(indexPath.row) isExpandableCell: \(isExpandableCell) isExpandedCell: \(isExpandedCell)") 101 | } 102 | ``` 103 | 104 | Set basic `UITableViewDataSource`, `UITableViewDelegate` and Done! 105 | 106 | ### Customize 107 | 108 | Expand & Collapse All if you want 109 | ```swift 110 | self.ynTableView.expandAll() 111 | self.ynTableView.collapseAll() 112 | ``` 113 | 114 | Inherit `YNExpandableCell` if you want awesome '+' '-' custom accessory type 115 | ```swift 116 | class YNExpandableCellEx: YNExpandableCell 117 | 118 | // Change normalCustomAccessoryType, selectedCustomAccessoryType Images 119 | ``` 120 | 121 | Cutomize `UITableViewRowAnimation` 122 | ```swift 123 | self.ynTableView.ynTableViewRowAnimation = UITableViewRowAnimation.top 124 | ``` 125 | 126 | Make Extensions for more `UITableViewDelegate` if you need or make pull request for me :) 127 | 128 | ## References 129 | #### Please tell me or make pull request if you use this library in your application :) 130 | #### [@zigbang](https://github.com/zigbang) 131 | #### [MotionBook](https://github.com/younatics/MotionBook) 132 | ## Author 133 | [younatics](https://twitter.com/younatics) 134 | Twitter 135 | 136 | ## License 137 | YNExpandableCell is available under the MIT license. See the LICENSE file for more info. 138 | -------------------------------------------------------------------------------- /YNExpandableCell.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint YNDropDownMenu.podspec' to ensure this is a 3 | # valid spec before submitting. 4 | # 5 | # Any lines starting with a # are optional, but their use is encouraged 6 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | s.name = 'YNExpandableCell' 11 | s.version = '1.2.1' 12 | s.summary = 'Easiest way to expand and collapse cell for iOS with Swift 4.2' 13 | 14 | s.description = <<-DESC 15 | Easiest usage of expandable & collapsible cell for iOS, written in Swift 3. You can customize expandable `UITableViewCell` whatever you like. `YNExpandableCell` is made because `insertRows(at indexPaths, with animation` and `deleteRows(at indexPaths, with animation` is hard to use. You can just inheirt `YNTableViewDelegate` and add one more method `func tableView(_ tableView: YNTableView, expandCellAt indexPath) -> UITableViewCell?` 16 | DESC 17 | 18 | s.homepage = 'https://github.com/younatics/YNExpandableCell' 19 | s.screenshots = 'https://raw.githubusercontent.com/younatics/YNExpandableCell/master/Images/YNExpandableCell.PNG' 20 | s.license = { :type => 'MIT', :file => 'LICENSE' } 21 | s.author = { "Seungyoun Yi" => "younatics@gmail.com" } 22 | 23 | s.source = { :git => 'https://github.com/younatics/YNExpandableCell.git', :tag => s.version.to_s } 24 | s.source_files = 'YNExpandableCell/*.swift' 25 | s.resources = "YNExpandableCell/*.xcassets" 26 | 27 | s.ios.deployment_target = '9.0' 28 | 29 | # s.public_header_files = 'Pod/Classes/**/*.h' 30 | s.frameworks = 'UIKit' 31 | s.requires_arc = true 32 | end 33 | -------------------------------------------------------------------------------- /YNExpandableCell.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 19FE325D1EA7BC9500A4DB5E /* YNExpandableCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 19FE325B1EA7BC9500A4DB5E /* YNExpandableCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 19FE32861EA7BD0C00A4DB5E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FE32791EA7BD0C00A4DB5E /* AppDelegate.swift */; }; 12 | 19FE32871EA7BD0C00A4DB5E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 19FE327A1EA7BD0C00A4DB5E /* Assets.xcassets */; }; 13 | 19FE32881EA7BD0C00A4DB5E /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 19FE327C1EA7BD0C00A4DB5E /* LaunchScreen.xib */; }; 14 | 19FE32891EA7BD0C00A4DB5E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 19FE327E1EA7BD0C00A4DB5E /* Main.storyboard */; }; 15 | 19FE328B1EA7BD0C00A4DB5E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FE32811EA7BD0C00A4DB5E /* ViewController.swift */; }; 16 | 19FE328C1EA7BD0C00A4DB5E /* YNExpandableCellEx.xib in Resources */ = {isa = PBXBuildFile; fileRef = 19FE32821EA7BD0C00A4DB5E /* YNExpandableCellEx.xib */; }; 17 | 19FE328D1EA7BD0C00A4DB5E /* YNExpandableCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FE32831EA7BD0C00A4DB5E /* YNExpandableCells.swift */; }; 18 | 19FE328E1EA7BD0C00A4DB5E /* YNSegmentCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 19FE32841EA7BD0C00A4DB5E /* YNSegmentCell.xib */; }; 19 | 19FE328F1EA7BD0C00A4DB5E /* YNSliderCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 19FE32851EA7BD0C00A4DB5E /* YNSliderCell.xib */; }; 20 | 19FE32901EA7BD2200A4DB5E /* YNExpandableCell.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 19FE32581EA7BC9500A4DB5E /* YNExpandableCell.framework */; }; 21 | 19FE32911EA7BD2200A4DB5E /* YNExpandableCell.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 19FE32581EA7BC9500A4DB5E /* YNExpandableCell.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 22 | 19FE329C1EA7BD6200A4DB5E /* YNExpandableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FE32951EA7BD6200A4DB5E /* YNExpandableCell.swift */; }; 23 | 19FE329D1EA7BD6200A4DB5E /* YNExpandableCell.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 19FE32961EA7BD6200A4DB5E /* YNExpandableCell.xcassets */; }; 24 | 19FE329E1EA7BD6200A4DB5E /* YNExpandableDeprecated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FE32971EA7BD6200A4DB5E /* YNExpandableDeprecated.swift */; }; 25 | 19FE329F1EA7BD6200A4DB5E /* YNTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FE32981EA7BD6200A4DB5E /* YNTableView.swift */; }; 26 | 19FE32A01EA7BD6200A4DB5E /* YNTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FE32991EA7BD6200A4DB5E /* YNTableViewCell.swift */; }; 27 | 19FE32A11EA7BD6200A4DB5E /* YNTableViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FE329A1EA7BD6200A4DB5E /* YNTableViewDelegate.swift */; }; 28 | 19FE32A21EA7BD6200A4DB5E /* YNTableViewExtenstion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FE329B1EA7BD6200A4DB5E /* YNTableViewExtenstion.swift */; }; 29 | /* End PBXBuildFile section */ 30 | 31 | /* Begin PBXContainerItemProxy section */ 32 | 19FE32921EA7BD2200A4DB5E /* PBXContainerItemProxy */ = { 33 | isa = PBXContainerItemProxy; 34 | containerPortal = 19FE324F1EA7BC9500A4DB5E /* Project object */; 35 | proxyType = 1; 36 | remoteGlobalIDString = 19FE32571EA7BC9500A4DB5E; 37 | remoteInfo = YNExpandableCell; 38 | }; 39 | /* End PBXContainerItemProxy section */ 40 | 41 | /* Begin PBXCopyFilesBuildPhase section */ 42 | 19FE32941EA7BD2200A4DB5E /* Embed Frameworks */ = { 43 | isa = PBXCopyFilesBuildPhase; 44 | buildActionMask = 2147483647; 45 | dstPath = ""; 46 | dstSubfolderSpec = 10; 47 | files = ( 48 | 19FE32911EA7BD2200A4DB5E /* YNExpandableCell.framework in Embed Frameworks */, 49 | ); 50 | name = "Embed Frameworks"; 51 | runOnlyForDeploymentPostprocessing = 0; 52 | }; 53 | /* End PBXCopyFilesBuildPhase section */ 54 | 55 | /* Begin PBXFileReference section */ 56 | 19FE32581EA7BC9500A4DB5E /* YNExpandableCell.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = YNExpandableCell.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 19FE325B1EA7BC9500A4DB5E /* YNExpandableCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YNExpandableCell.h; sourceTree = ""; }; 58 | 19FE325C1EA7BC9500A4DB5E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 59 | 19FE32671EA7BCD100A4DB5E /* YNExpandableCellDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = YNExpandableCellDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 60 | 19FE32791EA7BD0C00A4DB5E /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 61 | 19FE327A1EA7BD0C00A4DB5E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 62 | 19FE327D1EA7BD0C00A4DB5E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = LaunchScreen.xib; sourceTree = ""; }; 63 | 19FE327F1EA7BD0C00A4DB5E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Main.storyboard; sourceTree = ""; }; 64 | 19FE32801EA7BD0C00A4DB5E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 65 | 19FE32811EA7BD0C00A4DB5E /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 66 | 19FE32821EA7BD0C00A4DB5E /* YNExpandableCellEx.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = YNExpandableCellEx.xib; sourceTree = ""; }; 67 | 19FE32831EA7BD0C00A4DB5E /* YNExpandableCells.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YNExpandableCells.swift; sourceTree = ""; }; 68 | 19FE32841EA7BD0C00A4DB5E /* YNSegmentCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = YNSegmentCell.xib; sourceTree = ""; }; 69 | 19FE32851EA7BD0C00A4DB5E /* YNSliderCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = YNSliderCell.xib; sourceTree = ""; }; 70 | 19FE32951EA7BD6200A4DB5E /* YNExpandableCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YNExpandableCell.swift; sourceTree = ""; }; 71 | 19FE32961EA7BD6200A4DB5E /* YNExpandableCell.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = YNExpandableCell.xcassets; sourceTree = ""; }; 72 | 19FE32971EA7BD6200A4DB5E /* YNExpandableDeprecated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YNExpandableDeprecated.swift; sourceTree = ""; }; 73 | 19FE32981EA7BD6200A4DB5E /* YNTableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YNTableView.swift; sourceTree = ""; }; 74 | 19FE32991EA7BD6200A4DB5E /* YNTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YNTableViewCell.swift; sourceTree = ""; }; 75 | 19FE329A1EA7BD6200A4DB5E /* YNTableViewDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YNTableViewDelegate.swift; sourceTree = ""; }; 76 | 19FE329B1EA7BD6200A4DB5E /* YNTableViewExtenstion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YNTableViewExtenstion.swift; sourceTree = ""; }; 77 | /* End PBXFileReference section */ 78 | 79 | /* Begin PBXFrameworksBuildPhase section */ 80 | 19FE32541EA7BC9500A4DB5E /* Frameworks */ = { 81 | isa = PBXFrameworksBuildPhase; 82 | buildActionMask = 2147483647; 83 | files = ( 84 | ); 85 | runOnlyForDeploymentPostprocessing = 0; 86 | }; 87 | 19FE32641EA7BCD100A4DB5E /* Frameworks */ = { 88 | isa = PBXFrameworksBuildPhase; 89 | buildActionMask = 2147483647; 90 | files = ( 91 | 19FE32901EA7BD2200A4DB5E /* YNExpandableCell.framework in Frameworks */, 92 | ); 93 | runOnlyForDeploymentPostprocessing = 0; 94 | }; 95 | /* End PBXFrameworksBuildPhase section */ 96 | 97 | /* Begin PBXGroup section */ 98 | 19FE324E1EA7BC9500A4DB5E = { 99 | isa = PBXGroup; 100 | children = ( 101 | 19FE325A1EA7BC9500A4DB5E /* YNExpandableCell */, 102 | 19FE32681EA7BCD100A4DB5E /* YNExpandableCellDemo */, 103 | 19FE32591EA7BC9500A4DB5E /* Products */, 104 | ); 105 | sourceTree = ""; 106 | }; 107 | 19FE32591EA7BC9500A4DB5E /* Products */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 19FE32581EA7BC9500A4DB5E /* YNExpandableCell.framework */, 111 | 19FE32671EA7BCD100A4DB5E /* YNExpandableCellDemo.app */, 112 | ); 113 | name = Products; 114 | sourceTree = ""; 115 | }; 116 | 19FE325A1EA7BC9500A4DB5E /* YNExpandableCell */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | 19FE32951EA7BD6200A4DB5E /* YNExpandableCell.swift */, 120 | 19FE32961EA7BD6200A4DB5E /* YNExpandableCell.xcassets */, 121 | 19FE32971EA7BD6200A4DB5E /* YNExpandableDeprecated.swift */, 122 | 19FE32981EA7BD6200A4DB5E /* YNTableView.swift */, 123 | 19FE32991EA7BD6200A4DB5E /* YNTableViewCell.swift */, 124 | 19FE329A1EA7BD6200A4DB5E /* YNTableViewDelegate.swift */, 125 | 19FE329B1EA7BD6200A4DB5E /* YNTableViewExtenstion.swift */, 126 | 19FE325B1EA7BC9500A4DB5E /* YNExpandableCell.h */, 127 | 19FE325C1EA7BC9500A4DB5E /* Info.plist */, 128 | ); 129 | path = YNExpandableCell; 130 | sourceTree = ""; 131 | }; 132 | 19FE32681EA7BCD100A4DB5E /* YNExpandableCellDemo */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | 19FE32791EA7BD0C00A4DB5E /* AppDelegate.swift */, 136 | 19FE327A1EA7BD0C00A4DB5E /* Assets.xcassets */, 137 | 19FE327B1EA7BD0C00A4DB5E /* Base.lproj */, 138 | 19FE32801EA7BD0C00A4DB5E /* Info.plist */, 139 | 19FE32811EA7BD0C00A4DB5E /* ViewController.swift */, 140 | 19FE32821EA7BD0C00A4DB5E /* YNExpandableCellEx.xib */, 141 | 19FE32831EA7BD0C00A4DB5E /* YNExpandableCells.swift */, 142 | 19FE32841EA7BD0C00A4DB5E /* YNSegmentCell.xib */, 143 | 19FE32851EA7BD0C00A4DB5E /* YNSliderCell.xib */, 144 | ); 145 | path = YNExpandableCellDemo; 146 | sourceTree = ""; 147 | }; 148 | 19FE327B1EA7BD0C00A4DB5E /* Base.lproj */ = { 149 | isa = PBXGroup; 150 | children = ( 151 | 19FE327C1EA7BD0C00A4DB5E /* LaunchScreen.xib */, 152 | 19FE327E1EA7BD0C00A4DB5E /* Main.storyboard */, 153 | ); 154 | path = Base.lproj; 155 | sourceTree = ""; 156 | }; 157 | /* End PBXGroup section */ 158 | 159 | /* Begin PBXHeadersBuildPhase section */ 160 | 19FE32551EA7BC9500A4DB5E /* Headers */ = { 161 | isa = PBXHeadersBuildPhase; 162 | buildActionMask = 2147483647; 163 | files = ( 164 | 19FE325D1EA7BC9500A4DB5E /* YNExpandableCell.h in Headers */, 165 | ); 166 | runOnlyForDeploymentPostprocessing = 0; 167 | }; 168 | /* End PBXHeadersBuildPhase section */ 169 | 170 | /* Begin PBXNativeTarget section */ 171 | 19FE32571EA7BC9500A4DB5E /* YNExpandableCell */ = { 172 | isa = PBXNativeTarget; 173 | buildConfigurationList = 19FE32601EA7BC9500A4DB5E /* Build configuration list for PBXNativeTarget "YNExpandableCell" */; 174 | buildPhases = ( 175 | 19FE32531EA7BC9500A4DB5E /* Sources */, 176 | 19FE32541EA7BC9500A4DB5E /* Frameworks */, 177 | 19FE32551EA7BC9500A4DB5E /* Headers */, 178 | 19FE32561EA7BC9500A4DB5E /* Resources */, 179 | ); 180 | buildRules = ( 181 | ); 182 | dependencies = ( 183 | ); 184 | name = YNExpandableCell; 185 | productName = YNExpandableCell; 186 | productReference = 19FE32581EA7BC9500A4DB5E /* YNExpandableCell.framework */; 187 | productType = "com.apple.product-type.framework"; 188 | }; 189 | 19FE32661EA7BCD100A4DB5E /* YNExpandableCellDemo */ = { 190 | isa = PBXNativeTarget; 191 | buildConfigurationList = 19FE32761EA7BCD100A4DB5E /* Build configuration list for PBXNativeTarget "YNExpandableCellDemo" */; 192 | buildPhases = ( 193 | 19FE32631EA7BCD100A4DB5E /* Sources */, 194 | 19FE32641EA7BCD100A4DB5E /* Frameworks */, 195 | 19FE32651EA7BCD100A4DB5E /* Resources */, 196 | 19FE32941EA7BD2200A4DB5E /* Embed Frameworks */, 197 | ); 198 | buildRules = ( 199 | ); 200 | dependencies = ( 201 | 19FE32931EA7BD2200A4DB5E /* PBXTargetDependency */, 202 | ); 203 | name = YNExpandableCellDemo; 204 | productName = YNExpandableCellDemo; 205 | productReference = 19FE32671EA7BCD100A4DB5E /* YNExpandableCellDemo.app */; 206 | productType = "com.apple.product-type.application"; 207 | }; 208 | /* End PBXNativeTarget section */ 209 | 210 | /* Begin PBXProject section */ 211 | 19FE324F1EA7BC9500A4DB5E /* Project object */ = { 212 | isa = PBXProject; 213 | attributes = { 214 | LastSwiftUpdateCheck = 0830; 215 | LastUpgradeCheck = 1010; 216 | ORGANIZATIONNAME = SeungyounYi; 217 | TargetAttributes = { 218 | 19FE32571EA7BC9500A4DB5E = { 219 | CreatedOnToolsVersion = 8.3.2; 220 | DevelopmentTeam = 4G7K3CN2JU; 221 | LastSwiftMigration = 0830; 222 | ProvisioningStyle = Automatic; 223 | }; 224 | 19FE32661EA7BCD100A4DB5E = { 225 | CreatedOnToolsVersion = 8.3.2; 226 | DevelopmentTeam = 4G7K3CN2JU; 227 | LastSwiftMigration = 0830; 228 | ProvisioningStyle = Automatic; 229 | }; 230 | }; 231 | }; 232 | buildConfigurationList = 19FE32521EA7BC9500A4DB5E /* Build configuration list for PBXProject "YNExpandableCell" */; 233 | compatibilityVersion = "Xcode 3.2"; 234 | developmentRegion = English; 235 | hasScannedForEncodings = 0; 236 | knownRegions = ( 237 | en, 238 | Base, 239 | ); 240 | mainGroup = 19FE324E1EA7BC9500A4DB5E; 241 | productRefGroup = 19FE32591EA7BC9500A4DB5E /* Products */; 242 | projectDirPath = ""; 243 | projectRoot = ""; 244 | targets = ( 245 | 19FE32571EA7BC9500A4DB5E /* YNExpandableCell */, 246 | 19FE32661EA7BCD100A4DB5E /* YNExpandableCellDemo */, 247 | ); 248 | }; 249 | /* End PBXProject section */ 250 | 251 | /* Begin PBXResourcesBuildPhase section */ 252 | 19FE32561EA7BC9500A4DB5E /* Resources */ = { 253 | isa = PBXResourcesBuildPhase; 254 | buildActionMask = 2147483647; 255 | files = ( 256 | 19FE329D1EA7BD6200A4DB5E /* YNExpandableCell.xcassets in Resources */, 257 | ); 258 | runOnlyForDeploymentPostprocessing = 0; 259 | }; 260 | 19FE32651EA7BCD100A4DB5E /* Resources */ = { 261 | isa = PBXResourcesBuildPhase; 262 | buildActionMask = 2147483647; 263 | files = ( 264 | 19FE328F1EA7BD0C00A4DB5E /* YNSliderCell.xib in Resources */, 265 | 19FE32891EA7BD0C00A4DB5E /* Main.storyboard in Resources */, 266 | 19FE32881EA7BD0C00A4DB5E /* LaunchScreen.xib in Resources */, 267 | 19FE32871EA7BD0C00A4DB5E /* Assets.xcassets in Resources */, 268 | 19FE328E1EA7BD0C00A4DB5E /* YNSegmentCell.xib in Resources */, 269 | 19FE328C1EA7BD0C00A4DB5E /* YNExpandableCellEx.xib in Resources */, 270 | ); 271 | runOnlyForDeploymentPostprocessing = 0; 272 | }; 273 | /* End PBXResourcesBuildPhase section */ 274 | 275 | /* Begin PBXSourcesBuildPhase section */ 276 | 19FE32531EA7BC9500A4DB5E /* Sources */ = { 277 | isa = PBXSourcesBuildPhase; 278 | buildActionMask = 2147483647; 279 | files = ( 280 | 19FE32A11EA7BD6200A4DB5E /* YNTableViewDelegate.swift in Sources */, 281 | 19FE329F1EA7BD6200A4DB5E /* YNTableView.swift in Sources */, 282 | 19FE329C1EA7BD6200A4DB5E /* YNExpandableCell.swift in Sources */, 283 | 19FE32A01EA7BD6200A4DB5E /* YNTableViewCell.swift in Sources */, 284 | 19FE329E1EA7BD6200A4DB5E /* YNExpandableDeprecated.swift in Sources */, 285 | 19FE32A21EA7BD6200A4DB5E /* YNTableViewExtenstion.swift in Sources */, 286 | ); 287 | runOnlyForDeploymentPostprocessing = 0; 288 | }; 289 | 19FE32631EA7BCD100A4DB5E /* Sources */ = { 290 | isa = PBXSourcesBuildPhase; 291 | buildActionMask = 2147483647; 292 | files = ( 293 | 19FE328B1EA7BD0C00A4DB5E /* ViewController.swift in Sources */, 294 | 19FE328D1EA7BD0C00A4DB5E /* YNExpandableCells.swift in Sources */, 295 | 19FE32861EA7BD0C00A4DB5E /* AppDelegate.swift in Sources */, 296 | ); 297 | runOnlyForDeploymentPostprocessing = 0; 298 | }; 299 | /* End PBXSourcesBuildPhase section */ 300 | 301 | /* Begin PBXTargetDependency section */ 302 | 19FE32931EA7BD2200A4DB5E /* PBXTargetDependency */ = { 303 | isa = PBXTargetDependency; 304 | target = 19FE32571EA7BC9500A4DB5E /* YNExpandableCell */; 305 | targetProxy = 19FE32921EA7BD2200A4DB5E /* PBXContainerItemProxy */; 306 | }; 307 | /* End PBXTargetDependency section */ 308 | 309 | /* Begin PBXVariantGroup section */ 310 | 19FE327C1EA7BD0C00A4DB5E /* LaunchScreen.xib */ = { 311 | isa = PBXVariantGroup; 312 | children = ( 313 | 19FE327D1EA7BD0C00A4DB5E /* Base */, 314 | ); 315 | name = LaunchScreen.xib; 316 | sourceTree = ""; 317 | }; 318 | 19FE327E1EA7BD0C00A4DB5E /* Main.storyboard */ = { 319 | isa = PBXVariantGroup; 320 | children = ( 321 | 19FE327F1EA7BD0C00A4DB5E /* Base */, 322 | ); 323 | name = Main.storyboard; 324 | sourceTree = ""; 325 | }; 326 | /* End PBXVariantGroup section */ 327 | 328 | /* Begin XCBuildConfiguration section */ 329 | 19FE325E1EA7BC9500A4DB5E /* Debug */ = { 330 | isa = XCBuildConfiguration; 331 | buildSettings = { 332 | ALWAYS_SEARCH_USER_PATHS = NO; 333 | CLANG_ANALYZER_NONNULL = YES; 334 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 335 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 336 | CLANG_CXX_LIBRARY = "libc++"; 337 | CLANG_ENABLE_MODULES = YES; 338 | CLANG_ENABLE_OBJC_ARC = YES; 339 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 340 | CLANG_WARN_BOOL_CONVERSION = YES; 341 | CLANG_WARN_COMMA = YES; 342 | CLANG_WARN_CONSTANT_CONVERSION = YES; 343 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 344 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 345 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 346 | CLANG_WARN_EMPTY_BODY = YES; 347 | CLANG_WARN_ENUM_CONVERSION = YES; 348 | CLANG_WARN_INFINITE_RECURSION = YES; 349 | CLANG_WARN_INT_CONVERSION = YES; 350 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 351 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 352 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 353 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 354 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 355 | CLANG_WARN_STRICT_PROTOTYPES = YES; 356 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 357 | CLANG_WARN_UNREACHABLE_CODE = YES; 358 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 359 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 360 | COPY_PHASE_STRIP = NO; 361 | CURRENT_PROJECT_VERSION = 1; 362 | DEBUG_INFORMATION_FORMAT = dwarf; 363 | ENABLE_STRICT_OBJC_MSGSEND = YES; 364 | ENABLE_TESTABILITY = YES; 365 | GCC_C_LANGUAGE_STANDARD = gnu99; 366 | GCC_DYNAMIC_NO_PIC = NO; 367 | GCC_NO_COMMON_BLOCKS = YES; 368 | GCC_OPTIMIZATION_LEVEL = 0; 369 | GCC_PREPROCESSOR_DEFINITIONS = ( 370 | "DEBUG=1", 371 | "$(inherited)", 372 | ); 373 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 374 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 375 | GCC_WARN_UNDECLARED_SELECTOR = YES; 376 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 377 | GCC_WARN_UNUSED_FUNCTION = YES; 378 | GCC_WARN_UNUSED_VARIABLE = YES; 379 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 380 | MTL_ENABLE_DEBUG_INFO = YES; 381 | ONLY_ACTIVE_ARCH = YES; 382 | SDKROOT = iphoneos; 383 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 384 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 385 | SWIFT_VERSION = 4.2; 386 | TARGETED_DEVICE_FAMILY = "1,2"; 387 | VERSIONING_SYSTEM = "apple-generic"; 388 | VERSION_INFO_PREFIX = ""; 389 | }; 390 | name = Debug; 391 | }; 392 | 19FE325F1EA7BC9500A4DB5E /* Release */ = { 393 | isa = XCBuildConfiguration; 394 | buildSettings = { 395 | ALWAYS_SEARCH_USER_PATHS = NO; 396 | CLANG_ANALYZER_NONNULL = YES; 397 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 398 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 399 | CLANG_CXX_LIBRARY = "libc++"; 400 | CLANG_ENABLE_MODULES = YES; 401 | CLANG_ENABLE_OBJC_ARC = YES; 402 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 403 | CLANG_WARN_BOOL_CONVERSION = YES; 404 | CLANG_WARN_COMMA = YES; 405 | CLANG_WARN_CONSTANT_CONVERSION = YES; 406 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 407 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 408 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 409 | CLANG_WARN_EMPTY_BODY = YES; 410 | CLANG_WARN_ENUM_CONVERSION = YES; 411 | CLANG_WARN_INFINITE_RECURSION = YES; 412 | CLANG_WARN_INT_CONVERSION = YES; 413 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 414 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 415 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 416 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 417 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 418 | CLANG_WARN_STRICT_PROTOTYPES = YES; 419 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 420 | CLANG_WARN_UNREACHABLE_CODE = YES; 421 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 422 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 423 | COPY_PHASE_STRIP = NO; 424 | CURRENT_PROJECT_VERSION = 1; 425 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 426 | ENABLE_NS_ASSERTIONS = NO; 427 | ENABLE_STRICT_OBJC_MSGSEND = YES; 428 | GCC_C_LANGUAGE_STANDARD = gnu99; 429 | GCC_NO_COMMON_BLOCKS = YES; 430 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 431 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 432 | GCC_WARN_UNDECLARED_SELECTOR = YES; 433 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 434 | GCC_WARN_UNUSED_FUNCTION = YES; 435 | GCC_WARN_UNUSED_VARIABLE = YES; 436 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 437 | MTL_ENABLE_DEBUG_INFO = NO; 438 | SDKROOT = iphoneos; 439 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 440 | SWIFT_VERSION = 4.2; 441 | TARGETED_DEVICE_FAMILY = "1,2"; 442 | VALIDATE_PRODUCT = YES; 443 | VERSIONING_SYSTEM = "apple-generic"; 444 | VERSION_INFO_PREFIX = ""; 445 | }; 446 | name = Release; 447 | }; 448 | 19FE32611EA7BC9500A4DB5E /* Debug */ = { 449 | isa = XCBuildConfiguration; 450 | buildSettings = { 451 | CLANG_ENABLE_MODULES = YES; 452 | CODE_SIGN_IDENTITY = ""; 453 | DEFINES_MODULE = YES; 454 | DEVELOPMENT_TEAM = 4G7K3CN2JU; 455 | DYLIB_COMPATIBILITY_VERSION = 1; 456 | DYLIB_CURRENT_VERSION = 1; 457 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 458 | INFOPLIST_FILE = YNExpandableCell/Info.plist; 459 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 460 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 461 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 462 | PRODUCT_BUNDLE_IDENTIFIER = com.seungyounyi.YNExpandableCell; 463 | PRODUCT_NAME = "$(TARGET_NAME)"; 464 | SKIP_INSTALL = YES; 465 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 466 | SWIFT_VERSION = 4.2; 467 | }; 468 | name = Debug; 469 | }; 470 | 19FE32621EA7BC9500A4DB5E /* Release */ = { 471 | isa = XCBuildConfiguration; 472 | buildSettings = { 473 | CLANG_ENABLE_MODULES = YES; 474 | CODE_SIGN_IDENTITY = ""; 475 | DEFINES_MODULE = YES; 476 | DEVELOPMENT_TEAM = 4G7K3CN2JU; 477 | DYLIB_COMPATIBILITY_VERSION = 1; 478 | DYLIB_CURRENT_VERSION = 1; 479 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 480 | INFOPLIST_FILE = YNExpandableCell/Info.plist; 481 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 482 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 483 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 484 | PRODUCT_BUNDLE_IDENTIFIER = com.seungyounyi.YNExpandableCell; 485 | PRODUCT_NAME = "$(TARGET_NAME)"; 486 | SKIP_INSTALL = YES; 487 | SWIFT_VERSION = 4.2; 488 | }; 489 | name = Release; 490 | }; 491 | 19FE32771EA7BCD100A4DB5E /* Debug */ = { 492 | isa = XCBuildConfiguration; 493 | buildSettings = { 494 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 495 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 496 | CLANG_ENABLE_MODULES = YES; 497 | DEVELOPMENT_TEAM = 4G7K3CN2JU; 498 | INFOPLIST_FILE = YNExpandableCellDemo/Info.plist; 499 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 500 | PRODUCT_BUNDLE_IDENTIFIER = com.seungyounyi.YNExpandableCellDemo; 501 | PRODUCT_NAME = "$(TARGET_NAME)"; 502 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 503 | SWIFT_VERSION = 4.2; 504 | }; 505 | name = Debug; 506 | }; 507 | 19FE32781EA7BCD100A4DB5E /* Release */ = { 508 | isa = XCBuildConfiguration; 509 | buildSettings = { 510 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 511 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 512 | CLANG_ENABLE_MODULES = YES; 513 | DEVELOPMENT_TEAM = 4G7K3CN2JU; 514 | INFOPLIST_FILE = YNExpandableCellDemo/Info.plist; 515 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 516 | PRODUCT_BUNDLE_IDENTIFIER = com.seungyounyi.YNExpandableCellDemo; 517 | PRODUCT_NAME = "$(TARGET_NAME)"; 518 | SWIFT_VERSION = 4.2; 519 | }; 520 | name = Release; 521 | }; 522 | /* End XCBuildConfiguration section */ 523 | 524 | /* Begin XCConfigurationList section */ 525 | 19FE32521EA7BC9500A4DB5E /* Build configuration list for PBXProject "YNExpandableCell" */ = { 526 | isa = XCConfigurationList; 527 | buildConfigurations = ( 528 | 19FE325E1EA7BC9500A4DB5E /* Debug */, 529 | 19FE325F1EA7BC9500A4DB5E /* Release */, 530 | ); 531 | defaultConfigurationIsVisible = 0; 532 | defaultConfigurationName = Release; 533 | }; 534 | 19FE32601EA7BC9500A4DB5E /* Build configuration list for PBXNativeTarget "YNExpandableCell" */ = { 535 | isa = XCConfigurationList; 536 | buildConfigurations = ( 537 | 19FE32611EA7BC9500A4DB5E /* Debug */, 538 | 19FE32621EA7BC9500A4DB5E /* Release */, 539 | ); 540 | defaultConfigurationIsVisible = 0; 541 | defaultConfigurationName = Release; 542 | }; 543 | 19FE32761EA7BCD100A4DB5E /* Build configuration list for PBXNativeTarget "YNExpandableCellDemo" */ = { 544 | isa = XCConfigurationList; 545 | buildConfigurations = ( 546 | 19FE32771EA7BCD100A4DB5E /* Debug */, 547 | 19FE32781EA7BCD100A4DB5E /* Release */, 548 | ); 549 | defaultConfigurationIsVisible = 0; 550 | defaultConfigurationName = Release; 551 | }; 552 | /* End XCConfigurationList section */ 553 | }; 554 | rootObject = 19FE324F1EA7BC9500A4DB5E /* Project object */; 555 | } 556 | -------------------------------------------------------------------------------- /YNExpandableCell.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /YNExpandableCell.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /YNExpandableCell.xcodeproj/xcshareddata/xcschemes/YNExpandableCell.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /YNExpandableCell/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /YNExpandableCell/YNExpandableCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // YNExpandableCell.h 3 | // YNExpandableCell 4 | // 5 | // Created by YiSeungyoun on 2017. 4. 20.. 6 | // Copyright © 2017년 SeungyounYi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for YNExpandableCell. 12 | FOUNDATION_EXPORT double YNExpandableCellVersionNumber; 13 | 14 | //! Project version string for YNExpandableCell. 15 | FOUNDATION_EXPORT const unsigned char YNExpandableCellVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /YNExpandableCell/YNExpandableCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YNTableViewCell.swift 3 | // YNExpandableCell 4 | // 5 | // Created by YiSeungyoun on 2017. 3. 11.. 6 | // Copyright © 2017년 SeungyounYi. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// Inherit YNExpandableCell when you want to use custom accessory type 12 | open class YNExpandableCell: UITableViewCell { 13 | 14 | /// Normal Custom Accessory Type change UIImage 15 | open var normalCustomAccessoryType: UIImageView! 16 | 17 | /// Selected Custom Accessory Type change UIImage 18 | open var selectedCustomAccessoryType: UIImageView! 19 | 20 | /// Basic Init method 21 | public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 22 | super.init(style: style, reuseIdentifier: reuseIdentifier) 23 | 24 | self.initView() 25 | } 26 | 27 | /// Basic Coder method 28 | required public init?(coder aDecoder: NSCoder) { 29 | super.init(coder: aDecoder) 30 | } 31 | 32 | /// Basic awakeFromNib method 33 | open override func awakeFromNib() { 34 | super.awakeFromNib() 35 | 36 | self.initView() 37 | } 38 | 39 | /// Init method. override this method whatever you like. Mainly about Custom Accessory Type 40 | open func initView() { 41 | let width = UIScreen.main.bounds.size.width 42 | let height = self.frame.size.height 43 | 44 | self.normalCustomAccessoryType = UIImageView(frame: CGRect(x: width - 46, y: (height-26)/2, width: 26, height: 26)) 45 | let yn_nor = UIImage(named: "yn_nor", in: Bundle(for: YNExpandableCell.self), compatibleWith: nil) 46 | self.normalCustomAccessoryType.image = yn_nor 47 | self.selectedCustomAccessoryType = UIImageView(frame: CGRect(x: width - 46, y: (height-26)/2, width: 26, height: 26)) 48 | let yn_sel = UIImage(named: "yn_sel", in: Bundle(for: YNExpandableCell.self), compatibleWith: nil) 49 | self.selectedCustomAccessoryType.image = yn_sel 50 | self.selectedCustomAccessoryType.isHidden = true 51 | 52 | self.contentView.addSubview(self.normalCustomAccessoryType) 53 | self.contentView.addSubview(self.selectedCustomAccessoryType) 54 | 55 | self.selectionStyle = .none 56 | } 57 | 58 | /// Normal function when cell is unclicked 59 | open func normal() { 60 | self.selectedCustomAccessoryType.isHidden = true 61 | self.normalCustomAccessoryType.isHidden = false 62 | 63 | self.rotateAnimationFrom(selectedCustomAccessoryType, toItem: normalCustomAccessoryType, duration: 0.3) 64 | } 65 | 66 | /// Selected function when cell is clicked 67 | open func selected() { 68 | self.selectedCustomAccessoryType.isHidden = false 69 | self.normalCustomAccessoryType.isHidden = true 70 | 71 | self.rotateAnimationFrom(normalCustomAccessoryType, toItem: selectedCustomAccessoryType, duration: 0.3) 72 | } 73 | 74 | fileprivate func rotateAnimationFrom(_ fromItem: UIImageView, toItem: UIImageView, duration: Double) { 75 | 76 | let fromRotate = animationFrom(0, to: Double.pi, key: "transform.rotation", duration: duration) 77 | let fromOpacity = animationFrom(1, to: 0, key: "opacity", duration: duration) 78 | 79 | let toRotate = animationFrom(-Double.pi, to: 0, key: "transform.rotation", duration: duration) 80 | let toOpacity = animationFrom(0, to: 1, key: "opacity", duration: duration) 81 | 82 | fromItem.layer.add(fromRotate, forKey: nil) 83 | fromItem.layer.add(fromOpacity, forKey: nil) 84 | 85 | toItem.layer.add(toRotate, forKey: nil) 86 | toItem.layer.add(toOpacity, forKey: nil) 87 | } 88 | 89 | fileprivate func Init(_ value : Type, block: (_ object: Type) -> Void) -> Type 90 | { 91 | block(value) 92 | return value 93 | } 94 | 95 | fileprivate func animationFrom(_ from: Double, to: Double, key: String, duration: Double) -> CABasicAnimation { 96 | return Init(CABasicAnimation(keyPath: key)) { 97 | $0.duration = duration 98 | $0.fromValue = from 99 | $0.toValue = to 100 | $0.fillMode = CAMediaTimingFillMode.forwards 101 | $0.isRemovedOnCompletion = false 102 | } 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /YNExpandableCell/YNExpandableCell.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /YNExpandableCell/YNExpandableCell.xcassets/yn_nor.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "filter_type_more_nor.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "filter_type_more_nor@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "filter_type_more_nor@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /YNExpandableCell/YNExpandableCell.xcassets/yn_nor.imageset/filter_type_more_nor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCell/YNExpandableCell.xcassets/yn_nor.imageset/filter_type_more_nor.png -------------------------------------------------------------------------------- /YNExpandableCell/YNExpandableCell.xcassets/yn_nor.imageset/filter_type_more_nor@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCell/YNExpandableCell.xcassets/yn_nor.imageset/filter_type_more_nor@2x.png -------------------------------------------------------------------------------- /YNExpandableCell/YNExpandableCell.xcassets/yn_nor.imageset/filter_type_more_nor@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCell/YNExpandableCell.xcassets/yn_nor.imageset/filter_type_more_nor@3x.png -------------------------------------------------------------------------------- /YNExpandableCell/YNExpandableCell.xcassets/yn_sel.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "filter_type_close_nor.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "filter_type_close_nor@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "filter_type_close_nor@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /YNExpandableCell/YNExpandableCell.xcassets/yn_sel.imageset/filter_type_close_nor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCell/YNExpandableCell.xcassets/yn_sel.imageset/filter_type_close_nor.png -------------------------------------------------------------------------------- /YNExpandableCell/YNExpandableCell.xcassets/yn_sel.imageset/filter_type_close_nor@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCell/YNExpandableCell.xcassets/yn_sel.imageset/filter_type_close_nor@2x.png -------------------------------------------------------------------------------- /YNExpandableCell/YNExpandableCell.xcassets/yn_sel.imageset/filter_type_close_nor@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCell/YNExpandableCell.xcassets/yn_sel.imageset/filter_type_close_nor@3x.png -------------------------------------------------------------------------------- /YNExpandableCell/YNExpandableDeprecated.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YNExpandableDeprecated.swift 3 | // YNExpandableCell 4 | // 5 | // Created by Seungyoun Yi on 2017. 3. 27.. 6 | // Copyright © 2017년 SeungyounYi. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension YNTableViewDelegate { 12 | 13 | /** 14 | Get didSelectRowAt IndexPath and whether it is ExpandedCell or not 15 | 16 | - Parameter tableView: YNTableView 17 | - Parameter indexPath: Selected IndexPath 18 | - Parameter isExpandedCell: Whether it is expandedCell or not 19 | */ 20 | @available(*, deprecated, message: "use tableView(_ tableView: YNTableView, didSelectRowAt indexPath: IndexPath, isExpandableCell: Bool, isExpandedCell: Bool) instead") 21 | func tableView(_ tableView: YNTableView, didSelectRowAt indexPath: IndexPath, isExpandedCell: Bool) { } 22 | 23 | 24 | /** 25 | Get didDeselectRowAt IndexPath and whether it is ExpandedCell or not 26 | 27 | - Parameter tableView: YNTableView 28 | - Parameter indexPath: Deselected IndexPath 29 | - Parameter isExpandedCell: Whether it is expandedCell or not 30 | */ 31 | @available(*, deprecated, message: "use tableView(_ tableView: YNTableView, didDeselectRowAt indexPath: IndexPath, isExpandableCell: Bool, isExpandedCell: Bool) instead") 32 | func tableView(_ tableView: YNTableView, didDeselectRowAt indexPath: IndexPath, isExpandedCell: Bool) { } 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /YNExpandableCell/YNTableView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YNTableView.swift 3 | // YNExpandableCell 4 | // 5 | // Created by YiSeungyoun on 2017. 3. 11.. 6 | // Copyright © 2017년 SeungyounYi. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | /// Inherit this tableView to use YNExpandableCell 13 | open class YNTableView: UITableView, UITableViewDataSource, UITableViewDelegate { 14 | private var expandedIndexPaths = [IndexPath]() 15 | 16 | /// Set ynDelegate to use this tableview 17 | open var ynDelegate: YNTableViewDelegate? { 18 | didSet { 19 | self.delegate = self 20 | self.dataSource = self 21 | } 22 | } 23 | 24 | /// Simple UITableViewRowAnimation 25 | open var ynTableViewRowAnimation = UITableView.RowAnimation.top 26 | 27 | /// Called in Nib 28 | open override func awakeFromNib() { 29 | super.awakeFromNib() 30 | 31 | self.initView() 32 | } 33 | 34 | /// Init method 35 | public override init(frame: CGRect, style: UITableView.Style) { 36 | super.init(frame: frame, style: style) 37 | 38 | self.initView() 39 | } 40 | 41 | /// Init coder 42 | required public init?(coder aDecoder: NSCoder) { 43 | super.init(coder: aDecoder) 44 | } 45 | 46 | //PRAGMA MARK: YNTableView Method 47 | 48 | /** 49 | Register cells with array of strings 50 | 51 | - Parameter nibNames: [String] 52 | - Parameter reuseIdentifiers: [String] 53 | */ 54 | open func registerCellsWith(nibNames: [String], and reuseIdentifiers: [String]) { 55 | self.checkValueIsSame(first: nibNames, second: reuseIdentifiers) 56 | 57 | for i in 0.. 0 else { return } 96 | var tempSelectedRowCount = 0 97 | var tempSelectedSection = tempExpandedIndexPaths[0].section 98 | var addedExpandedIndexPath = IndexPath() 99 | 100 | for i in 0.. 0{ 125 | let internalIndexPath = IndexPath(row: self.expandedIndexPaths[0].row - 1, section: self.expandedIndexPaths[0].section) 126 | self.didDeselectRowLogicAt(expandedIndexPath: self.expandedIndexPaths[0], indexPath: internalIndexPath) 127 | self.deselectRow(at: internalIndexPath, animated: true) 128 | } 129 | } 130 | 131 | //PRAGMA MARK: YNTableView Delegate 132 | 133 | /// Overide tableview reloadData 134 | open override func reloadData() { 135 | super.reloadData() 136 | for expandedIndexPath in expandedIndexPaths { 137 | let internalIndexPath = IndexPath(row: expandedIndexPath.row-1, section: expandedIndexPath.section) 138 | self.selectRow(at: internalIndexPath, animated: true, scrollPosition: .none) 139 | } 140 | } 141 | /// Basic UITableViewDelegate: func numberOfSections(in tableView: UITableView) -> Int 142 | open func numberOfSections(in tableView: UITableView) -> Int { 143 | guard let delegate = self.ynDelegate else { return Int() } 144 | guard let numberOfSection = delegate.numberOfSections?(in: self) else { return Int() } 145 | return numberOfSection 146 | } 147 | 148 | /// Basic UITableViewDelegate: func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 149 | open func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 150 | guard let delegate = self.ynDelegate else { return Int() } 151 | 152 | return delegate.tableView(self, numberOfRowsInSection: section) + self.checkExpandRowIn(section: section) 153 | } 154 | 155 | /// Basic UITableViewDelegate: func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 156 | open func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 157 | guard let delegate = self.ynDelegate else { return UITableViewCell() } 158 | 159 | for expandedIndexPath in self.expandedIndexPaths { 160 | if expandedIndexPath == indexPath { 161 | let internalIndexPath = IndexPath(row: indexPath.row - 1 - self.expandedRowCountSince(current: indexPath), section: indexPath.section) 162 | if let cell = delegate.tableView(self, expandCellAt: internalIndexPath) { 163 | return cell 164 | } else if let cell = delegate.tableView(self, expandCellWithHeightAt: internalIndexPath)?.cell { 165 | return cell 166 | } 167 | } 168 | } 169 | 170 | let internalIndexPath = IndexPath(row: indexPath.row - self.expandedRowCountSince(current: indexPath), section: indexPath.section) 171 | 172 | if let ynExpandableCell = delegate.tableView(self, cellForRowAt: internalIndexPath) as? YNExpandableCell { 173 | let checkSelectedIndexPath = IndexPath(row: indexPath.row + 1, section: indexPath.section) 174 | if self.expandedIndexPaths.contains(checkSelectedIndexPath) { 175 | ynExpandableCell.selected() 176 | return ynExpandableCell 177 | } 178 | } 179 | return delegate.tableView(self, cellForRowAt: internalIndexPath) 180 | 181 | } 182 | 183 | /// Basic UITableViewDelegate: func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 184 | open func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 185 | guard let delegate = self.ynDelegate else { return } 186 | 187 | let selectedIndexPath = IndexPath(row: indexPath.row - self.expandedRowCountSince(current: indexPath), section: indexPath.section) 188 | if (delegate.tableView(self, expandCellAt: selectedIndexPath)) != nil || (delegate.tableView(self, expandCellWithHeightAt: selectedIndexPath)) != nil { 189 | 190 | var sameIndexPathExists = false 191 | for expandedIndexPath in self.expandedIndexPaths { 192 | if indexPath == expandedIndexPath { 193 | sameIndexPathExists = true 194 | } 195 | } 196 | if !sameIndexPathExists { 197 | self.didSelectRowLogicAt(indexPath: indexPath) 198 | delegate.tableView(self, didSelectRowAt: indexPath, isExpandableCell: true, isExpandedCell: false) 199 | return 200 | } 201 | 202 | if self.expandedIndexPaths.isEmpty { 203 | self.didSelectRowLogicAt(indexPath: indexPath) 204 | delegate.tableView(self, didSelectRowAt: indexPath, isExpandableCell: true, isExpandedCell: false) 205 | return 206 | } 207 | delegate.tableView(self, didSelectRowAt: indexPath, isExpandableCell: false, isExpandedCell: true) 208 | 209 | } else if self.expandedIndexPaths.contains(indexPath) { 210 | delegate.tableView(self, didSelectRowAt: indexPath, isExpandableCell: false, isExpandedCell: true) 211 | } else { 212 | delegate.tableView(self, didSelectRowAt: indexPath, isExpandableCell: false, isExpandedCell: false) 213 | } 214 | } 215 | 216 | /// Basic UITableViewDelegate: func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) 217 | open func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) { 218 | guard let delegate = self.ynDelegate else { return } 219 | 220 | for expandedIndexPath in self.expandedIndexPaths { 221 | let internalIndexPath = IndexPath(row: expandedIndexPath.row - 1, section: expandedIndexPath.section) 222 | 223 | if expandedIndexPath == indexPath { 224 | delegate.tableView(self, didDeselectRowAt: indexPath, isExpandableCell: false, isExpandedCell: true) 225 | return 226 | } 227 | if internalIndexPath == indexPath { 228 | self.didDeselectRowLogicAt(expandedIndexPath: expandedIndexPath, indexPath: indexPath) 229 | delegate.tableView(self, didDeselectRowAt: indexPath, isExpandableCell: true, isExpandedCell: false) 230 | return 231 | } 232 | } 233 | 234 | delegate.tableView(self, didDeselectRowAt: indexPath, isExpandableCell: false, isExpandedCell: false) 235 | } 236 | 237 | /// Basic UITableViewDelegate: tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 238 | open func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 239 | guard let delegate = self.ynDelegate else { return 44 } 240 | 241 | var height:CGFloat = 0 242 | if let normalHeight = delegate.tableView?(self, heightForRowAt: indexPath) { 243 | height = normalHeight 244 | } 245 | 246 | for expandedIndexPaths in self.expandedIndexPaths { 247 | if indexPath == expandedIndexPaths { 248 | let selectedIndexPath = IndexPath(row: indexPath.row - 1 - self.expandedRowCountSince(current: indexPath), section: indexPath.section) 249 | if let _height = delegate.tableView(self, expandCellWithHeightAt: selectedIndexPath)?.height { 250 | height = _height 251 | } 252 | } 253 | } 254 | return height 255 | } 256 | 257 | /// Basic UITableViewDelegate: func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat 258 | open func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { 259 | return UITableView.automaticDimension 260 | } 261 | 262 | //PRAGMA MARK: YNTableView Logic 263 | private func checkExpandRowIn(section: Int) -> Int { 264 | var openedCellCount = 0 265 | 266 | for expandedIndexPaths in self.expandedIndexPaths { 267 | if expandedIndexPaths.section == section { 268 | openedCellCount += 1 269 | } 270 | } 271 | 272 | return openedCellCount 273 | } 274 | 275 | private func didDeselectRowLogicAt(expandedIndexPath: IndexPath, indexPath: IndexPath) { 276 | let index = self.expandedIndexPaths.index(of: expandedIndexPath) 277 | guard let _index = index else { return } 278 | self.expandedIndexPaths.remove(at: _index) 279 | self.deleteRows(at: [expandedIndexPath], with: ynTableViewRowAnimation) 280 | self.expandedIndexPathsDeselectAfter(current: indexPath) 281 | 282 | guard let ynExpandableCell = cellForRow(at: indexPath) as? YNExpandableCell else { return } 283 | ynExpandableCell.normal() 284 | 285 | } 286 | 287 | 288 | private func didSelectRowLogicAt(indexPath: IndexPath) { 289 | let insertIndexPath = IndexPath(row: indexPath.row + 1, section: indexPath.section) 290 | self.expandedIndexPaths.append(insertIndexPath) 291 | self.insertRows(at: [insertIndexPath], with: ynTableViewRowAnimation) 292 | self.expandedIndexPathsSelectAfter(current: indexPath) 293 | 294 | guard let ynExpandableCell = cellForRow(at: indexPath) as? YNExpandableCell else { return } 295 | ynExpandableCell.selected() 296 | } 297 | 298 | private func expandedIndexPathsSelectAfter(current indexPath: IndexPath) { 299 | for expandedIndexPath in self.expandedIndexPaths { 300 | if expandedIndexPath.section == indexPath.section { 301 | if expandedIndexPath.row > indexPath.row + 1 { 302 | let index = self.expandedIndexPaths.index(of: expandedIndexPath) 303 | guard let _index = index else { return } 304 | 305 | let indexPath = IndexPath(row: expandedIndexPath.row + 1, section: expandedIndexPath.section) 306 | self.expandedIndexPaths[_index] = indexPath 307 | 308 | } 309 | } 310 | } 311 | } 312 | 313 | private func expandedIndexPathsDeselectAfter(current indexPath: IndexPath) { 314 | for expandedIndexPath in self.expandedIndexPaths { 315 | if expandedIndexPath.section == indexPath.section { 316 | if expandedIndexPath.row > indexPath.row { 317 | let index = self.expandedIndexPaths.index(of: expandedIndexPath) 318 | guard let _index = index else { return } 319 | 320 | let indexPath = IndexPath(row: expandedIndexPath.row - 1, section: expandedIndexPath.section) 321 | self.expandedIndexPaths[_index] = indexPath 322 | 323 | } 324 | } 325 | } 326 | } 327 | 328 | private func expandedRowCountSince(current indexPath: IndexPath) -> Int { 329 | var expandCount = 0 330 | for expandedIndexPath in self.expandedIndexPaths { 331 | if expandedIndexPath.section == indexPath.section { 332 | if expandedIndexPath.row < indexPath.row { 333 | expandCount += 1 334 | } 335 | } 336 | } 337 | 338 | return expandCount 339 | } 340 | 341 | private func checkValueIsSame(first: [Any], second: [Any]) { 342 | if first.count != second.count { 343 | fatalError("Make first and second value count same") 344 | } 345 | } 346 | 347 | private func initView() { 348 | self.allowsMultipleSelection = true 349 | } 350 | 351 | } 352 | -------------------------------------------------------------------------------- /YNExpandableCell/YNTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YNTableViewCell.swift 3 | // YNExpandableCell 4 | // 5 | // Created by YiSeungyoun on 2017. 4. 8.. 6 | // Copyright © 2017년 SeungyounYi. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | open class YNTableViewCell: NSObject { 12 | open var cell: UITableViewCell? 13 | open var height: CGFloat? 14 | } 15 | -------------------------------------------------------------------------------- /YNExpandableCell/YNTableViewDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YNTableViewDelegate.swift 3 | // YNExpandableCell 4 | // 5 | // Created by YiSeungyoun on 2017. 3. 11.. 6 | // Copyright © 2017년 SeungyounYi. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | /// You need to set delegate and add only one method. 13 | public protocol YNTableViewDelegate: UITableViewDelegate, UITableViewDataSource { 14 | 15 | /** 16 | Determine expandable cell in this view. This method is all that you have to do 17 | 18 | - Parameter tableView: YNTableView 19 | - Parameter indexPath: Determine expandable cell and return UITableViewCell 20 | */ 21 | func tableView(_ tableView: YNTableView, expandCellAt indexPath: IndexPath) -> UITableViewCell? 22 | 23 | /** 24 | Determine expandable cell in this view. you can add height in YNTableViewCell object. 25 | 26 | - Parameter tableView: YNTableView 27 | - Parameter indexPath: Determine expandable cell and return UITableViewCell 28 | */ 29 | func tableView(_ tableView: YNTableView, expandCellWithHeightAt indexPath: IndexPath) -> YNTableViewCell? 30 | 31 | /** 32 | Get didSelectRowAt IndexPath and whether it is ExpandedCell or not 33 | 34 | - Parameter tableView: YNTableView 35 | - Parameter indexPath: Selected IndexPath 36 | - Parameter isExpandableCell: Whether it is expandableCell or not 37 | - Parameter isExpandedCell: Whether it is expandedCell or not 38 | */ 39 | func tableView(_ tableView: YNTableView, didSelectRowAt indexPath: IndexPath, isExpandableCell: Bool, isExpandedCell: Bool) 40 | 41 | /** 42 | Get didDeselectRowAt IndexPath and whether it is ExpandedCell or not 43 | 44 | - Parameter tableView: YNTableView 45 | - Parameter indexPath: Deselected IndexPath 46 | - Parameter isExpandableCell: Whether it is expandableCell or not 47 | - Parameter isExpandedCell: Whether it is expandedCell or not 48 | */ 49 | func tableView(_ tableView: YNTableView, didDeselectRowAt indexPath: IndexPath, isExpandableCell: Bool, isExpandedCell: Bool) 50 | 51 | } 52 | 53 | public extension YNTableViewDelegate { 54 | /** 55 | Determine expandable cell in this view. This method is all that you have to do 56 | 57 | - Parameter tableView: YNTableView 58 | - Parameter indexPath: Determine expandable cell and return UITableViewCell 59 | */ 60 | func tableView(_ tableView: YNTableView, expandCellAt indexPath: IndexPath) -> UITableViewCell? { return nil } 61 | 62 | /** 63 | Determine expandable cell in this view. you can add height in YNTableViewCell object. 64 | 65 | - Parameter tableView: YNTableView 66 | - Parameter indexPath: Determine expandable cell and return UITableViewCell 67 | */ 68 | func tableView(_ tableView: YNTableView, expandCellWithHeightAt indexPath: IndexPath) -> YNTableViewCell? { return nil } 69 | 70 | /** 71 | Get didSelectRowAt IndexPath and whether it is ExpandedCell or not 72 | 73 | - Parameter tableView: YNTableView 74 | - Parameter indexPath: Selected IndexPath 75 | - Parameter isExpandableCell: Whether it is expandableCell or not 76 | - Parameter isExpandedCell: Whether it is expandedCell or not 77 | */ 78 | func tableView(_ tableView: YNTableView, didSelectRowAt indexPath: IndexPath, isExpandableCell: Bool, isExpandedCell: Bool) { } 79 | 80 | /** 81 | Get didDeselectRowAt IndexPath and whether it is ExpandedCell or not 82 | 83 | - Parameter tableView: YNTableView 84 | - Parameter indexPath: Deselected IndexPath 85 | - Parameter isExpandableCell: Whether it is expandableCell or not 86 | - Parameter isExpandedCell: Whether it is expandedCell or not 87 | */ 88 | func tableView(_ tableView: YNTableView, didDeselectRowAt indexPath: IndexPath, isExpandableCell: Bool, isExpandedCell: Bool) { } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /YNExpandableCell/YNTableViewExtenstion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YNTableViewExtenstion.swift 3 | // YNExpandableCell 4 | // 5 | // Created by YiSeungyoun on 2017. 3. 18.. 6 | // Copyright © 2017년 SeungyounYi. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension YNTableView { 12 | /// Basic UITableViewDelegate: func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? 13 | open func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 14 | guard let delegate = self.ynDelegate else { return nil } 15 | guard let titleForHeaderInSection = delegate.tableView?(self, titleForHeaderInSection: section) else { return nil } 16 | 17 | return titleForHeaderInSection 18 | } 19 | 20 | /// Basic UITableViewDelegate: func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat 21 | open func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 22 | guard let delegate = self.ynDelegate else { return CGFloat() } 23 | guard let heightForHeaderInSection = delegate.tableView?(self, heightForHeaderInSection: section) else { return CGFloat() } 24 | 25 | return heightForHeaderInSection 26 | } 27 | 28 | /// Basic UITableViewDelegate: func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? 29 | open func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { 30 | guard let delegate = self.ynDelegate else { return nil } 31 | guard let viewForHeaderInSection = delegate.tableView?(self, viewForHeaderInSection: section) else { return nil } 32 | return viewForHeaderInSection 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /YNExpandableCellDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // YNExpandableCell 4 | // 5 | // Created by YiSeungyoun on 2017. 3. 11.. 6 | // Copyright © 2017년 SeungyounYi. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | func applicationWillResignActive(_ application: UIApplication) { 22 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 23 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 24 | } 25 | 26 | func applicationDidEnterBackground(_ application: UIApplication) { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | func applicationWillEnterForeground(_ application: UIApplication) { 32 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 33 | } 34 | 35 | func applicationDidBecomeActive(_ application: UIApplication) { 36 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 37 | } 38 | 39 | func applicationWillTerminate(_ application: UIApplication) { 40 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 41 | } 42 | 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "idiom" : "iphone", 23 | "size" : "29x29", 24 | "scale" : "2x" 25 | }, 26 | { 27 | "size" : "29x29", 28 | "idiom" : "iphone", 29 | "filename" : "Icon-App-29x29@3x.png", 30 | "scale" : "3x" 31 | }, 32 | { 33 | "idiom" : "iphone", 34 | "size" : "40x40", 35 | "scale" : "2x" 36 | }, 37 | { 38 | "size" : "40x40", 39 | "idiom" : "iphone", 40 | "filename" : "Icon-App-40x40@3x.png", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "size" : "57x57", 45 | "idiom" : "iphone", 46 | "filename" : "Icon-App-57x57@1x.png", 47 | "scale" : "1x" 48 | }, 49 | { 50 | "size" : "57x57", 51 | "idiom" : "iphone", 52 | "filename" : "Icon-App-57x57@2x.png", 53 | "scale" : "2x" 54 | }, 55 | { 56 | "size" : "60x60", 57 | "idiom" : "iphone", 58 | "filename" : "Icon-App-60x60@2x.png", 59 | "scale" : "2x" 60 | }, 61 | { 62 | "idiom" : "iphone", 63 | "size" : "60x60", 64 | "scale" : "3x" 65 | }, 66 | { 67 | "size" : "20x20", 68 | "idiom" : "ipad", 69 | "filename" : "Icon-App-20x20@1x.png", 70 | "scale" : "1x" 71 | }, 72 | { 73 | "idiom" : "ipad", 74 | "size" : "20x20", 75 | "scale" : "2x" 76 | }, 77 | { 78 | "idiom" : "ipad", 79 | "size" : "29x29", 80 | "scale" : "1x" 81 | }, 82 | { 83 | "idiom" : "ipad", 84 | "size" : "29x29", 85 | "scale" : "2x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@1x.png", 91 | "scale" : "1x" 92 | }, 93 | { 94 | "size" : "40x40", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-40x40@2x.png", 97 | "scale" : "2x" 98 | }, 99 | { 100 | "size" : "50x50", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-Small-50x50@1x.png", 103 | "scale" : "1x" 104 | }, 105 | { 106 | "size" : "50x50", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-Small-50x50@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "72x72", 113 | "idiom" : "ipad", 114 | "filename" : "Icon-App-72x72@1x.png", 115 | "scale" : "1x" 116 | }, 117 | { 118 | "size" : "72x72", 119 | "idiom" : "ipad", 120 | "filename" : "Icon-App-72x72@2x.png", 121 | "scale" : "2x" 122 | }, 123 | { 124 | "size" : "76x76", 125 | "idiom" : "ipad", 126 | "filename" : "Icon-App-76x76@1x.png", 127 | "scale" : "1x" 128 | }, 129 | { 130 | "size" : "76x76", 131 | "idiom" : "ipad", 132 | "filename" : "Icon-App-76x76@2x.png", 133 | "scale" : "2x" 134 | }, 135 | { 136 | "size" : "83.5x83.5", 137 | "idiom" : "ipad", 138 | "filename" : "Icon-App-83.5x83.5@2x.png", 139 | "scale" : "2x" 140 | }, 141 | { 142 | "idiom" : "car", 143 | "size" : "60x60", 144 | "scale" : "2x" 145 | }, 146 | { 147 | "size" : "60x60", 148 | "idiom" : "car", 149 | "filename" : "Icon-App-60x60@3x.png", 150 | "scale" : "3x" 151 | }, 152 | { 153 | "size" : "24x24", 154 | "idiom" : "watch", 155 | "scale" : "2x", 156 | "role" : "notificationCenter", 157 | "subtype" : "38mm" 158 | }, 159 | { 160 | "size" : "27.5x27.5", 161 | "idiom" : "watch", 162 | "scale" : "2x", 163 | "role" : "notificationCenter", 164 | "subtype" : "42mm" 165 | }, 166 | { 167 | "size" : "29x29", 168 | "idiom" : "watch", 169 | "filename" : "Icon-App-29x29@2x.png", 170 | "role" : "companionSettings", 171 | "scale" : "2x" 172 | }, 173 | { 174 | "size" : "29x29", 175 | "idiom" : "watch", 176 | "role" : "companionSettings", 177 | "scale" : "3x" 178 | }, 179 | { 180 | "size" : "40x40", 181 | "idiom" : "watch", 182 | "scale" : "2x", 183 | "role" : "appLauncher", 184 | "subtype" : "38mm" 185 | }, 186 | { 187 | "size" : "86x86", 188 | "idiom" : "watch", 189 | "scale" : "2x", 190 | "role" : "quickLook", 191 | "subtype" : "38mm" 192 | }, 193 | { 194 | "size" : "98x98", 195 | "idiom" : "watch", 196 | "scale" : "2x", 197 | "role" : "quickLook", 198 | "subtype" : "42mm" 199 | } 200 | ], 201 | "info" : { 202 | "version" : 1, 203 | "author" : "xcode" 204 | } 205 | } -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-Small-50x50@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-Small-50x50@1x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-Small-50x50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/younatics/YNExpandableCell/341f97cf9d417b5bab61bfa3963da76276162fce/YNExpandableCellDemo/Assets.xcassets/AppIcon.appiconset/Icon-Small-50x50@2x.png -------------------------------------------------------------------------------- /YNExpandableCellDemo/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /YNExpandableCellDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /YNExpandableCellDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /YNExpandableCellDemo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // YNExpandableCell 4 | // 5 | // Created by YiSeungyoun on 2017. 3. 11.. 6 | // Copyright © 2017년 SeungyounYi. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import YNExpandableCell 11 | 12 | class ViewController: UIViewController, YNTableViewDelegate { 13 | @IBOutlet var ynTableView: YNTableView! 14 | @IBOutlet var expandAllButton: UIBarButtonItem! 15 | @IBOutlet var collapseAllButton: UIBarButtonItem! 16 | 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | 20 | let cells = ["YNExpandableCellEx","YNSliderCell","YNSegmentCell"] 21 | self.ynTableView.registerCellsWith(nibNames: cells, and: cells) 22 | self.ynTableView.registerCellsWith(cells: [UITableViewCell.self as AnyClass], and: ["YNNonExpandableCell"]) 23 | 24 | self.ynTableView.ynDelegate = self 25 | self.ynTableView.ynTableViewRowAnimation = .top 26 | 27 | self.expandAllButton.action = #selector(self.expandAllButtonClicked) 28 | self.expandAllButton.target = self 29 | self.collapseAllButton.action = #selector(self.collapseAllButtonClicked) 30 | self.collapseAllButton.target = self 31 | 32 | } 33 | 34 | override func didReceiveMemoryWarning() { 35 | super.didReceiveMemoryWarning() 36 | // Dispose of any resources that can be recreated. 37 | } 38 | 39 | @objc func expandAllButtonClicked() { 40 | self.ynTableView.expandAll() 41 | } 42 | 43 | @objc func collapseAllButtonClicked() { 44 | self.ynTableView.collapseAll() 45 | } 46 | 47 | func tableView(_ tableView: YNTableView, expandCellWithHeightAt indexPath: IndexPath) -> YNTableViewCell? { 48 | let ynSliderCell = YNTableViewCell() 49 | ynSliderCell.cell = tableView.dequeueReusableCell(withIdentifier: YNSliderCell.ID) as! YNSliderCell 50 | ynSliderCell.height = 142 51 | 52 | let ynSegmentCell = YNTableViewCell() 53 | ynSegmentCell.cell = tableView.dequeueReusableCell(withIdentifier: YNSegmentCell.ID) as! YNSegmentCell 54 | ynSegmentCell.height = 160 55 | 56 | if indexPath.section == 0 && indexPath.row == 1 { 57 | return ynSliderCell 58 | } else if indexPath.section == 0 && indexPath.row == 2 { 59 | return ynSegmentCell 60 | } else if indexPath.section == 0 && indexPath.row == 4 { 61 | return ynSegmentCell 62 | } else if indexPath.section == 1 && indexPath.row == 0 { 63 | return ynSegmentCell 64 | } else if indexPath.section == 1 && indexPath.row == 1 { 65 | return ynSliderCell 66 | } else if indexPath.section == 2 && indexPath.row == 2 { 67 | return ynSliderCell 68 | } else if indexPath.section == 2 && indexPath.row == 4 { 69 | return ynSliderCell 70 | } 71 | return nil 72 | } 73 | 74 | // func tableView(_ tableView: YNTableView, expandCellAt indexPath: IndexPath) -> UITableViewCell? { 75 | // let ynSliderCell = tableView.dequeueReusableCell(withIdentifier: YNSliderCell.ID) as! YNSliderCell 76 | // let ynSegmentCell = tableView.dequeueReusableCell(withIdentifier: YNSegmentCell.ID) as! YNSegmentCell 77 | // 78 | // if indexPath.section == 0 && indexPath.row == 1 { 79 | // return ynSliderCell 80 | // } else if indexPath.section == 0 && indexPath.row == 2 { 81 | // return ynSegmentCell 82 | // } else if indexPath.section == 0 && indexPath.row == 4 { 83 | // return ynSegmentCell 84 | // } else if indexPath.section == 1 && indexPath.row == 0 { 85 | // return ynSegmentCell 86 | // } else if indexPath.section == 1 && indexPath.row == 1 { 87 | // return ynSliderCell 88 | // } else if indexPath.section == 2 && indexPath.row == 2 { 89 | // return ynSliderCell 90 | // } else if indexPath.section == 2 && indexPath.row == 4 { 91 | // return ynSliderCell 92 | // } 93 | // return nil 94 | // } 95 | 96 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 97 | let expandableCell = tableView.dequeueReusableCell(withIdentifier: YNExpandableCellEx.ID) as! YNExpandableCellEx 98 | if indexPath.section == 0 && indexPath.row == 1 { 99 | expandableCell.titleLabel.text = "YNSlider Cell" 100 | } else if indexPath.section == 0 && indexPath.row == 2 { 101 | expandableCell.titleLabel.text = "YNSegment Cell" 102 | } else if indexPath.section == 0 && indexPath.row == 4 { 103 | expandableCell.titleLabel.text = "YNSegment Cell" 104 | } else if indexPath.section == 1 && indexPath.row == 0 { 105 | expandableCell.titleLabel.text = "YNSegment Cell" 106 | } else if indexPath.section == 1 && indexPath.row == 1 { 107 | expandableCell.titleLabel.text = "YNSlider Cell" 108 | } else if indexPath.section == 2 && indexPath.row == 2 { 109 | expandableCell.titleLabel.text = "YNSlider Cell" 110 | } else if indexPath.section == 2 && indexPath.row == 4 { 111 | expandableCell.titleLabel.text = "YNSlider Cell" 112 | } else { 113 | let nonExpandablecell = tableView.dequeueReusableCell(withIdentifier: "YNNonExpandableCell") 114 | nonExpandablecell?.textLabel?.text = "YNNonExpandable Cell" 115 | nonExpandablecell?.selectionStyle = .none 116 | return nonExpandablecell! 117 | } 118 | return expandableCell 119 | 120 | } 121 | 122 | func tableView(_ tableView: YNTableView, didSelectRowAt indexPath: IndexPath, isExpandableCell: Bool, isExpandedCell: Bool) { 123 | print("Selected Section: \(indexPath.section) Row: \(indexPath.row) isExpandableCell: \(isExpandableCell) isExpandedCell: \(isExpandedCell)") 124 | } 125 | 126 | func tableView(_ tableView: YNTableView, didDeselectRowAt indexPath: IndexPath, isExpandableCell: Bool, isExpandedCell: Bool) { 127 | print("Deselected Section: \(indexPath.section) Row: \(indexPath.row) isExpandableCell: \(isExpandableCell) isExpandedCell: \(isExpandedCell)") 128 | } 129 | 130 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 131 | return 50 132 | } 133 | 134 | func numberOfSections(in tableView: UITableView) -> Int { 135 | return 3 136 | } 137 | 138 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 139 | if section == 0 { 140 | return 5 141 | } else if section == 1 { 142 | return 5 143 | } else if section == 2 { 144 | return 5 145 | } 146 | return 0 147 | } 148 | 149 | func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 150 | return 30 151 | } 152 | 153 | func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 154 | if section == 0 { 155 | return "Section 0" 156 | } else if section == 1 { 157 | return "Section 1" 158 | } else if section == 2 { 159 | return "Section 2" 160 | } 161 | return "" 162 | } 163 | } 164 | 165 | -------------------------------------------------------------------------------- /YNExpandableCellDemo/YNExpandableCellEx.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /YNExpandableCellDemo/YNExpandableCells.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YNExpandableCells.swift 3 | // YNExpandableCell 4 | // 5 | // Created by YiSeungyoun on 2017. 3. 14.. 6 | // Copyright © 2017년 SeungyounYi. All rights reserved. 7 | // 8 | 9 | import YNExpandableCell 10 | import UIKit 11 | 12 | class YNExpandableCellEx: YNExpandableCell { 13 | static let ID = "YNExpandableCellEx" 14 | 15 | @IBOutlet var titleLabel: UILabel! 16 | 17 | public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 18 | super.init(style: style, reuseIdentifier: reuseIdentifier) 19 | } 20 | 21 | required public init?(coder aDecoder: NSCoder) { 22 | super.init(coder: aDecoder) 23 | } 24 | 25 | public override func awakeFromNib() { 26 | super.awakeFromNib() 27 | } 28 | } 29 | 30 | class YNSliderCell: UITableViewCell { 31 | static let ID = "YNSliderCell" 32 | 33 | public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 34 | super.init(style: style, reuseIdentifier: reuseIdentifier) 35 | 36 | } 37 | 38 | required public init?(coder aDecoder: NSCoder) { 39 | super.init(coder: aDecoder) 40 | } 41 | 42 | public override func awakeFromNib() { 43 | super.awakeFromNib() 44 | self.selectionStyle = .none 45 | } 46 | 47 | } 48 | 49 | class YNSegmentCell: UITableViewCell { 50 | static let ID = "YNSegmentCell" 51 | 52 | public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 53 | super.init(style: style, reuseIdentifier: reuseIdentifier) 54 | 55 | } 56 | 57 | required public init?(coder aDecoder: NSCoder) { 58 | super.init(coder: aDecoder) 59 | } 60 | 61 | public override func awakeFromNib() { 62 | super.awakeFromNib() 63 | self.selectionStyle = .none 64 | 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /YNExpandableCellDemo/YNSegmentCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /YNExpandableCellDemo/YNSliderCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | --------------------------------------------------------------------------------