├── Demo
├── podsUpdate.command
├── podsInstall.command
├── LGViewControllersDemo
│ ├── Images.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ └── LaunchImage.launchimage
│ │ │ ├── Launch-Pad-L@1x.png
│ │ │ ├── Launch-Pad-L@2x.png
│ │ │ ├── Launch-Pad-P@1x.png
│ │ │ ├── Launch-Pad-P@2x.png
│ │ │ ├── Launch-Phone-35-P@1x.png
│ │ │ ├── Launch-Phone-35-P@2x.png
│ │ │ ├── Launch-Phone-40-P@2x.png
│ │ │ ├── Launch-Phone-47-P@2x.png
│ │ │ ├── Launch-Phone-55-L@3x.png
│ │ │ ├── Launch-Phone-55-P@3x.png
│ │ │ └── Contents.json
│ ├── TableViewController.h
│ ├── NavigationController.h
│ ├── AppDelegate.h
│ ├── DemoTableViewController.h
│ ├── DemoScrollViewController.h
│ ├── DemoCollectionViewController.h
│ ├── main.m
│ ├── NavigationController.m
│ ├── Info.plist
│ ├── AppDelegate.m
│ ├── TableViewController.m
│ ├── DemoScrollViewController.m
│ ├── LaunchScreen.storyboard
│ ├── DemoTableViewController.m
│ └── DemoCollectionViewController.m
├── Podfile
├── LGViewControllersDemo.xcodeproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── project.pbxproj
├── LGViewControllersDemo.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── LGViewControllersDemo.xcscmblueprint
└── Podfile.lock
├── .gitignore
├── LGViewControllers.podspec
├── LICENSE
├── LGViewControllers
├── LGViewControllers.h
├── LGViewControllerAnimator
│ ├── LGViewControllerAnimator.h
│ └── LGViewControllerAnimator.m
├── LGWebViewController
│ ├── LGWebView.h
│ ├── LGWebViewController.h
│ ├── LGWebView.m
│ └── LGWebViewController.m
├── LGScrollViewController
│ ├── LGScrollViewController.h
│ ├── LGScrollView.h
│ ├── LGScrollView.m
│ └── LGScrollViewController.m
├── LGCollectionViewController
│ ├── LGCollectionViewController.h
│ ├── LGCollectionView.h
│ ├── LGCollectionView.m
│ └── LGCollectionViewController.m
└── LGTableViewController
│ ├── LGTableViewController.h
│ ├── LGTableView.h
│ ├── LGTableViewController.m
│ └── LGTableView.m
└── README.md
/Demo/podsUpdate.command:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | cd "$(dirname "$0")"
4 |
5 | pod update
6 |
--------------------------------------------------------------------------------
/Demo/podsInstall.command:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | cd "$(dirname "$0")"
4 |
5 | pod install
6 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 |
4 | ],
5 | "info" : {
6 | "version" : 1,
7 | "author" : "xcode"
8 | }
9 | }
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Pad-L@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Friend-LGA/LGViewControllers/HEAD/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Pad-L@1x.png
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Pad-L@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Friend-LGA/LGViewControllers/HEAD/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Pad-L@2x.png
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Pad-P@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Friend-LGA/LGViewControllers/HEAD/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Pad-P@1x.png
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Pad-P@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Friend-LGA/LGViewControllers/HEAD/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Pad-P@2x.png
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Phone-35-P@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Friend-LGA/LGViewControllers/HEAD/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Phone-35-P@1x.png
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Phone-35-P@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Friend-LGA/LGViewControllers/HEAD/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Phone-35-P@2x.png
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Phone-40-P@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Friend-LGA/LGViewControllers/HEAD/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Phone-40-P@2x.png
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Phone-47-P@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Friend-LGA/LGViewControllers/HEAD/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Phone-47-P@2x.png
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Phone-55-L@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Friend-LGA/LGViewControllers/HEAD/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Phone-55-L@3x.png
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Phone-55-P@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Friend-LGA/LGViewControllers/HEAD/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Launch-Phone-55-P@3x.png
--------------------------------------------------------------------------------
/Demo/Podfile:
--------------------------------------------------------------------------------
1 | source 'https://github.com/CocoaPods/Specs.git'
2 |
3 | platform :ios, '6.0'
4 |
5 | xcodeproj 'LGViewControllersDemo'
6 |
7 | target 'LGViewControllersDemo' do
8 | pod 'LGViewControllers', :path => '../'
9 | end
10 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/TableViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // LGViewControllersDemo
4 | //
5 | // Created by Grigory Lutkov on 18.02.15.
6 | // Copyright (c) 2015 Grigory Lutkov. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface TableViewController : UITableViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/NavigationController.h:
--------------------------------------------------------------------------------
1 | //
2 | // NavigationController.h
3 | // LGViewControllersDemo
4 | //
5 | // Created by Grigory Lutkov on 18.02.15.
6 | // Copyright (c) 2015 Grigory Lutkov. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface NavigationController : UINavigationController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // LGViewControllersDemo
4 | //
5 | // Created by Grigory Lutkov on 18.02.15.
6 | // Copyright (c) 2015 Grigory Lutkov. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/DemoTableViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // DemoTableViewController.h
3 | // LGViewControllersDemo
4 | //
5 | // Created by Grigory Lutkov on 26.03.15.
6 | // Copyright (c) 2015 Grigory Lutkov. All rights reserved.
7 | //
8 |
9 | #import "LGTableViewController.h"
10 |
11 | @interface DemoTableViewController : LGTableViewController
12 |
13 | - (id)initWithTitle:(NSString *)title;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/DemoScrollViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // DemoScrollViewController.h
3 | // LGViewControllersDemo
4 | //
5 | // Created by Grigory Lutkov on 26.03.15.
6 | // Copyright (c) 2015 Grigory Lutkov. All rights reserved.
7 | //
8 |
9 | #import "LGScrollViewController.h"
10 |
11 | @interface DemoScrollViewController : LGScrollViewController
12 |
13 | - (id)initWithTitle:(NSString *)title;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/DemoCollectionViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // DemoCollectionViewController.h
3 | // LGViewControllersDemo
4 | //
5 | // Created by Grigory Lutkov on 26.03.15.
6 | // Copyright (c) 2015 Grigory Lutkov. All rights reserved.
7 | //
8 |
9 | #import "LGCollectionViewController.h"
10 |
11 | @interface DemoCollectionViewController : LGCollectionViewController
12 |
13 | - (id)initWithTitle:(NSString *)title;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // LGViewControllersDemo
4 | //
5 | // Created by Grigory Lutkov on 10.03.15.
6 | // Copyright (c) 2015 Grigory Lutkov. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | build/
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | xcuserdata
13 | *.xccheckout
14 | *.moved-aside
15 | DerivedData
16 | *.hmap
17 | *.ipa
18 | *.xcuserstate
19 |
20 | # CocoaPods
21 | #
22 | # We recommend against adding the Pods directory to your .gitignore. However
23 | # you should judge for yourself, the pros and cons are mentioned at:
24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
25 | #
26 | Pods/
27 |
28 | ###
29 | ._*
30 |
31 | .hgignore
32 |
33 | .DS_Store
34 |
--------------------------------------------------------------------------------
/Demo/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - DACircularProgress (2.3.1)
3 | - LGPlaceholderView (1.0.2)
4 | - LGRefreshView (1.0.3):
5 | - DACircularProgress (~> 2.3.0)
6 | - LGViewControllers (1.0.0):
7 | - LGPlaceholderView (~> 1.0.0)
8 | - LGRefreshView (~> 1.0.0)
9 |
10 | DEPENDENCIES:
11 | - LGViewControllers (from `../`)
12 |
13 | EXTERNAL SOURCES:
14 | LGViewControllers:
15 | :path: ../
16 |
17 | SPEC CHECKSUMS:
18 | DACircularProgress: 4dd437c0fc3da5161cb289e07ac449493d41db71
19 | LGPlaceholderView: 37ae1eaca38ace1418ae74e4d9db8fa5738367a2
20 | LGRefreshView: 2f3059fcb41abe8a3e032b8f5ea8b9b345869a64
21 | LGViewControllers: 7c46dc5105d1872105a787db00900a439793448d
22 |
23 | COCOAPODS: 0.39.0
24 |
--------------------------------------------------------------------------------
/LGViewControllers.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 |
3 | s.name = 'LGViewControllers'
4 | s.version = '1.0.0'
5 | s.platform = :ios, '6.0'
6 | s.license = 'MIT'
7 | s.homepage = 'https://github.com/Friend-LGA/LGViewControllers'
8 | s.author = { 'Grigory Lutkov' => 'Friend.LGA@gmail.com' }
9 | s.source = { :git => 'https://github.com/Friend-LGA/LGViewControllers.git', :tag => s.version }
10 | s.summary = 'Classes extends abilities of UITableViewController, UICollectionViewController, and more'
11 |
12 | s.requires_arc = true
13 |
14 | s.source_files = 'LGViewControllers/*.{h,m}'
15 | s.source_files = 'LGViewControllers/**/*.{h,m}'
16 |
17 | s.dependency 'LGRefreshView', '~> 1.0.0'
18 | s.dependency 'LGPlaceholderView', '~> 1.0.0'
19 |
20 | end
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Grigory Lutkov
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 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/NavigationController.m:
--------------------------------------------------------------------------------
1 | //
2 | // NavigationController.m
3 | // LGViewControllersDemo
4 | //
5 | // Created by Grigory Lutkov on 18.02.15.
6 | // Copyright (c) 2015 Grigory Lutkov. All rights reserved.
7 | //
8 |
9 | #import "NavigationController.h"
10 | #import "TableViewController.h"
11 |
12 | @interface NavigationController ()
13 |
14 | @end
15 |
16 | @implementation NavigationController
17 |
18 | - (void)viewDidLoad
19 | {
20 | [super viewDidLoad];
21 |
22 | self.navigationBar.translucent = YES;
23 | self.navigationBar.barTintColor = [UIColor colorWithRed:0.f green:0.5 blue:1.f alpha:1.f];
24 | self.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName: [UIColor whiteColor]};
25 | self.navigationBar.tintColor = [UIColor colorWithWhite:1.f alpha:0.5];
26 | }
27 |
28 | - (BOOL)shouldAutorotate
29 | {
30 | return YES;
31 | }
32 |
33 | - (BOOL)prefersStatusBarHidden
34 | {
35 | return UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation);
36 | }
37 |
38 | - (UIStatusBarStyle)preferredStatusBarStyle
39 | {
40 | return UIStatusBarStyleLightContent;
41 | }
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/LGViewControllers/LGViewControllers.h:
--------------------------------------------------------------------------------
1 | //
2 | // LGViewControllers.h
3 | // LGViewControllers
4 | //
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Copyright (c) 2015 Grigory Lutkov
9 | // (https://github.com/Friend-LGA/LGViewControllers)
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 | //
29 |
30 | #import "LGScrollViewController.h"
31 | #import "LGTableViewController.h"
32 | #import "LGCollectionViewController.h"
33 | #import "LGWebViewController.h"
34 | #import "LGViewControllerAnimator.h"
35 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/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 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/LGViewControllers/LGViewControllerAnimator/LGViewControllerAnimator.h:
--------------------------------------------------------------------------------
1 | //
2 | // LGViewControllerAnimator.h
3 | // LGViewControllers
4 | //
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Copyright (c) 2015 Grigory Lutkov
9 | // (https://github.com/Friend-LGA/LGViewControllers)
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 | //
29 |
30 | #import
31 |
32 | @interface LGViewControllerAnimator : NSObject
33 |
34 | @property (assign, nonatomic, getter=isGoingRight) BOOL goingRight;
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/LGViewControllers/LGWebViewController/LGWebView.h:
--------------------------------------------------------------------------------
1 | //
2 | // LGWebView.h
3 | // LGViewControllers
4 | //
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Copyright (c) 2015 Grigory Lutkov
9 | // (https://github.com/Friend-LGA/LGViewControllers)
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 | //
29 |
30 | #import
31 | #import "LGPlaceholderView.h"
32 |
33 | @interface LGWebView : UIWebView
34 |
35 | @property (assign, nonatomic, getter=isPlaceholderViewEnabled) BOOL placeholderViewEnabled;
36 |
37 | @property (strong, nonatomic) LGPlaceholderView *placeholderView;
38 |
39 | - (instancetype)initWithPlaceholderViewEnabled:(BOOL)placeholderViewEnabled;
40 |
41 | - (void)removeBackgroundImages;
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/LGViewControllers/LGWebViewController/LGWebViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // LGWebViewController.h
3 | // LGViewControllers
4 | //
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Copyright (c) 2015 Grigory Lutkov
9 | // (https://github.com/Friend-LGA/LGViewControllers)
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 | //
29 |
30 | #import
31 | #import "LGWebView.h"
32 |
33 | @interface LGWebViewController : UIViewController
34 |
35 | @property (strong, nonatomic) LGWebView *webView;
36 |
37 | @property (assign, nonatomic, getter=isOpenLinksInside) BOOL openLinksInside;
38 |
39 | - (instancetype)initWithPlaceholderViewEnabled:(BOOL)placeholderViewEnabled;
40 |
41 | - (instancetype)initWithTitle:(NSString *)title url:(NSURL *)url;
42 | - (instancetype)initWithTitle:(NSString *)title url:(NSURL *)url placeholderViewEnabled:(BOOL)placeholderViewEnabled;
43 |
44 | - (void)loadingDidFinishWithError:(NSError *)error;
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/LGViewControllers/LGScrollViewController/LGScrollViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // LGScrollViewController.h
3 | // LGViewControllers
4 | //
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Copyright (c) 2015 Grigory Lutkov
9 | // (https://github.com/Friend-LGA/LGViewControllers)
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 | //
29 |
30 | #import
31 | #import "LGScrollView.h"
32 |
33 | @interface LGScrollViewController : UIViewController
34 |
35 | @property (strong, nonatomic) LGScrollView *scrollView;
36 |
37 | @property (assign, nonatomic, getter=isKeyboardShowHideObserverEnabled) BOOL keyboardShowHideObserverEnabled;
38 |
39 | - (instancetype)initWithPlaceholderViewEnabled:(BOOL)placeholderViewEnabled refreshViewEnabled:(BOOL)refreshViewEnabled;
40 |
41 | - (void)refreshActions;
42 |
43 | - (void)keyboardWillShowHideNotification:(NSNotification *)notification;
44 | - (void)keyboardWillShowHideActionsAppear:(BOOL)appear keyboardHeight:(CGFloat)keyboardHeight;
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/LGViewControllers/LGCollectionViewController/LGCollectionViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // LGCollectionViewController.h
3 | // LGViewControllers
4 | //
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Copyright (c) 2015 Grigory Lutkov
9 | // (https://github.com/Friend-LGA/LGViewControllers)
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 | //
29 |
30 | #import
31 | #import "LGCollectionView.h"
32 |
33 | @interface LGCollectionViewController : UIViewController
34 |
35 | @property (strong, nonatomic) LGCollectionView *collectionView;
36 |
37 | @property (assign, nonatomic, getter=isKeyboardShowHideObserverEnabled) BOOL keyboardShowHideObserverEnabled;
38 |
39 | - (instancetype)initWithPlaceholderViewEnabled:(BOOL)placeholderViewEnabled refreshViewEnabled:(BOOL)refreshViewEnabled;
40 |
41 | - (void)refreshActions;
42 |
43 | - (void)keyboardWillShowHideNotification:(NSNotification *)notification;
44 | - (void)keyboardWillShowHideActionsAppear:(BOOL)appear keyboardHeight:(CGFloat)keyboardHeight;
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo.xcworkspace/xcshareddata/LGViewControllersDemo.xcscmblueprint:
--------------------------------------------------------------------------------
1 | {
2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "D1921A8DD95A49CEC02E603F7AFFE0B0D9E417F2",
3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
4 |
5 | },
6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
7 | "E2313CDD6C163A5D9D19AAF2AA5600F33F4ACE5E" : 0,
8 | "4029278A4951E3FF130BF388365315DBA49FB6A4" : 0,
9 | "D1921A8DD95A49CEC02E603F7AFFE0B0D9E417F2" : 0
10 | },
11 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "136A9ED3-45AA-42D8-8C59-D11727B9AB51",
12 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
13 | "E2313CDD6C163A5D9D19AAF2AA5600F33F4ACE5E" : "LGPlaceholderView",
14 | "4029278A4951E3FF130BF388365315DBA49FB6A4" : "LGRefreshView",
15 | "D1921A8DD95A49CEC02E603F7AFFE0B0D9E417F2" : "LGViewControllers"
16 | },
17 | "DVTSourceControlWorkspaceBlueprintNameKey" : "LGViewControllersDemo",
18 | "DVTSourceControlWorkspaceBlueprintVersion" : 204,
19 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "Demo\/LGViewControllersDemo.xcworkspace",
20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
21 | {
22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/Friend-LGA\/LGRefreshView.git",
23 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
24 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "4029278A4951E3FF130BF388365315DBA49FB6A4"
25 | },
26 | {
27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/Friend-LGA\/LGViewControllers.git",
28 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
29 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "D1921A8DD95A49CEC02E603F7AFFE0B0D9E417F2"
30 | },
31 | {
32 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/Friend-LGA\/LGPlaceholderView.git",
33 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
34 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "E2313CDD6C163A5D9D19AAF2AA5600F33F4ACE5E"
35 | }
36 | ]
37 | }
--------------------------------------------------------------------------------
/LGViewControllers/LGScrollViewController/LGScrollView.h:
--------------------------------------------------------------------------------
1 | //
2 | // LGScrollView.h
3 | // LGViewControllers
4 | //
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Copyright (c) 2015 Grigory Lutkov
9 | // (https://github.com/Friend-LGA/LGViewControllers)
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 | //
29 |
30 | #import
31 | #import "LGPlaceholderView.h"
32 | #import "LGRefreshView.h"
33 |
34 | @interface LGScrollView : UIScrollView
35 |
36 | @property (assign, nonatomic, readonly, getter=isRefreshViewEnabled) BOOL refreshViewEnabled;
37 | @property (assign, nonatomic, getter=isPlaceholderViewEnabled) BOOL placeholderViewEnabled;
38 |
39 | @property (strong, nonatomic) LGRefreshView *refreshView;
40 | @property (strong, nonatomic) LGPlaceholderView *placeholderView;
41 |
42 | /** Do not forget about weak referens to self for refreshHandler block */
43 | - (instancetype)initWithPlaceholderViewEnabled:(BOOL)placeholderViewEnabled refreshHandler:(void(^)())refreshHandler;
44 |
45 | - (void)addTopSeparatorViewWithColor:(UIColor *)color thinckness:(CGFloat)thinckness edgeInsets:(UIEdgeInsets)edgeInsets;
46 |
47 | /** Do not forget about weak referens to self for refreshHandler block */
48 | - (void)setRefreshViewEnabledWithHandler:(void(^)())refreshHandler;
49 | - (void)setRefreshViewDisabled;
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/LGViewControllers/LGTableViewController/LGTableViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // LGTableViewController.h
3 | // LGViewControllers
4 | //
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Copyright (c) 2015 Grigory Lutkov
9 | // (https://github.com/Friend-LGA/LGViewControllers)
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 | //
29 |
30 | #import
31 | #import "LGTableView.h"
32 |
33 | @interface LGTableViewController : UIViewController
34 |
35 | @property (strong, nonatomic) LGTableView *tableView;
36 |
37 | @property (assign, nonatomic, getter=isKeyboardShowHideObserverEnabled) BOOL keyboardShowHideObserverEnabled;
38 |
39 | - (instancetype)initWithStyle:(UITableViewStyle)style;
40 | - (instancetype)initWithStyle:(UITableViewStyle)style asyncCalculatingHeightForRows:(BOOL)asyncCalculatingHeightForRows;
41 | - (instancetype)initWithStyle:(UITableViewStyle)style asyncCalculatingHeightForRows:(BOOL)asyncCalculatingHeightForRows placeholderViewEnabled:(BOOL)placeholderViewEnabled refreshViewEnabled:(BOOL)refreshViewEnabled;
42 |
43 | - (void)refreshActions;
44 |
45 | - (void)keyboardWillShowHideNotification:(NSNotification *)notification;
46 | - (void)keyboardWillShowHideActionsAppear:(BOOL)appear keyboardHeight:(CGFloat)keyboardHeight;
47 |
48 | @end
49 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // LGViewControllersDemo
4 | //
5 | // Created by Grigory Lutkov on 18.02.15.
6 | // Copyright (c) 2015 Grigory Lutkov. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 | #import "NavigationController.h"
11 | #import "TableViewController.h"
12 |
13 | @implementation AppDelegate
14 |
15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
16 | {
17 | TableViewController *tableViewController = [TableViewController new];
18 | NavigationController *navigationController = [[NavigationController alloc] initWithRootViewController:tableViewController];
19 |
20 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
21 | self.window.rootViewController = navigationController;
22 | self.window.backgroundColor = [UIColor whiteColor];
23 | [self.window makeKeyAndVisible];
24 |
25 | return YES;
26 | }
27 |
28 | - (void)applicationWillResignActive:(UIApplication *)application
29 | {
30 | // 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.
31 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
32 | }
33 |
34 | - (void)applicationDidEnterBackground:(UIApplication *)application
35 | {
36 | // 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.
37 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
38 | }
39 |
40 | - (void)applicationWillEnterForeground:(UIApplication *)application
41 | {
42 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
43 | }
44 |
45 | - (void)applicationDidBecomeActive:(UIApplication *)application
46 | {
47 | // 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.
48 | }
49 |
50 | - (void)applicationWillTerminate:(UIApplication *)application
51 | {
52 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
53 | }
54 |
55 | @end
56 |
--------------------------------------------------------------------------------
/LGViewControllers/LGViewControllerAnimator/LGViewControllerAnimator.m:
--------------------------------------------------------------------------------
1 | //
2 | // LGViewControllerAnimator.m
3 | // LGViewControllers
4 | //
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Copyright (c) 2015 Grigory Lutkov
9 | // (https://github.com/Friend-LGA/LGViewControllers)
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 | //
29 |
30 | #import "LGViewControllerAnimator.h"
31 |
32 | static CGFloat const kChildViewPadding = 0.f;
33 | static CGFloat const kSpringDamping = 1.f;
34 | static CGFloat const kSpringVelocity = 0.5f;
35 |
36 | @implementation LGViewControllerAnimator
37 |
38 | - (NSTimeInterval)transitionDuration:(id)transitionContext
39 | {
40 | return 0.5;
41 | }
42 |
43 | - (void)animateTransition:(id)transitionContext
44 | {
45 | UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
46 | UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
47 |
48 | CGFloat travelDistance = [transitionContext containerView].bounds.size.width + kChildViewPadding;
49 | CGAffineTransform travel = CGAffineTransformMakeTranslation (_goingRight ? travelDistance : -travelDistance, 0);
50 |
51 | [[transitionContext containerView] addSubview:toViewController.view];
52 | toViewController.view.alpha = 0;
53 | toViewController.view.transform = CGAffineTransformInvert(travel);
54 |
55 | [UIView animateWithDuration:[self transitionDuration:transitionContext]
56 | delay:0.0
57 | usingSpringWithDamping:kSpringDamping
58 | initialSpringVelocity:kSpringVelocity
59 | options:0
60 | animations:^(void)
61 | {
62 | fromViewController.view.transform = travel;
63 | fromViewController.view.alpha = 0;
64 | toViewController.view.transform = CGAffineTransformIdentity;
65 | toViewController.view.alpha = 1;
66 | }
67 | completion:^(BOOL finished)
68 | {
69 | fromViewController.view.transform = CGAffineTransformIdentity;
70 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
71 | }];
72 | }
73 |
74 | @end
75 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/TableViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // LGViewControllersDemo
4 | //
5 | // Created by Grigory Lutkov on 18.02.15.
6 | // Copyright (c) 2015 Grigory Lutkov. All rights reserved.
7 | //
8 |
9 | #import "TableViewController.h"
10 | #import "DemoScrollViewController.h"
11 | #import "DemoTableViewController.h"
12 | #import "DemoCollectionViewController.h"
13 | #import "LGWebViewController.h"
14 |
15 | @interface TableViewController ()
16 |
17 | @property (strong, nonatomic) NSArray *titlesArray;
18 |
19 | @end
20 |
21 | @implementation TableViewController
22 |
23 | - (id)init
24 | {
25 | self = [super initWithStyle:UITableViewStylePlain];
26 | if (self)
27 | {
28 | self.title = @"LGViewControllers";
29 |
30 | _titlesArray = @[@"LGScrollViewController",
31 | @"LGTableViewController",
32 | @"LGCollectionViewController",
33 | @"LGWebViewController"];
34 |
35 | [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
36 | }
37 | return self;
38 | }
39 |
40 | #pragma mark - UITableView DataSource
41 |
42 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
43 | {
44 | return 1;
45 | }
46 |
47 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
48 | {
49 | return _titlesArray.count;
50 | }
51 |
52 | #pragma mark - UITableView Delegate
53 |
54 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
55 | {
56 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
57 |
58 | cell.textLabel.font = [UIFont systemFontOfSize:16.f];
59 | cell.textLabel.text = _titlesArray[indexPath.row];
60 |
61 | return cell;
62 | }
63 |
64 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
65 | {
66 | return 44.f;
67 | }
68 |
69 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
70 | {
71 | if (indexPath.row == 0)
72 | {
73 | DemoScrollViewController *viewController = [[DemoScrollViewController alloc] initWithTitle:_titlesArray[indexPath.row]];
74 | [self.navigationController pushViewController:viewController animated:YES];
75 | }
76 | else if (indexPath.row == 1)
77 | {
78 | DemoTableViewController *viewController = [[DemoTableViewController alloc] initWithTitle:_titlesArray[indexPath.row]];
79 | [self.navigationController pushViewController:viewController animated:YES];
80 | }
81 | else if (indexPath.row == 2)
82 | {
83 | DemoCollectionViewController *viewController = [[DemoCollectionViewController alloc] initWithTitle:_titlesArray[indexPath.row]];
84 | [self.navigationController pushViewController:viewController animated:YES];
85 | }
86 | else if (indexPath.row == 3)
87 | {
88 | LGWebViewController *viewController = [[LGWebViewController alloc] initWithTitle:_titlesArray[indexPath.row]
89 | url:[NSURL URLWithString:@"http://google.com"]
90 | placeholderViewEnabled:YES];
91 | viewController.webView.placeholderView.backgroundColor = [UIColor whiteColor];
92 | [self.navigationController pushViewController:viewController animated:YES];
93 | }
94 | }
95 |
96 | @end
97 |
--------------------------------------------------------------------------------
/LGViewControllers/LGWebViewController/LGWebView.m:
--------------------------------------------------------------------------------
1 | //
2 | // LGWebView.m
3 | // LGViewControllers
4 | //
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Copyright (c) 2015 Grigory Lutkov
9 | // (https://github.com/Friend-LGA/LGViewControllers)
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 | //
29 |
30 | #import "LGWebView.h"
31 |
32 | @implementation LGWebView
33 |
34 | - (instancetype)init
35 | {
36 | self = [super init];
37 | if (self)
38 | {
39 | [self initializeWithPlaceholderViewEnabled:NO];
40 | }
41 | return self;
42 | }
43 |
44 | - (instancetype)initWithFrame:(CGRect)frame
45 | {
46 | self = [super initWithFrame:frame];
47 | if (self)
48 | {
49 | [self initializeWithPlaceholderViewEnabled:NO];
50 | }
51 | return self;
52 | }
53 |
54 | - (instancetype)initWithPlaceholderViewEnabled:(BOOL)placeholderViewEnabled
55 | {
56 | self = [super init];
57 | if (self)
58 | {
59 | [self initializeWithPlaceholderViewEnabled:placeholderViewEnabled];
60 | }
61 | return self;
62 | }
63 |
64 | - (void)initializeWithPlaceholderViewEnabled:(BOOL)placeholderViewEnabled
65 | {
66 | self.placeholderViewEnabled = placeholderViewEnabled;
67 | }
68 |
69 | #pragma mark - Dealloc
70 |
71 | - (void)dealloc
72 | {
73 | #if DEBUG
74 | NSLog(@"%s [Line %d]", __PRETTY_FUNCTION__, __LINE__);
75 | #endif
76 | }
77 |
78 | #pragma mark -
79 |
80 | - (void)removeBackgroundImages
81 | {
82 | if ([UIDevice currentDevice].systemVersion.floatValue < 7)
83 | for (UIImageView *imageView in self.scrollView.subviews)
84 | if ([imageView isKindOfClass:[UIImageView class]] && imageView.image.size.width == 1)
85 | imageView.hidden = YES;
86 | }
87 |
88 | - (void)setPlaceholderViewEnabled:(BOOL)placeholderViewEnabled
89 | {
90 | if (_placeholderViewEnabled != placeholderViewEnabled)
91 | {
92 | _placeholderViewEnabled = placeholderViewEnabled;
93 |
94 | if (_placeholderViewEnabled && !_placeholderView)
95 | _placeholderView = [LGPlaceholderView placeholderViewWithView:self.scrollView];
96 | else if (!_placeholderViewEnabled && _placeholderView)
97 | {
98 | if (_placeholderView.superview)
99 | [_placeholderView removeFromSuperview];
100 |
101 | _placeholderView = nil;
102 | }
103 | }
104 | }
105 |
106 | @end
107 |
--------------------------------------------------------------------------------
/LGViewControllers/LGCollectionViewController/LGCollectionView.h:
--------------------------------------------------------------------------------
1 | //
2 | // LGCollectionView.h
3 | // LGViewControllers
4 | //
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Copyright (c) 2015 Grigory Lutkov
9 | // (https://github.com/Friend-LGA/LGViewControllers)
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 | //
29 |
30 | #import
31 | #import "LGPlaceholderView.h"
32 | #import "LGRefreshView.h"
33 |
34 | @interface LGCollectionView : UICollectionView
35 |
36 | @property (assign, nonatomic, readonly, getter=isRefreshViewEnabled) BOOL refreshViewEnabled;
37 | @property (assign, nonatomic, getter=isPlaceholderViewEnabled) BOOL placeholderViewEnabled;
38 |
39 | @property (strong, nonatomic) LGRefreshView *refreshView;
40 | @property (strong, nonatomic) LGPlaceholderView *placeholderView;
41 |
42 | /** Do not forget about weak referens to self for refreshHandler block */
43 | - (instancetype)initWithPlaceholderViewEnabled:(BOOL)placeholderViewEnabled refreshHandler:(void(^)())refreshHandler;
44 |
45 | /** Do not forget about weak referens to self for refreshHandler block */
46 | - (void)setRefreshViewEnabledWithHandler:(void(^)())refreshHandler;
47 | - (void)setRefreshViewDisabled;
48 |
49 | - (void)addTopSeparatorViewWithColor:(UIColor *)color thinckness:(CGFloat)thinckness edgeInsets:(UIEdgeInsets)edgeInsets;
50 |
51 | - (void)setViewWidth:(CGFloat)viewWidth
52 | cellAspect:(CGFloat)cellAspect
53 | numberOfCellsInARow:(NSUInteger)numberOfCellsInARow
54 | cellInsets:(CGFloat)cellInsets
55 | sectionInsets:(UIEdgeInsets)sectionInsets
56 | headerReferenceSize:(CGSize)headerReferenceSize
57 | footerReferenceSize:(CGSize)footerReferenceSize
58 | scrollDirection:(UICollectionViewScrollDirection)scrollDirection;
59 |
60 | - (void)setViewWidth:(CGFloat)viewWidth
61 | cellHeight:(CGFloat)cellHeight
62 | numberOfCellsInARow:(NSUInteger)numberOfCellsInARow
63 | cellInsets:(CGFloat)cellInsets
64 | sectionInsets:(UIEdgeInsets)sectionInsets
65 | headerReferenceSize:(CGSize)headerReferenceSize
66 | footerReferenceSize:(CGSize)footerReferenceSize
67 | scrollDirection:(UICollectionViewScrollDirection)scrollDirection;
68 |
69 | - (void)setCellWidth:(CGFloat)cellWidth
70 | cellHeight:(CGFloat)cellHeight
71 | cellInsets:(CGFloat)cellInsets
72 | sectionInsets:(UIEdgeInsets)sectionInsets
73 | headerReferenceSize:(CGSize)headerReferenceSize
74 | footerReferenceSize:(CGSize)footerReferenceSize
75 | scrollDirection:(UICollectionViewScrollDirection)scrollDirection;
76 |
77 | @end
78 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/Images.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "extent" : "full-screen",
5 | "idiom" : "iphone",
6 | "subtype" : "736h",
7 | "filename" : "Launch-Phone-55-P@3x.png",
8 | "minimum-system-version" : "8.0",
9 | "orientation" : "portrait",
10 | "scale" : "3x"
11 | },
12 | {
13 | "extent" : "full-screen",
14 | "idiom" : "iphone",
15 | "subtype" : "736h",
16 | "filename" : "Launch-Phone-55-L@3x.png",
17 | "minimum-system-version" : "8.0",
18 | "orientation" : "landscape",
19 | "scale" : "3x"
20 | },
21 | {
22 | "extent" : "full-screen",
23 | "idiom" : "iphone",
24 | "subtype" : "667h",
25 | "filename" : "Launch-Phone-47-P@2x.png",
26 | "minimum-system-version" : "8.0",
27 | "orientation" : "portrait",
28 | "scale" : "2x"
29 | },
30 | {
31 | "orientation" : "portrait",
32 | "idiom" : "iphone",
33 | "extent" : "full-screen",
34 | "minimum-system-version" : "7.0",
35 | "filename" : "Launch-Phone-35-P@2x.png",
36 | "scale" : "2x"
37 | },
38 | {
39 | "extent" : "full-screen",
40 | "idiom" : "iphone",
41 | "subtype" : "retina4",
42 | "filename" : "Launch-Phone-40-P@2x.png",
43 | "minimum-system-version" : "7.0",
44 | "orientation" : "portrait",
45 | "scale" : "2x"
46 | },
47 | {
48 | "orientation" : "portrait",
49 | "idiom" : "ipad",
50 | "extent" : "full-screen",
51 | "minimum-system-version" : "7.0",
52 | "filename" : "Launch-Pad-P@1x.png",
53 | "scale" : "1x"
54 | },
55 | {
56 | "orientation" : "landscape",
57 | "idiom" : "ipad",
58 | "extent" : "full-screen",
59 | "minimum-system-version" : "7.0",
60 | "filename" : "Launch-Pad-L@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "orientation" : "portrait",
65 | "idiom" : "ipad",
66 | "extent" : "full-screen",
67 | "minimum-system-version" : "7.0",
68 | "filename" : "Launch-Pad-P@2x.png",
69 | "scale" : "2x"
70 | },
71 | {
72 | "orientation" : "landscape",
73 | "idiom" : "ipad",
74 | "extent" : "full-screen",
75 | "minimum-system-version" : "7.0",
76 | "filename" : "Launch-Pad-L@2x.png",
77 | "scale" : "2x"
78 | },
79 | {
80 | "orientation" : "portrait",
81 | "idiom" : "iphone",
82 | "extent" : "full-screen",
83 | "filename" : "Launch-Phone-35-P@1x.png",
84 | "scale" : "1x"
85 | },
86 | {
87 | "orientation" : "portrait",
88 | "idiom" : "iphone",
89 | "extent" : "full-screen",
90 | "filename" : "Launch-Phone-35-P@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "orientation" : "portrait",
95 | "idiom" : "iphone",
96 | "extent" : "full-screen",
97 | "filename" : "Launch-Phone-40-P@2x.png",
98 | "subtype" : "retina4",
99 | "scale" : "2x"
100 | },
101 | {
102 | "orientation" : "portrait",
103 | "idiom" : "ipad",
104 | "extent" : "full-screen",
105 | "filename" : "Launch-Pad-P@1x.png",
106 | "scale" : "1x"
107 | },
108 | {
109 | "orientation" : "landscape",
110 | "idiom" : "ipad",
111 | "extent" : "full-screen",
112 | "filename" : "Launch-Pad-L@1x.png",
113 | "scale" : "1x"
114 | },
115 | {
116 | "orientation" : "portrait",
117 | "idiom" : "ipad",
118 | "extent" : "full-screen",
119 | "filename" : "Launch-Pad-P@2x.png",
120 | "scale" : "2x"
121 | },
122 | {
123 | "orientation" : "landscape",
124 | "idiom" : "ipad",
125 | "extent" : "full-screen",
126 | "filename" : "Launch-Pad-L@2x.png",
127 | "scale" : "2x"
128 | }
129 | ],
130 | "info" : {
131 | "version" : 1,
132 | "author" : "xcode"
133 | }
134 | }
--------------------------------------------------------------------------------
/LGViewControllers/LGTableViewController/LGTableView.h:
--------------------------------------------------------------------------------
1 | //
2 | // LGTableView.h
3 | // LGViewControllers
4 | //
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Copyright (c) 2015 Grigory Lutkov
9 | // (https://github.com/Friend-LGA/LGViewControllers)
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 | //
29 |
30 | #import
31 | #import "LGPlaceholderView.h"
32 | #import "LGRefreshView.h"
33 |
34 | @class LGTableView;
35 |
36 | @protocol LGTableViewDelegate
37 |
38 | @required
39 |
40 | - (CGFloat)tableView:(LGTableView *)tableView heightForRowAtIndexPathAsync:(NSIndexPath *)indexPath;
41 |
42 | @end
43 |
44 | @interface LGTableView : UITableView
45 |
46 | @property (strong, nonatomic, readonly) NSMutableArray *heightForRowsArray;
47 |
48 | @property (assign, nonatomic) id delegateLG;
49 |
50 | @property (assign, nonatomic, readonly, getter=isRefreshViewEnabled) BOOL refreshViewEnabled;
51 | @property (assign, nonatomic, getter=isPlaceholderViewEnabled) BOOL placeholderViewEnabled;
52 |
53 | @property (strong, nonatomic) LGRefreshView *refreshView;
54 | @property (strong, nonatomic) LGPlaceholderView *placeholderView;
55 |
56 | - (instancetype)initWithStyle:(UITableViewStyle)style;
57 |
58 | /** Do not forget about weak referens to self for refreshHandler block */
59 | - (instancetype)initWithStyle:(UITableViewStyle)style placeholderViewEnabled:(BOOL)placeholderViewEnabled refreshHandler:(void(^)())refreshHandler;
60 |
61 | /** Do not forget about weak referens to self for refreshHandler block */
62 | - (void)setRefreshViewEnabledWithHandler:(void(^)())refreshHandler;
63 | - (void)setRefreshViewDisabled;
64 |
65 | - (void)addTopSeparatorViewWithColor:(UIColor *)color thinckness:(CGFloat)thinckness edgeInsets:(UIEdgeInsets)edgeInsets;
66 |
67 | #pragma mark -
68 |
69 | - (void)reloadDataWithCompletionHandler:(void(^)())completionHandler;
70 | - (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation completionHandler:(void(^)())completionHandler;
71 | - (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation completionHandler:(void(^)())completionHandler;
72 |
73 | #pragma mark -
74 |
75 | - (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation completionHandler:(void(^)())completionHandler;
76 | - (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation completionHandler:(void(^)())completionHandler;
77 |
78 | #pragma mark -
79 |
80 | - (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation completionHandler:(void(^)())completionHandler;
81 | - (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation completionHandler:(void(^)())completionHandler;
82 |
83 | #pragma mark -
84 |
85 | - (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath completionHandler:(void(^)())completionHandler;
86 | - (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection completionHandler:(void(^)())completionHandler;
87 |
88 | @end
89 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/DemoScrollViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // DemoScrollViewController.m
3 | // LGViewControllersDemo
4 | //
5 | // Created by Grigory Lutkov on 26.03.15.
6 | // Copyright (c) 2015 Grigory Lutkov. All rights reserved.
7 | //
8 |
9 | #import "DemoScrollViewController.h"
10 |
11 | @interface DemoScrollViewController ()
12 |
13 | @property (strong, nonatomic) UILabel *label;
14 | @property (strong, nonatomic) UITextField *textField;
15 |
16 | @end
17 |
18 | @implementation DemoScrollViewController
19 |
20 | - (id)initWithTitle:(NSString *)title
21 | {
22 | self = [super initWithPlaceholderViewEnabled:YES refreshViewEnabled:YES];
23 | if (self)
24 | {
25 | self.title = title;
26 |
27 | self.view.backgroundColor = [UIColor whiteColor];
28 |
29 | _label = [UILabel new];
30 | _label.text = @"Updated never";
31 | _label.textColor = [UIColor blackColor];
32 | [self.scrollView addSubview:_label];
33 |
34 | _textField = [UITextField new];
35 | _textField.placeholder = @"UITextField";
36 | _textField.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1.f];
37 | [self.scrollView addSubview:_textField];
38 |
39 | self.scrollView.alwaysBounceVertical = YES;
40 |
41 | UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(gestureAction)];
42 | gesture.delegate = self;
43 | [self.scrollView addGestureRecognizer:gesture];
44 |
45 | self.keyboardShowHideObserverEnabled = YES;
46 |
47 | [self.scrollView.placeholderView showActivityIndicatorAnimated:NO completionHandler:nil];
48 | }
49 | return self;
50 | }
51 |
52 | #pragma mark - Dealloc
53 |
54 | - (void)dealloc
55 | {
56 | NSLog(@"%s [Line %d]", __PRETTY_FUNCTION__, __LINE__);
57 | }
58 |
59 | #pragma mark - Appearing
60 |
61 | - (void)viewWillLayoutSubviews
62 | {
63 | [super viewWillLayoutSubviews];
64 |
65 | CGFloat shift = 20.f;
66 |
67 | [_label sizeToFit];
68 | _label.center = CGPointMake(self.view.frame.size.width/2, shift+_label.frame.size.height/2);
69 | _label.frame = CGRectIntegral(_label.frame);
70 |
71 | _textField.frame = CGRectMake(10.f, self.scrollView.frame.size.height-self.scrollView.contentInset.top-shift-44.f, self.view.frame.size.width-20.f, 44.f);
72 | _textField.frame = CGRectIntegral(_textField.frame);
73 |
74 | self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width, _textField.frame.origin.y+_textField.frame.size.height+shift);
75 | }
76 |
77 | - (void)viewDidAppear:(BOOL)animated
78 | {
79 | [super viewDidAppear:animated];
80 |
81 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^(void)
82 | {
83 | [self.scrollView.placeholderView dismissAnimated:YES completionHandler:nil];
84 | });
85 | }
86 |
87 | #pragma mark - Refresh
88 |
89 | - (void)refreshActions
90 | {
91 | NSDate *date = [NSDate date];
92 |
93 | NSDateFormatter *dateFormatter = [NSDateFormatter new];
94 | dateFormatter.dateFormat = @"dd.MM.yyyy HH:mm:ss";
95 |
96 | _label.text = [NSString stringWithFormat:@"Updated %@", [dateFormatter stringFromDate:date]];
97 |
98 | CGFloat shift = 20.f;
99 |
100 | [_label sizeToFit];
101 | _label.center = CGPointMake(self.scrollView.frame.size.width/2, shift+_label.frame.size.height/2);
102 |
103 | [UIView transitionWithView:_label duration:0.3 options:UIViewAnimationOptionTransitionCrossDissolve animations:nil completion:nil];
104 |
105 | [self.scrollView.refreshView endRefreshing];
106 | }
107 |
108 | #pragma mark - Keyboard
109 |
110 | - (void)keyboardWillShowHideActionsAppear:(BOOL)appear keyboardHeight:(CGFloat)keyboardHeight
111 | {
112 | [super keyboardWillShowHideActionsAppear:appear keyboardHeight:keyboardHeight];
113 |
114 | if (appear)
115 | [self.scrollView scrollRectToVisible:_textField.frame animated:NO];
116 | }
117 |
118 | #pragma mark - UIGestureRecognizer Delegate
119 |
120 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
121 | {
122 | return ![touch.view isKindOfClass:[UIControl class]];
123 | }
124 |
125 | #pragma mark -
126 |
127 | - (void)gestureAction
128 | {
129 | [self.view endEditing:YES];
130 | }
131 |
132 | @end
133 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # LGViewControllers
2 |
3 | Classes extends abilities of UITableViewController, UICollectionViewController, and more.
4 | - [LGScrollViewController](https://github.com/Friend-LGA/LGViewControllers/blob/master/LGViewControllers/LGScrollViewController/LGScrollViewController.h) is view controller with LGScrollView as root view, that has LGPlaceholderView and LGRefreshView by default. View controller can watch for show/hide keyboard actions and scroll to first responder view without any manipulation.
5 | - [LGTableViewController](https://github.com/Friend-LGA/LGViewControllers/blob/master/LGViewControllers/LGTableViewController/LGTableViewController.h) can do everything like LGScrollViewController, more than that it can reload table view asynchronously, without freezing UI.
6 | - [LGCollectionViewController](https://github.com/Friend-LGA/LGViewControllers/blob/master/LGViewControllers/LGCollectionViewController/LGCollectionViewController.h) can do everything like LGScrollViewController, more than that it has easy initialization methods, to faster setup layout.
7 | - [LGWebViewController](https://github.com/Friend-LGA/LGViewControllers/blob/master/LGViewControllers/LGWebViewController/LGWebViewController.h) is view controller with LGWebView as root view, that has LGPlaceholderView by default. View controller has easy initialization methods, to use it without subclassing.
8 | - [LGViewControllerAnimator](https://github.com/Friend-LGA/LGViewControllers/blob/master/LGViewControllers/LGViewControllerAnimator/LGViewControllerAnimator.h) is class that implement slide animation between view controllers.
9 |
10 | ## Installation
11 |
12 | ### With source code
13 |
14 | - [Download repository](https://github.com/Friend-LGA/LGViewControllers/archive/master.zip), then add [LGViewControllers directory](https://github.com/Friend-LGA/LGViewControllers/blob/master/LGViewControllers/) to your project.
15 | - Also you need to install libraries:
16 | - [LGPlaceholderView](https://github.com/Friend-LGA/LGPlaceholderView)
17 | - [LGRefreshView](https://github.com/Friend-LGA/LGRefreshView)
18 |
19 | ### With CocoaPods
20 |
21 | [CocoaPods](http://cocoapods.org/) is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries in your projects. See the "Get Started" section for more details.
22 |
23 | #### Podfile
24 | ```
25 | platform :ios, '6.0'
26 | pod 'LGViewControllers', '~> 1.0.0'
27 | ```
28 |
29 | ## Usage
30 |
31 | In the source files where you need to use the library, import the header file:
32 |
33 | ```objective-c
34 | #import "LGViewControllers.h"
35 | ```
36 |
37 | Or you can use sublibraries separately, depend of your needs:
38 |
39 | ```objective-c
40 | #import "LGScrollViewController.h"
41 | #import "LGTableViewController.h"
42 | #import "LGCollectionViewController.h"
43 | #import "LGWebViewController.h"
44 |
45 | #import "LGScrollView.h"
46 | #import "LGTableView.h"
47 | #import "LGCollectionView.h"
48 | #import "LGWebView.h"
49 |
50 | #import "LGViewControllerAnimator.h"
51 | ```
52 |
53 | ### More
54 |
55 | For more details try Xcode [Demo project](https://github.com/Friend-LGA/LGViewControllers/blob/master/Demo) and see files:
56 | - [LGScrollViewController.h](https://github.com/Friend-LGA/LGViewControllers/blob/master/LGViewControllers/LGScrollViewController/LGScrollViewController.h) and [LGScrollView.h](https://github.com/Friend-LGA/LGViewControllers/blob/master/LGViewControllers/LGScrollViewController/LGScrollView.h)
57 | - [LGTableViewController.h](https://github.com/Friend-LGA/LGViewControllers/blob/master/LGViewControllers/LGTableViewController/LGTableViewController.h) and [LGTableView.h](https://github.com/Friend-LGA/LGViewControllers/blob/master/LGViewControllers/LGTableViewController/LGTableView.h)
58 | - [LGCollectionViewController.h](https://github.com/Friend-LGA/LGViewControllers/blob/master/LGViewControllers/LGCollectionViewController/LGCollectionViewController.h) and [LGCollectionView.h](https://github.com/Friend-LGA/LGViewControllers/blob/master/LGViewControllers/LGCollectionViewController/LGCollectionView.h)
59 | - [LGWebViewController.h](https://github.com/Friend-LGA/LGViewControllers/blob/master/LGViewControllers/LGWebViewController/LGWebViewController.h) and [LGWebView.h](https://github.com/Friend-LGA/LGViewControllers/blob/master/LGViewControllers/LGWebViewController/LGWebView.h)
60 | - [LGViewControllerAnimator.h](https://github.com/Friend-LGA/LGViewControllers/blob/master/LGViewControllers/LGViewControllerAnimator/LGViewControllerAnimator.h)
61 |
62 | ## License
63 |
64 | LGViewControllers is released under the MIT license. See [LICENSE](https://raw.githubusercontent.com/Friend-LGA/LGViewControllers/master/LICENSE) for details.
65 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
28 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/LGViewControllers/LGScrollViewController/LGScrollView.m:
--------------------------------------------------------------------------------
1 | //
2 | // LGScrollView.m
3 | // LGViewControllers
4 | //
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Copyright (c) 2015 Grigory Lutkov
9 | // (https://github.com/Friend-LGA/LGViewControllers)
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 | //
29 |
30 | #import "LGScrollView.h"
31 |
32 | @interface LGScrollView ()
33 |
34 | @property (strong, nonatomic) UIView *topSeparatorView;
35 |
36 | @end
37 |
38 | @implementation LGScrollView
39 |
40 | - (instancetype)init
41 | {
42 | self = [super init];
43 | if (self)
44 | {
45 | [self initializeWithPlaceholderViewEnabled:NO refreshHandler:nil];
46 | }
47 | return self;
48 | }
49 |
50 | - (instancetype)initWithFrame:(CGRect)frame
51 | {
52 | self = [super initWithFrame:frame];
53 | if (self)
54 | {
55 | [self initializeWithPlaceholderViewEnabled:NO refreshHandler:nil];
56 | }
57 | return self;
58 | }
59 |
60 | - (instancetype)initWithPlaceholderViewEnabled:(BOOL)placeholderViewEnabled refreshHandler:(void(^)())refreshHandler
61 | {
62 | self = [super init];
63 | if (self)
64 | {
65 | [self initializeWithPlaceholderViewEnabled:placeholderViewEnabled refreshHandler:refreshHandler];
66 | }
67 | return self;
68 | }
69 |
70 | - (void)initializeWithPlaceholderViewEnabled:(BOOL)placeholderViewEnabled refreshHandler:(void(^)())refreshHandler
71 | {
72 | self.backgroundColor = [UIColor clearColor];
73 |
74 | self.placeholderViewEnabled = placeholderViewEnabled;
75 |
76 | if (refreshHandler)
77 | [self setRefreshViewEnabledWithHandler:refreshHandler];
78 | }
79 |
80 | #pragma mark - Dealloc
81 |
82 | - (void)dealloc
83 | {
84 | #if DEBUG
85 | NSLog(@"%s [Line %d]", __PRETTY_FUNCTION__, __LINE__);
86 | #endif
87 | }
88 |
89 | #pragma mark -
90 |
91 | - (void)setRefreshViewEnabledWithHandler:(void(^)())refreshHandler
92 | {
93 | if (!_refreshViewEnabled && !_refreshView)
94 | {
95 | _refreshViewEnabled = YES;
96 |
97 | _refreshView = [LGRefreshView refreshViewWithScrollView:self
98 | refreshHandler:refreshHandler];
99 | }
100 | }
101 |
102 | - (void)setRefreshViewDisabled
103 | {
104 | if (_refreshViewEnabled && _refreshView)
105 | {
106 | _refreshViewEnabled = NO;
107 |
108 | if (_refreshView.superview)
109 | [_refreshView removeFromSuperview];
110 |
111 | _refreshView = nil;
112 | }
113 | }
114 |
115 | - (void)setPlaceholderViewEnabled:(BOOL)placeholderViewEnabled
116 | {
117 | if (_placeholderViewEnabled != placeholderViewEnabled)
118 | {
119 | _placeholderViewEnabled = placeholderViewEnabled;
120 |
121 | if (_placeholderViewEnabled && !_placeholderView)
122 | _placeholderView = [LGPlaceholderView placeholderViewWithView:self];
123 | else if (!_placeholderViewEnabled && _placeholderView)
124 | {
125 | if (_placeholderView.superview)
126 | [_placeholderView removeFromSuperview];
127 |
128 | _placeholderView = nil;
129 | }
130 | }
131 | }
132 |
133 | #pragma mark -
134 |
135 | - (void)addTopSeparatorViewWithColor:(UIColor *)color thinckness:(CGFloat)thinckness edgeInsets:(UIEdgeInsets)edgeInsets
136 | {
137 | if (_topSeparatorView)
138 | {
139 | [_topSeparatorView removeFromSuperview];
140 | _topSeparatorView = nil;
141 | }
142 |
143 | _topSeparatorView = [UIView new];
144 | _topSeparatorView.backgroundColor = color;
145 | _topSeparatorView.frame = CGRectMake(edgeInsets.left, -thinckness, self.frame.size.width-edgeInsets.left-edgeInsets.right, thinckness);
146 | [self addSubview:_topSeparatorView];
147 | }
148 |
149 | @end
150 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/DemoTableViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // DemoTableViewController.m
3 | // LGViewControllersDemo
4 | //
5 | // Created by Grigory Lutkov on 26.03.15.
6 | // Copyright (c) 2015 Grigory Lutkov. All rights reserved.
7 | //
8 |
9 | #import "DemoTableViewController.h"
10 |
11 | @interface DemoTableViewCell : UITableViewCell
12 |
13 | @end
14 |
15 | @implementation DemoTableViewCell
16 |
17 | - (id)initWithFrame:(CGRect)frame
18 | {
19 | self = [super initWithFrame:frame];
20 | if (self)
21 | {
22 | self.backgroundColor = [UIColor whiteColor];
23 |
24 | self.selectionStyle = UITableViewCellSelectionStyleNone;
25 | }
26 | return self;
27 | }
28 |
29 | - (void)layoutSubviews
30 | {
31 | self.textLabel.font = [UIFont systemFontOfSize:16.0];
32 | self.textLabel.numberOfLines = 0;
33 |
34 | [super layoutSubviews];
35 | }
36 |
37 | - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
38 | {
39 | if (highlighted) self.backgroundColor = [UIColor colorWithRed:0.f green:0.5 blue:1.f alpha:1.f];
40 | else self.backgroundColor = [UIColor whiteColor];
41 | }
42 |
43 | @end
44 |
45 | #pragma mark -
46 |
47 | @interface DemoTableViewController ()
48 |
49 | @property (assign, nonatomic, getter=isInitialized) BOOL initialized;
50 |
51 | @property (strong, nonatomic) NSMutableArray *dataArray;
52 |
53 | @property (assign, nonatomic, getter=isLoadingData) BOOL loadingData;
54 |
55 | @end
56 |
57 | @implementation DemoTableViewController
58 |
59 | - (id)initWithTitle:(NSString *)title
60 | {
61 | self = [super initWithStyle:UITableViewStylePlain asyncCalculatingHeightForRows:YES placeholderViewEnabled:YES refreshViewEnabled:YES];
62 | if (self)
63 | {
64 | self.title = title;
65 |
66 | self.view.backgroundColor = [UIColor whiteColor];
67 |
68 | [self.tableView registerClass:[DemoTableViewCell class] forCellReuseIdentifier:@"cell"];
69 |
70 | [self.tableView.placeholderView showActivityIndicatorAnimated:NO completionHandler:nil];
71 |
72 | self.tableView.alwaysBounceVertical = YES;
73 |
74 | [self addItemsToDataArray];
75 | }
76 | return self;
77 | }
78 |
79 | #pragma mark - Dealloc
80 |
81 | - (void)dealloc
82 | {
83 | NSLog(@"%s [Line %d]", __PRETTY_FUNCTION__, __LINE__);
84 | }
85 |
86 | #pragma mark - Appearing
87 |
88 | - (void)viewDidAppear:(BOOL)animated
89 | {
90 | [super viewDidAppear:animated];
91 |
92 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^(void)
93 | {
94 | [self.tableView.placeholderView dismissAnimated:YES completionHandler:nil];
95 |
96 | _initialized = YES;
97 | });
98 | }
99 |
100 | #pragma mark - UITableView Data Source
101 |
102 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
103 | {
104 | return 1;
105 | }
106 |
107 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
108 | {
109 | return _dataArray.count;
110 | }
111 |
112 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
113 | {
114 | DemoTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
115 |
116 | cell.textLabel.text = _dataArray[indexPath.row];
117 |
118 | return cell;
119 | }
120 |
121 | #pragma mark - UITableView Delegate
122 |
123 | - (CGFloat)tableView:(LGTableView *)tableView heightForRowAtIndexPathAsync:(NSIndexPath *)indexPath
124 | {
125 | NSString *string = _dataArray[indexPath.row];
126 |
127 | CGSize size = [string sizeWithFont:[UIFont systemFontOfSize:16.0] constrainedToSize:CGSizeMake(tableView.frame.size.width, CGFLOAT_MAX)];
128 |
129 | return size.height+20.f;
130 | }
131 |
132 | - (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath
133 | {
134 | NSLog(@"Table view did highlight cell section: %i row: %i", (int)indexPath.section, (int)indexPath.row);
135 | }
136 |
137 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
138 | {
139 | NSLog(@"Table view did select cell section: %i row: %i", (int)indexPath.section, (int)indexPath.row);
140 | }
141 |
142 | #pragma mark - UIScrollView Delegate
143 |
144 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView
145 | {
146 | if (!self.isLoadingData && self.isInitialized &&
147 | scrollView.contentOffset.y + scrollView.contentInset.top + scrollView.frame.size.height >= scrollView.contentSize.height - 100.f)
148 | {
149 | _loadingData = YES;
150 |
151 | [self.tableView beginUpdates];
152 |
153 | [self addItemsToDataArray];
154 |
155 | NSMutableArray *array = [NSMutableArray new];
156 |
157 | NSUInteger count = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone ? 30 : 40);
158 |
159 | for (NSUInteger i=_dataArray.count-count; i<_dataArray.count; i++)
160 | [array addObject:[NSIndexPath indexPathForRow:i inSection:0]];
161 |
162 | [self.tableView insertRowsAtIndexPaths:array
163 | withRowAnimation:UITableViewRowAnimationAutomatic
164 | completionHandler:^(void)
165 | {
166 | [self.tableView endUpdates];
167 |
168 | _loadingData = NO;
169 | }];
170 | }
171 | }
172 |
173 | #pragma mark -
174 |
175 | - (void)refreshActions
176 | {
177 | [_dataArray removeAllObjects];
178 |
179 | [self addItemsToDataArray];
180 |
181 | [self.tableView reloadDataWithCompletionHandler:^(void)
182 | {
183 | [UIView transitionWithView:self.tableView duration:0.3 options:UIViewAnimationOptionTransitionCrossDissolve animations:nil completion:nil];
184 |
185 | [self.tableView.refreshView endRefreshing];
186 | }];
187 | }
188 |
189 | - (void)addItemsToDataArray
190 | {
191 | if (!_dataArray)
192 | _dataArray = [NSMutableArray new];
193 |
194 | NSUInteger count = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone ? 30 : 40);
195 |
196 | for (NSUInteger i=0; i
9 | // (https://github.com/Friend-LGA/LGViewControllers)
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 | //
29 |
30 | #import "LGWebViewController.h"
31 |
32 | @interface LGWebViewController ()
33 |
34 | @property (assign, nonatomic, getter=isInitialized) BOOL initialized;
35 |
36 | @property (assign, nonatomic) UIEdgeInsets contentInset;
37 |
38 | @end
39 |
40 | @implementation LGWebViewController
41 |
42 | - (instancetype)init
43 | {
44 | self = [super init];
45 | if (self)
46 | {
47 | [self initializeWithPlaceholderViewEnabled:NO];
48 | }
49 | return self;
50 | }
51 |
52 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
53 | {
54 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
55 | if (self)
56 | {
57 | [self initializeWithPlaceholderViewEnabled:NO];
58 | }
59 | return self;
60 | }
61 |
62 | - (instancetype)initWithPlaceholderViewEnabled:(BOOL)placeholderViewEnabled
63 | {
64 | self = [super init];
65 | if (self)
66 | {
67 | [self initializeWithPlaceholderViewEnabled:placeholderViewEnabled];
68 | }
69 | return self;
70 | }
71 |
72 | - (void)initializeWithPlaceholderViewEnabled:(BOOL)placeholderViewEnabled
73 | {
74 | if ([UIDevice currentDevice].systemVersion.floatValue < 7.0)
75 | self.wantsFullScreenLayout = YES;
76 | else
77 | {
78 | self.extendedLayoutIncludesOpaqueBars = YES;
79 | self.automaticallyAdjustsScrollViewInsets = NO;
80 | }
81 |
82 | _webView = [[LGWebView alloc] initWithPlaceholderViewEnabled:placeholderViewEnabled];
83 | _webView.delegate = self;
84 | [self.view addSubview:_webView];
85 | }
86 |
87 | #pragma mark -
88 |
89 | - (instancetype)initWithTitle:(NSString *)title url:(NSURL *)url
90 | {
91 | self = [super init];
92 | if (self)
93 | {
94 | [self initializeWithTitle:title url:url placeholderViewEnabled:NO];
95 | }
96 | return self;
97 | }
98 |
99 | - (instancetype)initWithTitle:(NSString *)title url:(NSURL *)url placeholderViewEnabled:(BOOL)placeholderViewEnabled
100 | {
101 | self = [super init];
102 | if (self)
103 | {
104 | [self initializeWithTitle:title url:url placeholderViewEnabled:placeholderViewEnabled];
105 | }
106 | return self;
107 | }
108 |
109 | - (void)initializeWithTitle:(NSString *)title url:(NSURL *)url placeholderViewEnabled:(BOOL)placeholderViewEnabled
110 | {
111 | if ([UIDevice currentDevice].systemVersion.floatValue < 7.0)
112 | self.wantsFullScreenLayout = YES;
113 | else
114 | {
115 | self.extendedLayoutIncludesOpaqueBars = YES;
116 | self.automaticallyAdjustsScrollViewInsets = NO;
117 | }
118 |
119 | self.title = title;
120 |
121 | if ([url isKindOfClass:[NSString class]]) url = [NSURL URLWithString:(NSString *)url];
122 |
123 | NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
124 |
125 | _webView = [[LGWebView alloc] initWithPlaceholderViewEnabled:placeholderViewEnabled];
126 | _webView.delegate = self;
127 | [_webView loadRequest:request];
128 | _webView.clipsToBounds = NO;
129 | [self.view addSubview:_webView];
130 |
131 | if (_webView.isPlaceholderViewEnabled)
132 | [_webView.placeholderView showActivityIndicatorAnimated:NO completionHandler:nil];
133 | }
134 |
135 | #pragma mark - Dealloc
136 |
137 | - (void)dealloc
138 | {
139 | #if DEBUG
140 | NSLog(@"%s [Line %d]", __PRETTY_FUNCTION__, __LINE__);
141 | #endif
142 | }
143 |
144 | #pragma mark - Appearing
145 |
146 | - (void)viewWillLayoutSubviews
147 | {
148 | [super viewWillLayoutSubviews];
149 |
150 | CGFloat topInset = 0.f;
151 | topInset += (self.navigationController.navigationBarHidden ? 0.f : MIN(self.navigationController.navigationBar.frame.size.width, self.navigationController.navigationBar.frame.size.height));
152 | topInset += ([UIApplication sharedApplication].statusBarHidden ? 0.f : MIN([UIApplication sharedApplication].statusBarFrame.size.width, [UIApplication sharedApplication].statusBarFrame.size.height));
153 |
154 | CGFloat bottomInset = 0.f;
155 | bottomInset += (self.navigationController.isToolbarHidden ? 0.f : MIN(self.navigationController.toolbar.frame.size.width, self.navigationController.toolbar.frame.size.height));
156 |
157 | CGFloat topShift = 0.f;
158 | if ([UIDevice currentDevice].systemVersion.floatValue < 7.0 &&
159 | !self.navigationController.isNavigationBarHidden &&
160 | self.navigationController.navigationBar.isOpaque)
161 | topShift = topInset;
162 |
163 | CGRect newFrame = CGRectMake(0.f, topInset, self.view.frame.size.width, self.view.frame.size.height-topInset-bottomInset);
164 |
165 | if (!CGSizeEqualToSize(_webView.frame.size, newFrame.size))
166 | _webView.frame = newFrame;
167 | }
168 |
169 | #pragma mark - UIWebView Delegate
170 |
171 | - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
172 | {
173 | [self loadingDidFinishWithError:error];
174 | }
175 |
176 | - (void)webViewDidFinishLoad:(UIWebView *)webView
177 | {
178 | [self loadingDidFinishWithError:nil];
179 | }
180 |
181 | - (void)loadingDidFinishWithError:(NSError *)error
182 | {
183 | if (_webView.isPlaceholderViewEnabled)
184 | {
185 | if (error)
186 | [_webView.placeholderView showText:error.localizedDescription animated:YES completionHandler:nil];
187 | else
188 | [_webView.placeholderView dismissAnimated:YES completionHandler:nil];
189 | }
190 | }
191 |
192 | - (BOOL)webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType
193 | {
194 | if (inType == UIWebViewNavigationTypeLinkClicked && !self.isOpenLinksInside)
195 | {
196 | [[UIApplication sharedApplication] openURL:[inRequest URL]];
197 |
198 | return NO;
199 | }
200 |
201 | return YES;
202 | }
203 |
204 | @end
205 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo/DemoCollectionViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // DemoCollectionViewController.m
3 | // LGViewControllersDemo
4 | //
5 | // Created by Grigory Lutkov on 26.03.15.
6 | // Copyright (c) 2015 Grigory Lutkov. All rights reserved.
7 | //
8 |
9 | #import "DemoCollectionViewController.h"
10 |
11 | @interface DemoCollectionViewCell : UICollectionViewCell
12 |
13 | @property (strong, nonatomic) UILabel *textLabel;
14 |
15 | @end
16 |
17 | @implementation DemoCollectionViewCell
18 |
19 | - (id)initWithFrame:(CGRect)frame
20 | {
21 | self = [super initWithFrame:frame];
22 | if (self)
23 | {
24 | self.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1.f];
25 |
26 | _textLabel = [UILabel new];
27 | _textLabel.backgroundColor = [UIColor clearColor];
28 | _textLabel.font = [UIFont systemFontOfSize:16.f];
29 | [self addSubview:_textLabel];
30 | }
31 | return self;
32 | }
33 |
34 | - (void)layoutSubviews
35 | {
36 | [super layoutSubviews];
37 |
38 | [_textLabel sizeToFit];
39 | _textLabel.center = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
40 | _textLabel.frame = CGRectIntegral(_textLabel.frame);
41 | }
42 |
43 | - (void)setHighlighted:(BOOL)highlighted
44 | {
45 | if (highlighted) self.backgroundColor = [UIColor colorWithRed:0.f green:0.5 blue:1.f alpha:1.f];
46 | else self.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1.f];
47 | }
48 |
49 | @end
50 |
51 | #pragma mark -
52 |
53 | @interface DemoCollectionViewController ()
54 |
55 | @property (assign, nonatomic, getter=isInitialized) BOOL initialized;
56 |
57 | @property (strong, nonatomic) NSMutableArray *dataArray;
58 |
59 | @property (assign, nonatomic, getter=isLoadingData) BOOL loadingData;
60 |
61 | @end
62 |
63 | @implementation DemoCollectionViewController
64 |
65 | - (id)initWithTitle:(NSString *)title
66 | {
67 | self = [super initWithPlaceholderViewEnabled:YES refreshViewEnabled:YES];
68 | if (self)
69 | {
70 | self.title = title;
71 |
72 | self.view.backgroundColor = [UIColor whiteColor];
73 |
74 | [self.collectionView registerClass:[DemoCollectionViewCell class] forCellWithReuseIdentifier:@"cell"];
75 |
76 | [self.collectionView.placeholderView showActivityIndicatorAnimated:NO completionHandler:nil];
77 |
78 | self.collectionView.alwaysBounceVertical = YES;
79 |
80 | [self addItemsToDataArray];
81 | }
82 | return self;
83 | }
84 |
85 | #pragma mark - Dealloc
86 |
87 | - (void)dealloc
88 | {
89 | NSLog(@"%s [Line %d]", __PRETTY_FUNCTION__, __LINE__);
90 | }
91 |
92 | #pragma mark - Appearing
93 |
94 | - (void)viewWillLayoutSubviews
95 | {
96 | [super viewWillLayoutSubviews];
97 |
98 | NSUInteger numberOfCellsInARow = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone ? 3 : 6);
99 | if (self.view.frame.size.width > self.view.frame.size.height) numberOfCellsInARow += 2;
100 |
101 | _loadingData = YES;
102 |
103 | [self.collectionView setViewWidth:self.view.frame.size.width
104 | cellAspect:1.f
105 | numberOfCellsInARow:numberOfCellsInARow
106 | cellInsets:2.f
107 | sectionInsets:UIEdgeInsetsMake(2.f, 2.f, 2.f, 2.f)
108 | headerReferenceSize:CGSizeZero
109 | footerReferenceSize:CGSizeZero
110 | scrollDirection:UICollectionViewScrollDirectionVertical];
111 |
112 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^(void)
113 | {
114 | _loadingData = NO;
115 | });
116 | }
117 |
118 | - (void)viewDidAppear:(BOOL)animated
119 | {
120 | [super viewDidAppear:animated];
121 |
122 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^(void)
123 | {
124 | [self.collectionView.placeholderView dismissAnimated:YES completionHandler:nil];
125 |
126 | _initialized = YES;
127 | });
128 | }
129 |
130 | #pragma mark - UICollectionView Data Source
131 |
132 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
133 | {
134 | return 1;
135 | }
136 |
137 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
138 | {
139 | return _dataArray.count;
140 | }
141 |
142 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
143 | {
144 | DemoCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
145 |
146 | cell.textLabel.text = _dataArray[indexPath.row];
147 |
148 | [cell setNeedsLayout];
149 |
150 | return cell;
151 | }
152 |
153 | #pragma mark - UICollectionView Delegate
154 |
155 | - (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath
156 | {
157 | NSLog(@"Collection view did highlight cell section: %i item: %i", (int)indexPath.section, (int)indexPath.row);
158 | }
159 |
160 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
161 | {
162 | NSLog(@"Collection view did select cell section: %i item: %i", (int)indexPath.section, (int)indexPath.row);
163 | }
164 |
165 | #pragma mark - UIScrollView Delegate
166 |
167 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView
168 | {
169 | if (!self.isLoadingData && self.isInitialized &&
170 | scrollView.contentOffset.y + scrollView.contentInset.top + scrollView.frame.size.height >= scrollView.contentSize.height - 100.f)
171 | {
172 | _loadingData = YES;
173 |
174 | [self.collectionView performBatchUpdates:^(void)
175 | {
176 | [self addItemsToDataArray];
177 |
178 | NSMutableArray *array = [NSMutableArray new];
179 |
180 | NSUInteger count = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone ? 30 : 70);
181 |
182 | for (NSUInteger i=_dataArray.count-count; i<_dataArray.count; i++)
183 | [array addObject:[NSIndexPath indexPathForItem:i inSection:0]];
184 |
185 | [self.collectionView insertItemsAtIndexPaths:array];
186 | }
187 | completion:^(BOOL finished)
188 | {
189 | _loadingData = NO;
190 | }];
191 | }
192 | }
193 |
194 | #pragma mark -
195 |
196 | - (void)refreshActions
197 | {
198 | [_dataArray removeAllObjects];
199 |
200 | [self addItemsToDataArray];
201 |
202 | [self.collectionView reloadData];
203 |
204 | [UIView transitionWithView:self.collectionView duration:0.3 options:UIViewAnimationOptionTransitionCrossDissolve animations:nil completion:nil];
205 |
206 | [self.collectionView.refreshView endRefreshing];
207 | }
208 |
209 | - (void)addItemsToDataArray
210 | {
211 | if (!_dataArray)
212 | _dataArray = [NSMutableArray new];
213 |
214 | NSUInteger count = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone ? 30 : 70);
215 |
216 | for (NSUInteger i=0; i
9 | // (https://github.com/Friend-LGA/LGViewControllers)
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 | //
29 |
30 | #import "LGCollectionView.h"
31 |
32 | @interface LGCollectionView ()
33 |
34 | @property (strong, nonatomic) UIView *topSeparatorView;
35 |
36 | @end
37 |
38 | @implementation LGCollectionView
39 |
40 | - (instancetype)init
41 | {
42 | self = [super initWithFrame:CGRectZero collectionViewLayout:[UICollectionViewFlowLayout new]];
43 | if (self)
44 | {
45 | [self initializeWithPlaceholderViewEnabled:NO refreshHandler:nil];
46 | }
47 | return self;
48 | }
49 |
50 | - (instancetype)initWithFrame:(CGRect)frame
51 | {
52 | self = [super initWithFrame:frame collectionViewLayout:[UICollectionViewFlowLayout new]];
53 | if (self)
54 | {
55 | [self initializeWithPlaceholderViewEnabled:NO refreshHandler:nil];
56 | }
57 | return self;
58 | }
59 |
60 | - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout
61 | {
62 | self = [super initWithFrame:frame collectionViewLayout:(layout ? layout : [UICollectionViewFlowLayout new])];
63 | if (self)
64 | {
65 | [self initializeWithPlaceholderViewEnabled:NO refreshHandler:nil];
66 | }
67 | return self;
68 | }
69 |
70 | - (instancetype)initWithPlaceholderViewEnabled:(BOOL)placeholderViewEnabled refreshHandler:(void(^)())refreshHandler
71 | {
72 | self = [super initWithFrame:CGRectZero collectionViewLayout:[UICollectionViewFlowLayout new]];
73 | if (self)
74 | {
75 | [self initializeWithPlaceholderViewEnabled:placeholderViewEnabled refreshHandler:refreshHandler];
76 | }
77 | return self;
78 | }
79 |
80 | - (void)initializeWithPlaceholderViewEnabled:(BOOL)placeholderViewEnabled refreshHandler:(void(^)())refreshHandler
81 | {
82 | self.backgroundColor = [UIColor clearColor];
83 |
84 | self.placeholderViewEnabled = placeholderViewEnabled;
85 |
86 | if (refreshHandler)
87 | [self setRefreshViewEnabledWithHandler:refreshHandler];
88 | }
89 |
90 | #pragma mark - Dealloc
91 |
92 | - (void)dealloc
93 | {
94 | #if DEBUG
95 | NSLog(@"%s [Line %d]", __PRETTY_FUNCTION__, __LINE__);
96 | #endif
97 | }
98 |
99 | #pragma mark -
100 |
101 | - (void)setFrame:(CGRect)frame
102 | {
103 | if (_topSeparatorView && CGSizeEqualToSize(self.frame.size, frame.size))
104 | {
105 | CGFloat widthDif = frame.size.width-self.frame.size.width;
106 |
107 | _topSeparatorView.frame = CGRectMake(_topSeparatorView.frame.origin.x, _topSeparatorView.frame.origin.y, _topSeparatorView.frame.size.width+widthDif, _topSeparatorView.frame.size.height);
108 | }
109 |
110 | [super setFrame:frame];
111 | }
112 |
113 | #pragma mark -
114 |
115 | - (void)setRefreshViewEnabledWithHandler:(void(^)())refreshHandler
116 | {
117 | if (!_refreshViewEnabled && !_refreshView)
118 | {
119 | _refreshViewEnabled = YES;
120 |
121 | _refreshView = [LGRefreshView refreshViewWithScrollView:self
122 | refreshHandler:refreshHandler];
123 | }
124 | }
125 |
126 | - (void)setRefreshViewDisabled
127 | {
128 | if (_refreshViewEnabled && _refreshView)
129 | {
130 | _refreshViewEnabled = NO;
131 |
132 | if (_refreshView.superview)
133 | [_refreshView removeFromSuperview];
134 |
135 | _refreshView = nil;
136 | }
137 | }
138 |
139 | - (void)setPlaceholderViewEnabled:(BOOL)placeholderViewEnabled
140 | {
141 | if (_placeholderViewEnabled != placeholderViewEnabled)
142 | {
143 | _placeholderViewEnabled = placeholderViewEnabled;
144 |
145 | if (_placeholderViewEnabled && !_placeholderView)
146 | _placeholderView = [LGPlaceholderView placeholderViewWithView:self];
147 | else if (!_placeholderViewEnabled && _placeholderView)
148 | {
149 | if (_placeholderView.superview)
150 | [_placeholderView removeFromSuperview];
151 |
152 | _placeholderView = nil;
153 | }
154 | }
155 | }
156 |
157 | #pragma mark -
158 |
159 | - (void)addTopSeparatorViewWithColor:(UIColor *)color thinckness:(CGFloat)thinckness edgeInsets:(UIEdgeInsets)edgeInsets
160 | {
161 | if (!_topSeparatorView)
162 | {
163 | _topSeparatorView = [UIView new];
164 | [self addSubview:_topSeparatorView];
165 | }
166 |
167 | _topSeparatorView.backgroundColor = color;
168 | _topSeparatorView.frame = CGRectMake(edgeInsets.left, -thinckness, self.frame.size.width-edgeInsets.left-edgeInsets.right, thinckness);
169 | }
170 |
171 | #pragma mark - UICollectionViewLayout
172 |
173 | - (void)setViewWidth:(CGFloat)viewWidth
174 | cellAspect:(CGFloat)cellAspect
175 | numberOfCellsInARow:(NSUInteger)numberOfCellsInARow
176 | cellInsets:(CGFloat)cellInsets
177 | sectionInsets:(UIEdgeInsets)sectionInsets
178 | headerReferenceSize:(CGSize)headerReferenceSize
179 | footerReferenceSize:(CGSize)footerReferenceSize
180 | scrollDirection:(UICollectionViewScrollDirection)scrollDirection
181 | {
182 | CGFloat cellWidth = (viewWidth-sectionInsets.left-sectionInsets.right-cellInsets*(numberOfCellsInARow-1))/numberOfCellsInARow;
183 | CGFloat cellHeight = cellWidth/cellAspect;
184 |
185 | [self setCellWidth:cellWidth
186 | cellHeight:cellHeight
187 | cellInsets:cellInsets
188 | sectionInsets:sectionInsets
189 | headerReferenceSize:headerReferenceSize
190 | footerReferenceSize:footerReferenceSize
191 | scrollDirection:scrollDirection];
192 | }
193 |
194 | - (void)setViewWidth:(CGFloat)viewWidth
195 | cellHeight:(CGFloat)cellHeight
196 | numberOfCellsInARow:(NSUInteger)numberOfCellsInARow
197 | cellInsets:(CGFloat)cellInsets
198 | sectionInsets:(UIEdgeInsets)sectionInsets
199 | headerReferenceSize:(CGSize)headerReferenceSize
200 | footerReferenceSize:(CGSize)footerReferenceSize
201 | scrollDirection:(UICollectionViewScrollDirection)scrollDirection
202 | {
203 | CGFloat cellWidth = (viewWidth-sectionInsets.left-sectionInsets.right-cellInsets*(numberOfCellsInARow-1))/numberOfCellsInARow;
204 |
205 | [self setCellWidth:cellWidth
206 | cellHeight:cellHeight
207 | cellInsets:cellInsets
208 | sectionInsets:sectionInsets
209 | headerReferenceSize:headerReferenceSize
210 | footerReferenceSize:footerReferenceSize
211 | scrollDirection:scrollDirection];
212 | }
213 |
214 | - (void)setCellWidth:(CGFloat)cellWidth
215 | cellHeight:(CGFloat)cellHeight
216 | cellInsets:(CGFloat)cellInsets
217 | sectionInsets:(UIEdgeInsets)sectionInsets
218 | headerReferenceSize:(CGSize)headerReferenceSize
219 | footerReferenceSize:(CGSize)footerReferenceSize
220 | scrollDirection:(UICollectionViewScrollDirection)scrollDirection
221 | {
222 | UICollectionViewFlowLayout *collectionViewLayout = [UICollectionViewFlowLayout new];
223 | collectionViewLayout.sectionInset = sectionInsets;
224 | collectionViewLayout.itemSize = CGSizeMake(cellWidth, cellHeight);
225 | collectionViewLayout.minimumLineSpacing = cellInsets; //*(sectionInsets.left || sectionInsets.right ? 1 : 2);
226 | collectionViewLayout.minimumInteritemSpacing = 0;
227 | collectionViewLayout.scrollDirection = scrollDirection;
228 | collectionViewLayout.headerReferenceSize = headerReferenceSize;
229 | collectionViewLayout.footerReferenceSize = footerReferenceSize;
230 |
231 | [self setCollectionViewLayout:collectionViewLayout animated:NO];
232 | }
233 |
234 | @end
235 |
--------------------------------------------------------------------------------
/LGViewControllers/LGScrollViewController/LGScrollViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // LGScrollViewController.m
3 | // LGViewControllers
4 | //
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Copyright (c) 2015 Grigory Lutkov
9 | // (https://github.com/Friend-LGA/LGViewControllers)
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 | //
29 |
30 | #import "LGScrollViewController.h"
31 |
32 | @interface LGScrollViewController ()
33 |
34 | @property (assign, nonatomic) CGFloat bottomContentInset;
35 | @property (assign, nonatomic) CGFloat bottomScrollIndicatorInsets;
36 |
37 | @end
38 |
39 | @implementation LGScrollViewController
40 |
41 | - (instancetype)init
42 | {
43 | self = [super init];
44 | if (self)
45 | {
46 | [self initializeWithPlaceholderViewEnabled:NO refreshViewEnabled:NO];
47 | }
48 | return self;
49 | }
50 |
51 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
52 | {
53 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
54 | if (self)
55 | {
56 | [self initializeWithPlaceholderViewEnabled:NO refreshViewEnabled:NO];
57 | }
58 | return self;
59 | }
60 |
61 | - (instancetype)initWithPlaceholderViewEnabled:(BOOL)placeholderViewEnabled refreshViewEnabled:(BOOL)refreshViewEnabled
62 | {
63 | self = [super init];
64 | if (self)
65 | {
66 | [self initializeWithPlaceholderViewEnabled:placeholderViewEnabled refreshViewEnabled:refreshViewEnabled];
67 | }
68 | return self;
69 | }
70 |
71 | - (void)initializeWithPlaceholderViewEnabled:(BOOL)placeholderViewEnabled refreshViewEnabled:(BOOL)refreshViewEnabled
72 | {
73 | if ([UIDevice currentDevice].systemVersion.floatValue < 7.0)
74 | self.wantsFullScreenLayout = YES;
75 | else
76 | {
77 | self.extendedLayoutIncludesOpaqueBars = YES;
78 | self.automaticallyAdjustsScrollViewInsets = NO;
79 | }
80 |
81 | if (refreshViewEnabled)
82 | {
83 | __weak typeof(self) wself = self;
84 |
85 | _scrollView = [[LGScrollView alloc] initWithPlaceholderViewEnabled:placeholderViewEnabled
86 | refreshHandler:^(void)
87 | {
88 | if (wself)
89 | {
90 | __strong typeof(wself) self = wself;
91 |
92 | [self refreshActions];
93 | }
94 | }];
95 | }
96 | else _scrollView = [[LGScrollView alloc] initWithPlaceholderViewEnabled:placeholderViewEnabled
97 | refreshHandler:nil];
98 | _scrollView.delegate = self;
99 | [self.view addSubview:_scrollView];
100 | }
101 |
102 | #pragma mark - Dealloc
103 |
104 | - (void)dealloc
105 | {
106 | #if DEBUG
107 | NSLog(@"%s [Line %d]", __PRETTY_FUNCTION__, __LINE__);
108 | #endif
109 |
110 | if (self.isKeyboardShowHideObserverEnabled)
111 | _keyboardShowHideObserverEnabled = NO;
112 | }
113 |
114 | #pragma mark - Appearing
115 |
116 | - (void)viewWillLayoutSubviews
117 | {
118 | [super viewWillLayoutSubviews];
119 |
120 | CGFloat topInset = 0.f;
121 | topInset += (self.navigationController.navigationBarHidden ? 0.f : MIN(self.navigationController.navigationBar.frame.size.width, self.navigationController.navigationBar.frame.size.height));
122 | topInset += ([UIApplication sharedApplication].statusBarHidden ? 0.f : MIN([UIApplication sharedApplication].statusBarFrame.size.width, [UIApplication sharedApplication].statusBarFrame.size.height));
123 |
124 | CGFloat bottomInset = 0.f;
125 | bottomInset += (self.navigationController.isToolbarHidden ? 0.f : MIN(self.navigationController.toolbar.frame.size.width, self.navigationController.toolbar.frame.size.height));
126 |
127 | CGFloat topShift = 0.f;
128 | if ([UIDevice currentDevice].systemVersion.floatValue < 7.0 &&
129 | !self.navigationController.isNavigationBarHidden &&
130 | self.navigationController.navigationBar.isOpaque)
131 | topShift = topInset;
132 |
133 | CGRect newFrame = CGRectMake(0.f, -topShift, self.view.frame.size.width, self.view.frame.size.height+topShift);
134 |
135 | if (!CGSizeEqualToSize(_scrollView.frame.size, newFrame.size))
136 | {
137 | _scrollView.frame = newFrame;
138 | _scrollView.contentInset = UIEdgeInsetsMake(topInset, 0.f, bottomInset, 0.f);
139 | _scrollView.scrollIndicatorInsets = UIEdgeInsetsMake(topInset, 0.f, bottomInset, 0.f);
140 | }
141 | }
142 |
143 | #pragma mark - Refresh
144 |
145 | - (void)refreshActions
146 | {
147 | //
148 | }
149 |
150 | #pragma mark - Keyboard notification
151 |
152 | - (void)setKeyboardShowHideObserverEnabled:(BOOL)keyboardShowHideObserverEnabled
153 | {
154 | if (_keyboardShowHideObserverEnabled != keyboardShowHideObserverEnabled)
155 | {
156 | _keyboardShowHideObserverEnabled = keyboardShowHideObserverEnabled;
157 |
158 | if (_keyboardShowHideObserverEnabled)
159 | {
160 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShowHideNotification:) name:UIKeyboardWillShowNotification object:nil];
161 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShowHideNotification:) name:UIKeyboardWillHideNotification object:nil];
162 | }
163 | else
164 | {
165 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
166 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
167 | }
168 | }
169 | }
170 |
171 | - (void)keyboardWillShowHideNotification:(NSNotification *)notification
172 | {
173 | [LGScrollViewController keyboardAnimateWithNotificationUserInfo:notification.userInfo
174 | animations:^(CGFloat keyboardHeight)
175 | {
176 | BOOL appear = (notification.name == UIKeyboardWillShowNotification);
177 |
178 | [self keyboardWillShowHideActionsAppear:appear keyboardHeight:keyboardHeight];
179 | }];
180 | }
181 |
182 | - (void)keyboardWillShowHideActionsAppear:(BOOL)appear keyboardHeight:(CGFloat)keyboardHeight
183 | {
184 | if (appear)
185 | {
186 | _bottomContentInset = _scrollView.contentInset.bottom;
187 | _bottomScrollIndicatorInsets = _scrollView.scrollIndicatorInsets.bottom;
188 | }
189 |
190 | CGFloat bottomContentInset = (appear ? keyboardHeight : _bottomContentInset);
191 | CGFloat bottomScrollIndicatorInsets = (appear ? keyboardHeight : _bottomScrollIndicatorInsets);
192 |
193 | UIEdgeInsets contentInset = _scrollView.contentInset;
194 | UIEdgeInsets scrollIndicatorInsets = _scrollView.scrollIndicatorInsets;
195 |
196 | contentInset.bottom = bottomContentInset;
197 | scrollIndicatorInsets.bottom = bottomScrollIndicatorInsets;
198 |
199 | _scrollView.contentInset = contentInset;
200 | _scrollView.scrollIndicatorInsets = scrollIndicatorInsets;
201 | }
202 |
203 | #pragma mark - Support
204 |
205 | + (void)keyboardAnimateWithNotificationUserInfo:(NSDictionary *)notificationUserInfo animations:(void(^)(CGFloat keyboardHeight))animations
206 | {
207 | CGFloat keyboardHeight = (notificationUserInfo[@"UIKeyboardBoundsUserInfoKey"] ? [notificationUserInfo[@"UIKeyboardBoundsUserInfoKey"] CGRectValue].size.height : 0.f);
208 | if (!keyboardHeight)
209 | keyboardHeight = (notificationUserInfo[UIKeyboardFrameBeginUserInfoKey] ? [notificationUserInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue].size.height : 0.f);
210 | if (!keyboardHeight)
211 | keyboardHeight = (notificationUserInfo[UIKeyboardFrameEndUserInfoKey] ? [notificationUserInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height : 0.f);
212 | if (!keyboardHeight)
213 | return;
214 |
215 | NSTimeInterval animationDuration = [notificationUserInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
216 | int animationCurve = [notificationUserInfo[UIKeyboardAnimationCurveUserInfoKey] intValue];
217 |
218 | [UIView beginAnimations:nil context:NULL];
219 | [UIView setAnimationDuration:animationDuration];
220 | [UIView setAnimationCurve:animationCurve];
221 |
222 | if (animations) animations(keyboardHeight);
223 |
224 | [UIView commitAnimations];
225 | }
226 |
227 | @end
228 |
--------------------------------------------------------------------------------
/LGViewControllers/LGCollectionViewController/LGCollectionViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // LGCollectionViewController.m
3 | // LGViewControllers
4 | //
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Copyright (c) 2015 Grigory Lutkov
9 | // (https://github.com/Friend-LGA/LGViewControllers)
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 | //
29 |
30 | #import "LGCollectionViewController.h"
31 |
32 | @interface LGCollectionViewController ()
33 |
34 | @property (assign, nonatomic) CGFloat bottomContentInset;
35 | @property (assign, nonatomic) CGFloat bottomScrollIndicatorInsets;
36 |
37 | @end
38 |
39 | @implementation LGCollectionViewController
40 |
41 | - (instancetype)init
42 | {
43 | self = [super init];
44 | if (self)
45 | {
46 | [self initializeWithPlaceholderViewEnabled:NO refreshViewEnabled:NO];
47 | }
48 | return self;
49 | }
50 |
51 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
52 | {
53 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
54 | if (self)
55 | {
56 | [self initializeWithPlaceholderViewEnabled:NO refreshViewEnabled:NO];
57 | }
58 | return self;
59 | }
60 |
61 | - (instancetype)initWithPlaceholderViewEnabled:(BOOL)placeholderViewEnabled refreshViewEnabled:(BOOL)refreshViewEnabled
62 | {
63 | self = [super init];
64 | if (self)
65 | {
66 | [self initializeWithPlaceholderViewEnabled:placeholderViewEnabled refreshViewEnabled:refreshViewEnabled];
67 | }
68 | return self;
69 | }
70 |
71 | - (void)initializeWithPlaceholderViewEnabled:(BOOL)placeholderViewEnabled refreshViewEnabled:(BOOL)refreshViewEnabled
72 | {
73 | if ([UIDevice currentDevice].systemVersion.floatValue < 7.0)
74 | self.wantsFullScreenLayout = YES;
75 | else
76 | {
77 | self.extendedLayoutIncludesOpaqueBars = YES;
78 | self.automaticallyAdjustsScrollViewInsets = NO;
79 | }
80 |
81 | if (refreshViewEnabled)
82 | {
83 | __weak typeof(self) wself = self;
84 |
85 | _collectionView = [[LGCollectionView alloc] initWithPlaceholderViewEnabled:placeholderViewEnabled
86 | refreshHandler:^(void)
87 | {
88 | if (wself)
89 | {
90 | __strong typeof(wself) self = wself;
91 |
92 | [self refreshActions];
93 | }
94 | }];
95 | }
96 | else _collectionView = [[LGCollectionView alloc] initWithPlaceholderViewEnabled:placeholderViewEnabled
97 | refreshHandler:nil];
98 | _collectionView.dataSource = self;
99 | _collectionView.delegate = self;
100 | [self.view addSubview:_collectionView];
101 | }
102 |
103 | #pragma mark - Dealloc
104 |
105 | - (void)dealloc
106 | {
107 | #if DEBUG
108 | NSLog(@"%s [Line %d]", __PRETTY_FUNCTION__, __LINE__);
109 | #endif
110 |
111 | if (self.isKeyboardShowHideObserverEnabled)
112 | _keyboardShowHideObserverEnabled = NO;
113 | }
114 |
115 | #pragma mark - Appearing
116 |
117 | - (void)viewWillLayoutSubviews
118 | {
119 | CGFloat topInset = 0.f;
120 | topInset += (self.navigationController.navigationBarHidden ? 0.f : MIN(self.navigationController.navigationBar.frame.size.width, self.navigationController.navigationBar.frame.size.height));
121 | topInset += ([UIApplication sharedApplication].statusBarHidden ? 0.f : MIN([UIApplication sharedApplication].statusBarFrame.size.width, [UIApplication sharedApplication].statusBarFrame.size.height));
122 |
123 | CGFloat bottomInset = 0.f;
124 | bottomInset += (self.navigationController.isToolbarHidden ? 0.f : MIN(self.navigationController.toolbar.frame.size.width, self.navigationController.toolbar.frame.size.height));
125 |
126 | CGFloat topShift = 0.f;
127 | if ([UIDevice currentDevice].systemVersion.floatValue < 7.0 &&
128 | !self.navigationController.isNavigationBarHidden &&
129 | self.navigationController.navigationBar.isOpaque)
130 | topShift = topInset;
131 |
132 | CGRect newFrame = CGRectMake(0.f, -topShift, self.view.frame.size.width, self.view.frame.size.height+topShift);
133 |
134 | if (!CGSizeEqualToSize(_collectionView.frame.size, newFrame.size))
135 | {
136 | _collectionView.frame = newFrame;
137 | _collectionView.contentInset = UIEdgeInsetsMake(topInset, 0.f, bottomInset, 0.f);
138 | _collectionView.scrollIndicatorInsets = UIEdgeInsetsMake(topInset, 0.f, bottomInset, 0.f);
139 | }
140 | }
141 |
142 | #pragma mark - Refresh
143 |
144 | - (void)refreshActions
145 | {
146 | //
147 | }
148 |
149 | #pragma mark - Keyboard notification
150 |
151 | - (void)setKeyboardShowHideObserverEnabled:(BOOL)keyboardShowHideObserverEnabled
152 | {
153 | if (_keyboardShowHideObserverEnabled != keyboardShowHideObserverEnabled)
154 | {
155 | _keyboardShowHideObserverEnabled = keyboardShowHideObserverEnabled;
156 |
157 | if (_keyboardShowHideObserverEnabled)
158 | {
159 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShowHideNotification:) name:UIKeyboardWillShowNotification object:nil];
160 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShowHideNotification:) name:UIKeyboardWillHideNotification object:nil];
161 | }
162 | else
163 | {
164 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
165 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
166 | }
167 | }
168 | }
169 |
170 | - (void)keyboardWillShowHideNotification:(NSNotification *)notification
171 | {
172 | [LGCollectionViewController keyboardAnimateWithNotificationUserInfo:notification.userInfo
173 | animations:^(CGFloat keyboardHeight)
174 | {
175 | BOOL appear = (notification.name == UIKeyboardWillShowNotification);
176 |
177 | [self keyboardWillShowHideActionsAppear:appear keyboardHeight:keyboardHeight];
178 | }];
179 | }
180 |
181 | - (void)keyboardWillShowHideActionsAppear:(BOOL)appear keyboardHeight:(CGFloat)keyboardHeight
182 | {
183 | if (appear)
184 | {
185 | _bottomContentInset = _collectionView.contentInset.bottom;
186 | _bottomScrollIndicatorInsets = _collectionView.scrollIndicatorInsets.bottom;
187 | }
188 |
189 | CGFloat bottomContentInset = (appear ? keyboardHeight : _bottomContentInset);
190 | CGFloat bottomScrollIndicatorInsets = (appear ? keyboardHeight : _bottomScrollIndicatorInsets);
191 |
192 | UIEdgeInsets contentInset = _collectionView.contentInset;
193 | UIEdgeInsets scrollIndicatorInsets = _collectionView.scrollIndicatorInsets;
194 |
195 | contentInset.bottom = bottomContentInset;
196 | scrollIndicatorInsets.bottom = bottomScrollIndicatorInsets;
197 |
198 | _collectionView.contentInset = contentInset;
199 | _collectionView.scrollIndicatorInsets = scrollIndicatorInsets;
200 | }
201 |
202 | #pragma mark - UICollectionView Data Source
203 |
204 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
205 | {
206 | return 0;
207 | }
208 |
209 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
210 | {
211 | return 0;
212 | }
213 |
214 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
215 | {
216 | return nil;
217 | }
218 |
219 | #pragma mark - Support
220 |
221 | + (void)keyboardAnimateWithNotificationUserInfo:(NSDictionary *)notificationUserInfo animations:(void(^)(CGFloat keyboardHeight))animations
222 | {
223 | CGFloat keyboardHeight = (notificationUserInfo[@"UIKeyboardBoundsUserInfoKey"] ? [notificationUserInfo[@"UIKeyboardBoundsUserInfoKey"] CGRectValue].size.height : 0.f);
224 | if (!keyboardHeight)
225 | keyboardHeight = (notificationUserInfo[UIKeyboardFrameBeginUserInfoKey] ? [notificationUserInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue].size.height : 0.f);
226 | if (!keyboardHeight)
227 | keyboardHeight = (notificationUserInfo[UIKeyboardFrameEndUserInfoKey] ? [notificationUserInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height : 0.f);
228 | if (!keyboardHeight)
229 | return;
230 |
231 | NSTimeInterval animationDuration = [notificationUserInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
232 | int animationCurve = [notificationUserInfo[UIKeyboardAnimationCurveUserInfoKey] intValue];
233 |
234 | [UIView beginAnimations:nil context:NULL];
235 | [UIView setAnimationDuration:animationDuration];
236 | [UIView setAnimationCurve:animationCurve];
237 |
238 | if (animations) animations(keyboardHeight);
239 |
240 | [UIView commitAnimations];
241 | }
242 |
243 | @end
244 |
--------------------------------------------------------------------------------
/LGViewControllers/LGTableViewController/LGTableViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // LGTableViewController.m
3 | // LGViewControllers
4 | //
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Copyright (c) 2015 Grigory Lutkov
9 | // (https://github.com/Friend-LGA/LGViewControllers)
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 | //
29 |
30 | #import "LGTableViewController.h"
31 |
32 | @interface LGTableViewController ()
33 |
34 | @property (assign, nonatomic, getter=isCalculating) BOOL calculating;
35 |
36 | @property (assign, nonatomic) CGFloat bottomContentInset;
37 | @property (assign, nonatomic) CGFloat bottomScrollIndicatorInsets;
38 |
39 | @end
40 |
41 | @implementation LGTableViewController
42 |
43 | - (instancetype)init
44 | {
45 | self = [super init];
46 | if (self)
47 | {
48 | [self initializeWithStyle:UITableViewStylePlain asyncCalculatingHeightForRows:NO placeholderViewEnabled:NO refreshViewEnabled:NO];
49 | }
50 | return self;
51 | }
52 |
53 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
54 | {
55 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
56 | if (self)
57 | {
58 | [self initializeWithStyle:UITableViewStylePlain asyncCalculatingHeightForRows:NO placeholderViewEnabled:NO refreshViewEnabled:NO];
59 | }
60 | return self;
61 | }
62 |
63 | - (instancetype)initWithStyle:(UITableViewStyle)style
64 | {
65 | self = [super init];
66 | if (self)
67 | {
68 | [self initializeWithStyle:style asyncCalculatingHeightForRows:NO placeholderViewEnabled:NO refreshViewEnabled:NO];
69 | }
70 | return self;
71 | }
72 |
73 | - (instancetype)initWithStyle:(UITableViewStyle)style asyncCalculatingHeightForRows:(BOOL)asyncCalculatingHeightForRows
74 | {
75 | self = [super init];
76 | if (self)
77 | {
78 | [self initializeWithStyle:style asyncCalculatingHeightForRows:asyncCalculatingHeightForRows placeholderViewEnabled:NO refreshViewEnabled:NO];
79 | }
80 | return self;
81 | }
82 |
83 | - (instancetype)initWithStyle:(UITableViewStyle)style asyncCalculatingHeightForRows:(BOOL)asyncCalculatingHeightForRows placeholderViewEnabled:(BOOL)placeholderViewEnabled refreshViewEnabled:(BOOL)refreshViewEnabled
84 | {
85 | self = [super init];
86 | if (self)
87 | {
88 | [self initializeWithStyle:style asyncCalculatingHeightForRows:asyncCalculatingHeightForRows placeholderViewEnabled:placeholderViewEnabled refreshViewEnabled:refreshViewEnabled];
89 | }
90 | return self;
91 | }
92 |
93 | - (void)initializeWithStyle:(UITableViewStyle)style asyncCalculatingHeightForRows:(BOOL)asyncCalculatingHeightForRows placeholderViewEnabled:(BOOL)placeholderViewEnabled refreshViewEnabled:(BOOL)refreshViewEnabled
94 | {
95 | if ([UIDevice currentDevice].systemVersion.floatValue < 7.0)
96 | self.wantsFullScreenLayout = YES;
97 | else
98 | {
99 | self.extendedLayoutIncludesOpaqueBars = YES;
100 | self.automaticallyAdjustsScrollViewInsets = NO;
101 | }
102 |
103 | if (refreshViewEnabled)
104 | {
105 | __weak typeof(self) wself = self;
106 |
107 | _tableView = [[LGTableView alloc] initWithStyle:style
108 | placeholderViewEnabled:placeholderViewEnabled
109 | refreshHandler:^(void)
110 | {
111 | if (wself)
112 | {
113 | __strong typeof(wself) self = wself;
114 |
115 | [self refreshActions];
116 | }
117 | }];
118 | }
119 | else _tableView = [[LGTableView alloc] initWithStyle:style
120 | placeholderViewEnabled:placeholderViewEnabled
121 | refreshHandler:nil];
122 | _tableView.dataSource = self;
123 | _tableView.delegate = self;
124 | if (asyncCalculatingHeightForRows)
125 | _tableView.delegateLG = self;
126 |
127 | [self.view addSubview:_tableView];
128 | }
129 |
130 | #pragma mark - Dealloc
131 |
132 | - (void)dealloc
133 | {
134 | #if DEBUG
135 | NSLog(@"%s [Line %d]", __PRETTY_FUNCTION__, __LINE__);
136 | #endif
137 |
138 | if (self.isKeyboardShowHideObserverEnabled)
139 | _keyboardShowHideObserverEnabled = NO;
140 | }
141 |
142 | #pragma mark - Appearing
143 |
144 | - (void)viewWillLayoutSubviews
145 | {
146 | [super viewWillLayoutSubviews];
147 |
148 | CGFloat topInset = 0.f;
149 | topInset += (self.navigationController.navigationBarHidden ? 0.f : MIN(self.navigationController.navigationBar.frame.size.width, self.navigationController.navigationBar.frame.size.height));
150 | topInset += ([UIApplication sharedApplication].statusBarHidden ? 0.f : MIN([UIApplication sharedApplication].statusBarFrame.size.width, [UIApplication sharedApplication].statusBarFrame.size.height));
151 |
152 | CGFloat bottomInset = 0.f;
153 | bottomInset += (self.navigationController.isToolbarHidden ? 0.f : MIN(self.navigationController.toolbar.frame.size.width, self.navigationController.toolbar.frame.size.height));
154 |
155 | CGFloat topShift = 0.f;
156 | if ([UIDevice currentDevice].systemVersion.floatValue < 7.0 &&
157 | !self.navigationController.isNavigationBarHidden &&
158 | self.navigationController.navigationBar.isOpaque)
159 | topShift = topInset;
160 |
161 | CGRect newFrame = CGRectMake(0.f, -topShift, self.view.frame.size.width, self.view.frame.size.height+topShift);
162 |
163 | if (!CGSizeEqualToSize(_tableView.frame.size, newFrame.size))
164 | {
165 | _tableView.frame = newFrame;
166 | _tableView.contentInset = UIEdgeInsetsMake(topInset, 0.f, bottomInset, 0.f);
167 | _tableView.scrollIndicatorInsets = UIEdgeInsetsMake(topInset, 0.f, bottomInset, 0.f);
168 | }
169 | }
170 |
171 | #pragma mark - Refresh
172 |
173 | - (void)refreshActions
174 | {
175 | //
176 | }
177 |
178 | #pragma mark - Keyboard notification
179 |
180 | - (void)setKeyboardShowHideObserverEnabled:(BOOL)keyboardShowHideObserverEnabled
181 | {
182 | if (_keyboardShowHideObserverEnabled != keyboardShowHideObserverEnabled)
183 | {
184 | _keyboardShowHideObserverEnabled = keyboardShowHideObserverEnabled;
185 |
186 | if (_keyboardShowHideObserverEnabled)
187 | {
188 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShowHideNotification:) name:UIKeyboardWillShowNotification object:nil];
189 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShowHideNotification:) name:UIKeyboardWillHideNotification object:nil];
190 | }
191 | else
192 | {
193 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
194 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
195 | }
196 | }
197 | }
198 |
199 | - (void)keyboardWillShowHideNotification:(NSNotification *)notification
200 | {
201 | [LGTableViewController keyboardAnimateWithNotificationUserInfo:notification.userInfo
202 | animations:^(CGFloat keyboardHeight)
203 | {
204 | BOOL appear = (notification.name == UIKeyboardWillShowNotification);
205 |
206 | [self keyboardWillShowHideActionsAppear:appear keyboardHeight:keyboardHeight];
207 | }];
208 | }
209 |
210 | - (void)keyboardWillShowHideActionsAppear:(BOOL)appear keyboardHeight:(CGFloat)keyboardHeight
211 | {
212 | if (appear)
213 | {
214 | _bottomContentInset = _tableView.contentInset.bottom;
215 | _bottomScrollIndicatorInsets = _tableView.scrollIndicatorInsets.bottom;
216 | }
217 |
218 | CGFloat bottomContentInset = (appear ? keyboardHeight : _bottomContentInset);
219 | CGFloat bottomScrollIndicatorInsets = (appear ? keyboardHeight : _bottomScrollIndicatorInsets);
220 |
221 | UIEdgeInsets contentInset = _tableView.contentInset;
222 | UIEdgeInsets scrollIndicatorInsets = _tableView.scrollIndicatorInsets;
223 |
224 | contentInset.bottom = bottomContentInset;
225 | scrollIndicatorInsets.bottom = bottomScrollIndicatorInsets;
226 |
227 | _tableView.contentInset = contentInset;
228 | _tableView.scrollIndicatorInsets = scrollIndicatorInsets;
229 | }
230 |
231 | #pragma mark - UITableView Data Source
232 |
233 | - (NSInteger)numberOfSectionsInTableView:(LGTableView *)tableView
234 | {
235 | return 0;
236 | }
237 |
238 | - (NSInteger)tableView:(LGTableView *)tableView numberOfRowsInSection:(NSInteger)section
239 | {
240 | return 0;
241 | }
242 |
243 | - (UITableViewCell *)tableView:(LGTableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
244 | {
245 | return nil;
246 | }
247 |
248 | #pragma mark - UITableView Delegate
249 |
250 | - (CGFloat)tableView:(LGTableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
251 | {
252 | if (tableView.heightForRowsArray && tableView.heightForRowsArray.count > indexPath.section && [tableView.heightForRowsArray[indexPath.section] count] > indexPath.row)
253 | return [tableView.heightForRowsArray[indexPath.section][indexPath.row] floatValue];
254 | else
255 | return 0.f;
256 | }
257 |
258 | #pragma mark - LGTableView Delegate
259 |
260 | - (CGFloat)tableView:(LGTableView *)tableView heightForRowAtIndexPathAsync:(NSIndexPath *)indexPath
261 | {
262 | return 0.f;
263 | }
264 |
265 | #pragma mark - Support
266 |
267 | + (void)keyboardAnimateWithNotificationUserInfo:(NSDictionary *)notificationUserInfo animations:(void(^)(CGFloat keyboardHeight))animations
268 | {
269 | CGFloat keyboardHeight = (notificationUserInfo[@"UIKeyboardBoundsUserInfoKey"] ? [notificationUserInfo[@"UIKeyboardBoundsUserInfoKey"] CGRectValue].size.height : 0.f);
270 | if (!keyboardHeight)
271 | keyboardHeight = (notificationUserInfo[UIKeyboardFrameBeginUserInfoKey] ? [notificationUserInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue].size.height : 0.f);
272 | if (!keyboardHeight)
273 | keyboardHeight = (notificationUserInfo[UIKeyboardFrameEndUserInfoKey] ? [notificationUserInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height : 0.f);
274 | if (!keyboardHeight)
275 | return;
276 |
277 | NSTimeInterval animationDuration = [notificationUserInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
278 | int animationCurve = [notificationUserInfo[UIKeyboardAnimationCurveUserInfoKey] intValue];
279 |
280 | [UIView beginAnimations:nil context:NULL];
281 | [UIView setAnimationDuration:animationDuration];
282 | [UIView setAnimationCurve:animationCurve];
283 |
284 | if (animations) animations(keyboardHeight);
285 |
286 | [UIView commitAnimations];
287 | }
288 |
289 | @end
290 |
--------------------------------------------------------------------------------
/Demo/LGViewControllersDemo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 4A3ABCAC1AC42EE4003889C0 /* NavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A3ABCA91AC42EE4003889C0 /* NavigationController.m */; };
11 | 4A3ABCAD1AC42EE4003889C0 /* TableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A3ABCAB1AC42EE4003889C0 /* TableViewController.m */; };
12 | 4A3ABCB11AC4302C003889C0 /* DemoScrollViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A3ABCB01AC4302C003889C0 /* DemoScrollViewController.m */; };
13 | 4A3ABCB41AC4303F003889C0 /* DemoTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A3ABCB31AC4303F003889C0 /* DemoTableViewController.m */; };
14 | 4A3ABCB71AC43053003889C0 /* DemoCollectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A3ABCB61AC43053003889C0 /* DemoCollectionViewController.m */; };
15 | 4A836B6F1BF4F59F008374ED /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4A836B6E1BF4F59F008374ED /* LaunchScreen.storyboard */; };
16 | 4AD365021AAF697400EE6F1A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AD365011AAF697400EE6F1A /* main.m */; };
17 | 4AD365051AAF697400EE6F1A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AD365041AAF697400EE6F1A /* AppDelegate.m */; };
18 | 4AD3650D1AAF697400EE6F1A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4AD3650C1AAF697400EE6F1A /* Images.xcassets */; };
19 | 7F51DFF3BB66312F12BC8BE8 /* libPods-LGViewControllersDemo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E0E8F7B42D50ED52044F660E /* libPods-LGViewControllersDemo.a */; };
20 | /* End PBXBuildFile section */
21 |
22 | /* Begin PBXFileReference section */
23 | 2B77219F3CFA36F3921E2476 /* Pods-LGViewControllersDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LGViewControllersDemo.release.xcconfig"; path = "Pods/Target Support Files/Pods-LGViewControllersDemo/Pods-LGViewControllersDemo.release.xcconfig"; sourceTree = ""; };
24 | 4A3ABCA81AC42EE4003889C0 /* NavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NavigationController.h; sourceTree = ""; };
25 | 4A3ABCA91AC42EE4003889C0 /* NavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NavigationController.m; sourceTree = ""; };
26 | 4A3ABCAA1AC42EE4003889C0 /* TableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TableViewController.h; sourceTree = ""; };
27 | 4A3ABCAB1AC42EE4003889C0 /* TableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TableViewController.m; sourceTree = ""; };
28 | 4A3ABCAF1AC4302C003889C0 /* DemoScrollViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoScrollViewController.h; sourceTree = ""; };
29 | 4A3ABCB01AC4302C003889C0 /* DemoScrollViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoScrollViewController.m; sourceTree = ""; };
30 | 4A3ABCB21AC4303F003889C0 /* DemoTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoTableViewController.h; sourceTree = ""; };
31 | 4A3ABCB31AC4303F003889C0 /* DemoTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoTableViewController.m; sourceTree = ""; };
32 | 4A3ABCB51AC43053003889C0 /* DemoCollectionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoCollectionViewController.h; sourceTree = ""; };
33 | 4A3ABCB61AC43053003889C0 /* DemoCollectionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoCollectionViewController.m; sourceTree = ""; };
34 | 4A836B6E1BF4F59F008374ED /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; };
35 | 4AD364FC1AAF697400EE6F1A /* LGViewControllersDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LGViewControllersDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
36 | 4AD365001AAF697400EE6F1A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
37 | 4AD365011AAF697400EE6F1A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
38 | 4AD365031AAF697400EE6F1A /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
39 | 4AD365041AAF697400EE6F1A /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
40 | 4AD3650C1AAF697400EE6F1A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
41 | 7B887A530616A117C959BA8C /* Pods-LGViewControllersDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LGViewControllersDemo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-LGViewControllersDemo/Pods-LGViewControllersDemo.debug.xcconfig"; sourceTree = ""; };
42 | E0E8F7B42D50ED52044F660E /* libPods-LGViewControllersDemo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-LGViewControllersDemo.a"; sourceTree = BUILT_PRODUCTS_DIR; };
43 | /* End PBXFileReference section */
44 |
45 | /* Begin PBXFrameworksBuildPhase section */
46 | 4AD364F91AAF697400EE6F1A /* Frameworks */ = {
47 | isa = PBXFrameworksBuildPhase;
48 | buildActionMask = 2147483647;
49 | files = (
50 | 7F51DFF3BB66312F12BC8BE8 /* libPods-LGViewControllersDemo.a in Frameworks */,
51 | );
52 | runOnlyForDeploymentPostprocessing = 0;
53 | };
54 | /* End PBXFrameworksBuildPhase section */
55 |
56 | /* Begin PBXGroup section */
57 | 4A3ABCAE1AC42EE7003889C0 /* Demo View Controllers */ = {
58 | isa = PBXGroup;
59 | children = (
60 | 4A3ABCAF1AC4302C003889C0 /* DemoScrollViewController.h */,
61 | 4A3ABCB01AC4302C003889C0 /* DemoScrollViewController.m */,
62 | 4A3ABCB21AC4303F003889C0 /* DemoTableViewController.h */,
63 | 4A3ABCB31AC4303F003889C0 /* DemoTableViewController.m */,
64 | 4A3ABCB51AC43053003889C0 /* DemoCollectionViewController.h */,
65 | 4A3ABCB61AC43053003889C0 /* DemoCollectionViewController.m */,
66 | );
67 | name = "Demo View Controllers";
68 | sourceTree = "";
69 | };
70 | 4AD364F31AAF697400EE6F1A = {
71 | isa = PBXGroup;
72 | children = (
73 | 4AD364FE1AAF697400EE6F1A /* LGViewControllersDemo */,
74 | 4AD364FD1AAF697400EE6F1A /* Products */,
75 | E18FA7A6B41C918231772117 /* Pods */,
76 | 9312A34566155AFE9840D1FD /* Frameworks */,
77 | );
78 | sourceTree = "";
79 | };
80 | 4AD364FD1AAF697400EE6F1A /* Products */ = {
81 | isa = PBXGroup;
82 | children = (
83 | 4AD364FC1AAF697400EE6F1A /* LGViewControllersDemo.app */,
84 | );
85 | name = Products;
86 | sourceTree = "";
87 | };
88 | 4AD364FE1AAF697400EE6F1A /* LGViewControllersDemo */ = {
89 | isa = PBXGroup;
90 | children = (
91 | 4AD365031AAF697400EE6F1A /* AppDelegate.h */,
92 | 4AD365041AAF697400EE6F1A /* AppDelegate.m */,
93 | 4A3ABCA81AC42EE4003889C0 /* NavigationController.h */,
94 | 4A3ABCA91AC42EE4003889C0 /* NavigationController.m */,
95 | 4A3ABCAA1AC42EE4003889C0 /* TableViewController.h */,
96 | 4A3ABCAB1AC42EE4003889C0 /* TableViewController.m */,
97 | 4A3ABCAE1AC42EE7003889C0 /* Demo View Controllers */,
98 | 4AD3650C1AAF697400EE6F1A /* Images.xcassets */,
99 | 4AD364FF1AAF697400EE6F1A /* Supporting Files */,
100 | 4A836B6E1BF4F59F008374ED /* LaunchScreen.storyboard */,
101 | );
102 | path = LGViewControllersDemo;
103 | sourceTree = "";
104 | };
105 | 4AD364FF1AAF697400EE6F1A /* Supporting Files */ = {
106 | isa = PBXGroup;
107 | children = (
108 | 4AD365001AAF697400EE6F1A /* Info.plist */,
109 | 4AD365011AAF697400EE6F1A /* main.m */,
110 | );
111 | name = "Supporting Files";
112 | sourceTree = "";
113 | };
114 | 9312A34566155AFE9840D1FD /* Frameworks */ = {
115 | isa = PBXGroup;
116 | children = (
117 | E0E8F7B42D50ED52044F660E /* libPods-LGViewControllersDemo.a */,
118 | );
119 | name = Frameworks;
120 | sourceTree = "";
121 | };
122 | E18FA7A6B41C918231772117 /* Pods */ = {
123 | isa = PBXGroup;
124 | children = (
125 | 7B887A530616A117C959BA8C /* Pods-LGViewControllersDemo.debug.xcconfig */,
126 | 2B77219F3CFA36F3921E2476 /* Pods-LGViewControllersDemo.release.xcconfig */,
127 | );
128 | name = Pods;
129 | sourceTree = "";
130 | };
131 | /* End PBXGroup section */
132 |
133 | /* Begin PBXNativeTarget section */
134 | 4AD364FB1AAF697400EE6F1A /* LGViewControllersDemo */ = {
135 | isa = PBXNativeTarget;
136 | buildConfigurationList = 4AD3651F1AAF697400EE6F1A /* Build configuration list for PBXNativeTarget "LGViewControllersDemo" */;
137 | buildPhases = (
138 | AB00FCB2AB99F54B8415BB14 /* Check Pods Manifest.lock */,
139 | 4AD364F81AAF697400EE6F1A /* Sources */,
140 | 4AD364F91AAF697400EE6F1A /* Frameworks */,
141 | 4AD364FA1AAF697400EE6F1A /* Resources */,
142 | 3251F0FCE8BEE2089F55D4E4 /* Copy Pods Resources */,
143 | DB088874A69AA1CF41DD02A9 /* Embed Pods Frameworks */,
144 | );
145 | buildRules = (
146 | );
147 | dependencies = (
148 | );
149 | name = LGViewControllersDemo;
150 | productName = LGViewControllersDemo;
151 | productReference = 4AD364FC1AAF697400EE6F1A /* LGViewControllersDemo.app */;
152 | productType = "com.apple.product-type.application";
153 | };
154 | /* End PBXNativeTarget section */
155 |
156 | /* Begin PBXProject section */
157 | 4AD364F41AAF697400EE6F1A /* Project object */ = {
158 | isa = PBXProject;
159 | attributes = {
160 | LastUpgradeCheck = 0710;
161 | ORGANIZATIONNAME = "Grigory Lutkov";
162 | TargetAttributes = {
163 | 4AD364FB1AAF697400EE6F1A = {
164 | CreatedOnToolsVersion = 6.2;
165 | };
166 | };
167 | };
168 | buildConfigurationList = 4AD364F71AAF697400EE6F1A /* Build configuration list for PBXProject "LGViewControllersDemo" */;
169 | compatibilityVersion = "Xcode 3.2";
170 | developmentRegion = English;
171 | hasScannedForEncodings = 0;
172 | knownRegions = (
173 | en,
174 | Base,
175 | );
176 | mainGroup = 4AD364F31AAF697400EE6F1A;
177 | productRefGroup = 4AD364FD1AAF697400EE6F1A /* Products */;
178 | projectDirPath = "";
179 | projectRoot = "";
180 | targets = (
181 | 4AD364FB1AAF697400EE6F1A /* LGViewControllersDemo */,
182 | );
183 | };
184 | /* End PBXProject section */
185 |
186 | /* Begin PBXResourcesBuildPhase section */
187 | 4AD364FA1AAF697400EE6F1A /* Resources */ = {
188 | isa = PBXResourcesBuildPhase;
189 | buildActionMask = 2147483647;
190 | files = (
191 | 4A836B6F1BF4F59F008374ED /* LaunchScreen.storyboard in Resources */,
192 | 4AD3650D1AAF697400EE6F1A /* Images.xcassets in Resources */,
193 | );
194 | runOnlyForDeploymentPostprocessing = 0;
195 | };
196 | /* End PBXResourcesBuildPhase section */
197 |
198 | /* Begin PBXShellScriptBuildPhase section */
199 | 3251F0FCE8BEE2089F55D4E4 /* Copy Pods Resources */ = {
200 | isa = PBXShellScriptBuildPhase;
201 | buildActionMask = 2147483647;
202 | files = (
203 | );
204 | inputPaths = (
205 | );
206 | name = "Copy Pods Resources";
207 | outputPaths = (
208 | );
209 | runOnlyForDeploymentPostprocessing = 0;
210 | shellPath = /bin/sh;
211 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-LGViewControllersDemo/Pods-LGViewControllersDemo-resources.sh\"\n";
212 | showEnvVarsInLog = 0;
213 | };
214 | AB00FCB2AB99F54B8415BB14 /* Check Pods Manifest.lock */ = {
215 | isa = PBXShellScriptBuildPhase;
216 | buildActionMask = 2147483647;
217 | files = (
218 | );
219 | inputPaths = (
220 | );
221 | name = "Check Pods Manifest.lock";
222 | outputPaths = (
223 | );
224 | runOnlyForDeploymentPostprocessing = 0;
225 | shellPath = /bin/sh;
226 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
227 | showEnvVarsInLog = 0;
228 | };
229 | DB088874A69AA1CF41DD02A9 /* Embed Pods Frameworks */ = {
230 | isa = PBXShellScriptBuildPhase;
231 | buildActionMask = 2147483647;
232 | files = (
233 | );
234 | inputPaths = (
235 | );
236 | name = "Embed Pods Frameworks";
237 | outputPaths = (
238 | );
239 | runOnlyForDeploymentPostprocessing = 0;
240 | shellPath = /bin/sh;
241 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-LGViewControllersDemo/Pods-LGViewControllersDemo-frameworks.sh\"\n";
242 | showEnvVarsInLog = 0;
243 | };
244 | /* End PBXShellScriptBuildPhase section */
245 |
246 | /* Begin PBXSourcesBuildPhase section */
247 | 4AD364F81AAF697400EE6F1A /* Sources */ = {
248 | isa = PBXSourcesBuildPhase;
249 | buildActionMask = 2147483647;
250 | files = (
251 | 4A3ABCB41AC4303F003889C0 /* DemoTableViewController.m in Sources */,
252 | 4A3ABCAC1AC42EE4003889C0 /* NavigationController.m in Sources */,
253 | 4AD365051AAF697400EE6F1A /* AppDelegate.m in Sources */,
254 | 4AD365021AAF697400EE6F1A /* main.m in Sources */,
255 | 4A3ABCB71AC43053003889C0 /* DemoCollectionViewController.m in Sources */,
256 | 4A3ABCAD1AC42EE4003889C0 /* TableViewController.m in Sources */,
257 | 4A3ABCB11AC4302C003889C0 /* DemoScrollViewController.m in Sources */,
258 | );
259 | runOnlyForDeploymentPostprocessing = 0;
260 | };
261 | /* End PBXSourcesBuildPhase section */
262 |
263 | /* Begin XCBuildConfiguration section */
264 | 4AD3651D1AAF697400EE6F1A /* Debug */ = {
265 | isa = XCBuildConfiguration;
266 | buildSettings = {
267 | ALWAYS_SEARCH_USER_PATHS = NO;
268 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
269 | CLANG_CXX_LIBRARY = "libc++";
270 | CLANG_ENABLE_MODULES = YES;
271 | CLANG_ENABLE_OBJC_ARC = YES;
272 | CLANG_WARN_BOOL_CONVERSION = YES;
273 | CLANG_WARN_CONSTANT_CONVERSION = YES;
274 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
275 | CLANG_WARN_EMPTY_BODY = YES;
276 | CLANG_WARN_ENUM_CONVERSION = YES;
277 | CLANG_WARN_INT_CONVERSION = YES;
278 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
279 | CLANG_WARN_UNREACHABLE_CODE = YES;
280 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
281 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
282 | COPY_PHASE_STRIP = NO;
283 | ENABLE_STRICT_OBJC_MSGSEND = YES;
284 | ENABLE_TESTABILITY = YES;
285 | GCC_C_LANGUAGE_STANDARD = gnu99;
286 | GCC_DYNAMIC_NO_PIC = NO;
287 | GCC_OPTIMIZATION_LEVEL = 0;
288 | GCC_PREPROCESSOR_DEFINITIONS = (
289 | "DEBUG=1",
290 | "$(inherited)",
291 | );
292 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
293 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
294 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
295 | GCC_WARN_UNDECLARED_SELECTOR = YES;
296 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
297 | GCC_WARN_UNUSED_FUNCTION = YES;
298 | GCC_WARN_UNUSED_VARIABLE = YES;
299 | IPHONEOS_DEPLOYMENT_TARGET = 6.0;
300 | MTL_ENABLE_DEBUG_INFO = YES;
301 | ONLY_ACTIVE_ARCH = YES;
302 | SDKROOT = iphoneos;
303 | TARGETED_DEVICE_FAMILY = "1,2";
304 | };
305 | name = Debug;
306 | };
307 | 4AD3651E1AAF697400EE6F1A /* Release */ = {
308 | isa = XCBuildConfiguration;
309 | buildSettings = {
310 | ALWAYS_SEARCH_USER_PATHS = NO;
311 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
312 | CLANG_CXX_LIBRARY = "libc++";
313 | CLANG_ENABLE_MODULES = YES;
314 | CLANG_ENABLE_OBJC_ARC = YES;
315 | CLANG_WARN_BOOL_CONVERSION = YES;
316 | CLANG_WARN_CONSTANT_CONVERSION = YES;
317 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
318 | CLANG_WARN_EMPTY_BODY = YES;
319 | CLANG_WARN_ENUM_CONVERSION = YES;
320 | CLANG_WARN_INT_CONVERSION = YES;
321 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
322 | CLANG_WARN_UNREACHABLE_CODE = YES;
323 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
324 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
325 | COPY_PHASE_STRIP = NO;
326 | ENABLE_NS_ASSERTIONS = NO;
327 | ENABLE_STRICT_OBJC_MSGSEND = YES;
328 | GCC_C_LANGUAGE_STANDARD = gnu99;
329 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
330 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
331 | GCC_WARN_UNDECLARED_SELECTOR = YES;
332 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
333 | GCC_WARN_UNUSED_FUNCTION = YES;
334 | GCC_WARN_UNUSED_VARIABLE = YES;
335 | IPHONEOS_DEPLOYMENT_TARGET = 6.0;
336 | MTL_ENABLE_DEBUG_INFO = NO;
337 | SDKROOT = iphoneos;
338 | TARGETED_DEVICE_FAMILY = "1,2";
339 | VALIDATE_PRODUCT = YES;
340 | };
341 | name = Release;
342 | };
343 | 4AD365201AAF697400EE6F1A /* Debug */ = {
344 | isa = XCBuildConfiguration;
345 | baseConfigurationReference = 7B887A530616A117C959BA8C /* Pods-LGViewControllersDemo.debug.xcconfig */;
346 | buildSettings = {
347 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
348 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
349 | CODE_SIGN_IDENTITY = "iPhone Developer";
350 | INFOPLIST_FILE = LGViewControllersDemo/Info.plist;
351 | IPHONEOS_DEPLOYMENT_TARGET = 6.0;
352 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
353 | PRODUCT_BUNDLE_IDENTIFIER = "com.test.$(PRODUCT_NAME)";
354 | PRODUCT_NAME = "$(TARGET_NAME)";
355 | };
356 | name = Debug;
357 | };
358 | 4AD365211AAF697400EE6F1A /* Release */ = {
359 | isa = XCBuildConfiguration;
360 | baseConfigurationReference = 2B77219F3CFA36F3921E2476 /* Pods-LGViewControllersDemo.release.xcconfig */;
361 | buildSettings = {
362 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
363 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
364 | CODE_SIGN_IDENTITY = "iPhone Developer";
365 | INFOPLIST_FILE = LGViewControllersDemo/Info.plist;
366 | IPHONEOS_DEPLOYMENT_TARGET = 6.0;
367 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
368 | PRODUCT_BUNDLE_IDENTIFIER = "com.test.$(PRODUCT_NAME)";
369 | PRODUCT_NAME = "$(TARGET_NAME)";
370 | };
371 | name = Release;
372 | };
373 | /* End XCBuildConfiguration section */
374 |
375 | /* Begin XCConfigurationList section */
376 | 4AD364F71AAF697400EE6F1A /* Build configuration list for PBXProject "LGViewControllersDemo" */ = {
377 | isa = XCConfigurationList;
378 | buildConfigurations = (
379 | 4AD3651D1AAF697400EE6F1A /* Debug */,
380 | 4AD3651E1AAF697400EE6F1A /* Release */,
381 | );
382 | defaultConfigurationIsVisible = 0;
383 | defaultConfigurationName = Release;
384 | };
385 | 4AD3651F1AAF697400EE6F1A /* Build configuration list for PBXNativeTarget "LGViewControllersDemo" */ = {
386 | isa = XCConfigurationList;
387 | buildConfigurations = (
388 | 4AD365201AAF697400EE6F1A /* Debug */,
389 | 4AD365211AAF697400EE6F1A /* Release */,
390 | );
391 | defaultConfigurationIsVisible = 0;
392 | defaultConfigurationName = Release;
393 | };
394 | /* End XCConfigurationList section */
395 | };
396 | rootObject = 4AD364F41AAF697400EE6F1A /* Project object */;
397 | }
398 |
--------------------------------------------------------------------------------
/LGViewControllers/LGTableViewController/LGTableView.m:
--------------------------------------------------------------------------------
1 | //
2 | // LGTableView.m
3 | // LGViewControllers
4 | //
5 | //
6 | // The MIT License (MIT)
7 | //
8 | // Copyright (c) 2015 Grigory Lutkov
9 | // (https://github.com/Friend-LGA/LGViewControllers)
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 | //
29 |
30 | #import "LGTableView.h"
31 |
32 | @interface LGTableView ()
33 |
34 | @property (strong, nonatomic) NSMutableArray *heightForRowsArray;
35 |
36 | @property (strong, nonatomic) UIView *topSeparatorView;
37 |
38 | @end
39 |
40 | @implementation LGTableView
41 |
42 | - (instancetype)init
43 | {
44 | self = [super initWithFrame:CGRectZero style:UITableViewStylePlain];
45 | if (self)
46 | {
47 | [self initializeWithPlaceholderViewEnabled:NO refreshHandler:nil];
48 | }
49 | return self;
50 | }
51 |
52 | - (instancetype)initWithStyle:(UITableViewStyle)style
53 | {
54 | self = [super initWithFrame:CGRectZero style:style];
55 | if (self)
56 | {
57 | [self initializeWithPlaceholderViewEnabled:NO refreshHandler:nil];
58 | }
59 | return self;
60 | }
61 |
62 | - (instancetype)initWithFrame:(CGRect)frame
63 | {
64 | self = [super initWithFrame:frame style:UITableViewStylePlain];
65 | if (self)
66 | {
67 | [self initializeWithPlaceholderViewEnabled:NO refreshHandler:nil];
68 | }
69 | return self;
70 | }
71 |
72 | - (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style
73 | {
74 | self = [super initWithFrame:frame style:style];
75 | if (self)
76 | {
77 | [self initializeWithPlaceholderViewEnabled:NO refreshHandler:nil];
78 | }
79 | return self;
80 | }
81 |
82 | - (instancetype)initWithStyle:(UITableViewStyle)style placeholderViewEnabled:(BOOL)placeholderViewEnabled refreshHandler:(void(^)())refreshHandler
83 | {
84 | self = [super initWithFrame:CGRectZero style:style];
85 | if (self)
86 | {
87 | [self initializeWithPlaceholderViewEnabled:placeholderViewEnabled refreshHandler:refreshHandler];
88 | }
89 | return self;
90 | }
91 |
92 | - (void)initializeWithPlaceholderViewEnabled:(BOOL)placeholderViewEnabled refreshHandler:(void(^)())refreshHandler
93 | {
94 | self.backgroundColor = [UIColor clearColor];
95 |
96 | self.placeholderViewEnabled = placeholderViewEnabled;
97 |
98 | if (refreshHandler)
99 | [self setRefreshViewEnabledWithHandler:refreshHandler];
100 | }
101 |
102 | #pragma mark - Dealloc
103 |
104 | - (void)dealloc
105 | {
106 | #if DEBUG
107 | NSLog(@"%s [Line %d]", __PRETTY_FUNCTION__, __LINE__);
108 | #endif
109 |
110 | self.delegateLG = nil;
111 | }
112 |
113 | #pragma mark -
114 |
115 | - (void)setFrame:(CGRect)frame
116 | {
117 | if (_topSeparatorView && CGSizeEqualToSize(self.frame.size, frame.size))
118 | {
119 | CGFloat widthDif = frame.size.width-self.frame.size.width;
120 |
121 | _topSeparatorView.frame = CGRectMake(_topSeparatorView.frame.origin.x, _topSeparatorView.frame.origin.y, _topSeparatorView.frame.size.width+widthDif, _topSeparatorView.frame.size.height);
122 | }
123 |
124 | [super setFrame:frame];
125 | }
126 |
127 | #pragma mark -
128 |
129 | - (void)setDelegateLG:(id)delegateLG
130 | {
131 | _delegateLG = delegateLG;
132 |
133 | if (_delegateLG) _heightForRowsArray = [NSMutableArray new];
134 | else _heightForRowsArray = nil;
135 | }
136 |
137 | #pragma mark -
138 |
139 | - (void)setRefreshViewEnabledWithHandler:(void(^)())refreshHandler
140 | {
141 | if (!_refreshViewEnabled && !_refreshView)
142 | {
143 | _refreshViewEnabled = YES;
144 |
145 | _refreshView = [LGRefreshView refreshViewWithScrollView:self
146 | refreshHandler:refreshHandler];
147 | }
148 | }
149 |
150 | - (void)setRefreshViewDisabled
151 | {
152 | if (_refreshViewEnabled && _refreshView)
153 | {
154 | _refreshViewEnabled = NO;
155 |
156 | if (_refreshView.superview)
157 | [_refreshView removeFromSuperview];
158 |
159 | _refreshView = nil;
160 | }
161 | }
162 |
163 | - (void)setPlaceholderViewEnabled:(BOOL)placeholderViewEnabled
164 | {
165 | if (_placeholderViewEnabled != placeholderViewEnabled)
166 | {
167 | _placeholderViewEnabled = placeholderViewEnabled;
168 |
169 | if (_placeholderViewEnabled && !_placeholderView)
170 | _placeholderView = [LGPlaceholderView placeholderViewWithView:self];
171 | else if (!_placeholderViewEnabled && _placeholderView)
172 | {
173 | if (_placeholderView.superview)
174 | [_placeholderView removeFromSuperview];
175 |
176 | _placeholderView = nil;
177 | }
178 | }
179 | }
180 |
181 | #pragma mark -
182 |
183 | - (void)addTopSeparatorViewWithColor:(UIColor *)color thinckness:(CGFloat)thinckness edgeInsets:(UIEdgeInsets)edgeInsets
184 | {
185 | if (_topSeparatorView)
186 | {
187 | [_topSeparatorView removeFromSuperview];
188 | _topSeparatorView = nil;
189 | }
190 |
191 | _topSeparatorView = [UIView new];
192 | _topSeparatorView.backgroundColor = color;
193 | _topSeparatorView.frame = CGRectMake(edgeInsets.left, -thinckness, self.frame.size.width-edgeInsets.left-edgeInsets.right, thinckness);
194 | [self addSubview:_topSeparatorView];
195 | }
196 |
197 | #pragma mark -
198 |
199 | - (void)reloadData
200 | {
201 | [self reloadDataWithCompletionHandler:nil];
202 | }
203 |
204 | - (void)reloadDataWithCompletionHandler:(void(^)())completionHandler
205 | {
206 | if (_delegateLG && [_delegateLG respondsToSelector:@selector(tableView:heightForRowAtIndexPathAsync:)])
207 | {
208 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(void)
209 | {
210 | NSMutableArray *heightForRowsArray = [NSMutableArray new];
211 |
212 | for (NSUInteger section=0; section<[self.dataSource numberOfSectionsInTableView:self]; section++)
213 | {
214 | NSMutableArray *sectionArray = [NSMutableArray new];
215 |
216 | for (NSUInteger row=0; row<[self.dataSource tableView:self numberOfRowsInSection:section]; row++)
217 | {
218 | NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
219 |
220 | CGFloat height = [_delegateLG tableView:self heightForRowAtIndexPathAsync:indexPath];
221 |
222 | NSNumber *heightObject = [NSNumber numberWithFloat:height];
223 |
224 | [sectionArray addObject:heightObject];
225 | }
226 |
227 | [heightForRowsArray addObject:sectionArray];
228 | }
229 |
230 | dispatch_async(dispatch_get_main_queue(), ^(void)
231 | {
232 | _heightForRowsArray = heightForRowsArray;
233 |
234 | [super reloadData];
235 |
236 | if (completionHandler) completionHandler();
237 | });
238 | });
239 | }
240 | else
241 | {
242 | [super reloadData];
243 |
244 | if (completionHandler) completionHandler();
245 | }
246 | }
247 |
248 | - (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
249 | {
250 | [self reloadRowsAtIndexPaths:indexPaths withRowAnimation:animation completionHandler:nil];
251 | }
252 |
253 | - (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation completionHandler:(void(^)())completionHandler
254 | {
255 | if (_delegateLG && [_delegateLG respondsToSelector:@selector(tableView:heightForRowAtIndexPathAsync:)])
256 | {
257 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(void)
258 | {
259 | NSMutableArray *heightForRowsArray = _heightForRowsArray.mutableCopy;
260 |
261 | for (NSUInteger section=0; section<[self.dataSource numberOfSectionsInTableView:self]; section++)
262 | {
263 | NSMutableArray *sectionArray = heightForRowsArray[section];
264 |
265 | for (NSUInteger row=0; row<[self.dataSource tableView:self numberOfRowsInSection:section]; row++)
266 | {
267 | NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
268 |
269 | if ([indexPaths containsObject:indexPath])
270 | {
271 | CGFloat height = [_delegateLG tableView:self heightForRowAtIndexPathAsync:indexPath];
272 |
273 | NSNumber *heightObject = [NSNumber numberWithFloat:height];
274 |
275 | [sectionArray replaceObjectAtIndex:row withObject:heightObject];
276 | }
277 | }
278 |
279 | [heightForRowsArray replaceObjectAtIndex:section withObject:sectionArray];
280 | }
281 |
282 | dispatch_async(dispatch_get_main_queue(), ^(void)
283 | {
284 | _heightForRowsArray = heightForRowsArray;
285 |
286 | [super reloadRowsAtIndexPaths:indexPaths withRowAnimation:animation];
287 |
288 | if (completionHandler) completionHandler();
289 | });
290 | });
291 | }
292 | else
293 | {
294 | [super reloadRowsAtIndexPaths:indexPaths withRowAnimation:animation];
295 |
296 | if (completionHandler) completionHandler();
297 | }
298 | }
299 |
300 | - (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation
301 | {
302 | [self reloadSections:sections withRowAnimation:animation completionHandler:nil];
303 | }
304 |
305 | - (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation completionHandler:(void(^)())completionHandler
306 | {
307 | if (_delegateLG && [_delegateLG respondsToSelector:@selector(tableView:heightForRowAtIndexPathAsync:)])
308 | {
309 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(void)
310 | {
311 | NSMutableArray *heightForRowsArray = _heightForRowsArray.mutableCopy;
312 |
313 | for (NSUInteger section=0; section<[self.dataSource numberOfSectionsInTableView:self]; section++)
314 | if ([sections containsIndex:section])
315 | {
316 | NSMutableArray *sectionArray = heightForRowsArray[section];
317 |
318 | for (NSUInteger row=0; row<[self.dataSource tableView:self numberOfRowsInSection:section]; row++)
319 | {
320 | NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
321 |
322 | CGFloat height = [_delegateLG tableView:self heightForRowAtIndexPathAsync:indexPath];
323 |
324 | NSNumber *heightObject = [NSNumber numberWithFloat:height];
325 |
326 | [sectionArray replaceObjectAtIndex:row withObject:heightObject];
327 | }
328 |
329 | [heightForRowsArray replaceObjectAtIndex:section withObject:sectionArray];
330 | }
331 |
332 | dispatch_async(dispatch_get_main_queue(), ^(void)
333 | {
334 | _heightForRowsArray = heightForRowsArray;
335 |
336 | [super reloadSections:sections withRowAnimation:animation];
337 |
338 | if (completionHandler) completionHandler();
339 | });
340 | });
341 | }
342 | else
343 | {
344 | [super reloadSections:sections withRowAnimation:animation];
345 |
346 | if (completionHandler) completionHandler();
347 | }
348 | }
349 |
350 | #pragma mark -
351 |
352 | - (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
353 | {
354 | [self insertRowsAtIndexPaths:indexPaths withRowAnimation:animation completionHandler:nil];
355 | }
356 |
357 | - (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation completionHandler:(void(^)())completionHandler
358 | {
359 | if (_delegateLG && [_delegateLG respondsToSelector:@selector(tableView:heightForRowAtIndexPathAsync:)])
360 | {
361 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(void)
362 | {
363 | NSArray *heightForRowsArray = [self insertRowsAtIndexPaths:indexPaths inArray:_heightForRowsArray];
364 |
365 | dispatch_async(dispatch_get_main_queue(), ^(void)
366 | {
367 | _heightForRowsArray = heightForRowsArray.mutableCopy;
368 |
369 | [super insertRowsAtIndexPaths:indexPaths withRowAnimation:animation];
370 |
371 | if (completionHandler) completionHandler();
372 | });
373 | });
374 | }
375 | else
376 | {
377 | [super insertRowsAtIndexPaths:indexPaths withRowAnimation:animation];
378 |
379 | if (completionHandler) completionHandler();
380 | }
381 | }
382 |
383 | - (NSMutableArray *)insertRowsAtIndexPaths:(NSArray *)indexPaths inArray:(NSArray *)array
384 | {
385 | NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"section" ascending:YES];
386 | NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"row" ascending:YES];
387 |
388 | NSArray *indexPathsSorted = [indexPaths sortedArrayUsingDescriptors:@[sortDescriptor1, sortDescriptor2]];
389 |
390 | NSMutableArray *heightForRowsArray = array.mutableCopy;
391 |
392 | for (NSIndexPath *indexPath in indexPathsSorted)
393 | {
394 | CGFloat height = [_delegateLG tableView:self heightForRowAtIndexPathAsync:indexPath];
395 |
396 | NSNumber *heightObject = [NSNumber numberWithFloat:height];
397 |
398 | if (heightForRowsArray.count > indexPath.section)
399 | {
400 | NSMutableArray *sectionArray = heightForRowsArray[indexPath.section];
401 |
402 | if (sectionArray.count > indexPath.row)
403 | [sectionArray insertObject:heightObject atIndex:indexPath.row];
404 | else
405 | [sectionArray addObject:heightObject];
406 | }
407 | else
408 | {
409 | NSMutableArray *sectionArray = [NSMutableArray new];
410 |
411 | [sectionArray addObject:heightObject];
412 |
413 | [heightForRowsArray addObject:sectionArray];
414 | }
415 | }
416 |
417 | return heightForRowsArray;
418 | }
419 |
420 | - (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation
421 | {
422 | [self insertSections:sections withRowAnimation:animation completionHandler:nil];
423 | }
424 |
425 | - (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation completionHandler:(void(^)())completionHandler
426 | {
427 | if (_delegateLG && [_delegateLG respondsToSelector:@selector(tableView:heightForRowAtIndexPathAsync:)])
428 | {
429 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(void)
430 | {
431 | NSArray *heightForRowsArray = [self insertSections:sections inArray:_heightForRowsArray];
432 |
433 | dispatch_async(dispatch_get_main_queue(), ^(void)
434 | {
435 | _heightForRowsArray = heightForRowsArray.mutableCopy;
436 |
437 | [super insertSections:sections withRowAnimation:animation];
438 |
439 | if (completionHandler) completionHandler();
440 | });
441 | });
442 | }
443 | else
444 | {
445 | [super insertSections:sections withRowAnimation:animation];
446 |
447 | if (completionHandler) completionHandler();
448 | }
449 | }
450 |
451 | - (NSMutableArray *)insertSections:(NSIndexSet *)sections inArray:(NSArray *)array
452 | {
453 | NSMutableIndexSet *sectionsSorted = [NSMutableIndexSet new];
454 |
455 | for (NSUInteger i=0; i