├── Untitled.gif ├── RollingNotice ├── Assets.xcassets │ ├── Contents.json │ ├── tb_icon.imageset │ │ ├── tb_icon@2x.png │ │ └── Contents.json │ ├── tb_icon2.imageset │ │ ├── tb_icon2@2x.png │ │ └── Contents.json │ ├── tb_icon3.imageset │ │ ├── tb_icon3@2x.png │ │ └── Contents.json │ ├── tb_icon5.imageset │ │ ├── tb_icon5@2x.png │ │ └── Contents.json │ ├── tb_icon6.imageset │ │ ├── tb_icon6@2x.png │ │ └── Contents.json │ ├── tb_icon7.imageset │ │ ├── tb_icon7@2x.png │ │ └── Contents.json │ └── AppIcon.appiconset │ │ └── Contents.json ├── ViewController.h ├── SecondViewController.h ├── DemoCell2.h ├── AppDelegate.h ├── ThirdViewController.h ├── CustomNoticeCell.h ├── DemoCell3.h ├── main.m ├── DemoCodeAutoLayout.h ├── DemoCell3.m ├── GYRollingNoticeView │ ├── GYNoticeViewCell.h │ ├── GYRollingNoticeView.h │ ├── GYNoticeViewCell.m │ └── GYRollingNoticeView.m ├── DemoCell2.m ├── CustomNoticeCell.m ├── Info.plist ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── DemoCodeAutoLayout.m ├── AppDelegate.m ├── SecondViewController.m ├── ThirdViewController.m ├── SecondViewController.xib ├── DemoCell3.xib ├── ViewController.m └── CustomNoticeCell.xib ├── RollingNotice.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── qm.xcuserdatad │ │ └── UserInterfaceState.xcuserstate ├── xcuserdata │ └── qm.xcuserdatad │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── RollingNotice.xcscheme ├── xcshareddata │ └── xcschemes │ │ └── RollingNotice.xcscheme └── project.pbxproj ├── LICENSE ├── README_en.md ├── README.md └── RollingNotice.podspec /Untitled.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maltsugar/RollingNotice/HEAD/Untitled.gif -------------------------------------------------------------------------------- /RollingNotice/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /RollingNotice/Assets.xcassets/tb_icon.imageset/tb_icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maltsugar/RollingNotice/HEAD/RollingNotice/Assets.xcassets/tb_icon.imageset/tb_icon@2x.png -------------------------------------------------------------------------------- /RollingNotice/Assets.xcassets/tb_icon2.imageset/tb_icon2@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maltsugar/RollingNotice/HEAD/RollingNotice/Assets.xcassets/tb_icon2.imageset/tb_icon2@2x.png -------------------------------------------------------------------------------- /RollingNotice/Assets.xcassets/tb_icon3.imageset/tb_icon3@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maltsugar/RollingNotice/HEAD/RollingNotice/Assets.xcassets/tb_icon3.imageset/tb_icon3@2x.png -------------------------------------------------------------------------------- /RollingNotice/Assets.xcassets/tb_icon5.imageset/tb_icon5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maltsugar/RollingNotice/HEAD/RollingNotice/Assets.xcassets/tb_icon5.imageset/tb_icon5@2x.png -------------------------------------------------------------------------------- /RollingNotice/Assets.xcassets/tb_icon6.imageset/tb_icon6@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maltsugar/RollingNotice/HEAD/RollingNotice/Assets.xcassets/tb_icon6.imageset/tb_icon6@2x.png -------------------------------------------------------------------------------- /RollingNotice/Assets.xcassets/tb_icon7.imageset/tb_icon7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maltsugar/RollingNotice/HEAD/RollingNotice/Assets.xcassets/tb_icon7.imageset/tb_icon7@2x.png -------------------------------------------------------------------------------- /RollingNotice.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /RollingNotice.xcodeproj/project.xcworkspace/xcuserdata/qm.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maltsugar/RollingNotice/HEAD/RollingNotice.xcodeproj/project.xcworkspace/xcuserdata/qm.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /RollingNotice/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // RollingNotice 4 | // 5 | // Created by qm on 2017/12/4. 6 | // Copyright © 2017年 qm. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /RollingNotice/SecondViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SecondViewController.h 3 | // RollingNotice 4 | // 5 | // Created by qm on 2018/8/7. 6 | // Copyright © 2018年 qm. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SecondViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /RollingNotice/DemoCell2.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCell2.h 3 | // RollingNotice 4 | // 5 | // Created by qm on 2017/12/13. 6 | // Copyright © 2017年 qm. All rights reserved. 7 | // 8 | 9 | #import "GYNoticeViewCell.h" 10 | 11 | @interface DemoCell2 : GYNoticeViewCell 12 | 13 | @property (nonatomic, strong) UILabel *customLab; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /RollingNotice/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // RollingNotice 4 | // 5 | // Created by qm on 2017/12/4. 6 | // Copyright © 2017年 qm. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /RollingNotice/ThirdViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ThirdViewController.h 3 | // RollingNotice 4 | // 5 | // Created by zgy on 2020/4/15. 6 | // Copyright © 2020 qm. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ThirdViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /RollingNotice/CustomNoticeCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // CustomNoticeCell.h 3 | // RollingNotice 4 | // 5 | // Created by qm on 2017/12/8. 6 | // Copyright © 2017年 qm. All rights reserved. 7 | // 8 | 9 | #import "GYNoticeViewCell.h" 10 | 11 | @interface CustomNoticeCell : GYNoticeViewCell 12 | 13 | - (void)noticeCellWithArr:(NSArray *)arr forIndex:(NSUInteger)index; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /RollingNotice/DemoCell3.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCell3.h 3 | // RollingNotice 4 | // 5 | // Created by qm on 2017/12/13. 6 | // Copyright © 2017年 qm. All rights reserved. 7 | // 8 | 9 | #import "GYNoticeViewCell.h" 10 | 11 | @interface DemoCell3 : GYNoticeViewCell 12 | 13 | @property (weak, nonatomic) IBOutlet UILabel *lab0; 14 | @property (weak, nonatomic) IBOutlet UILabel *lab1; 15 | 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /RollingNotice/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // RollingNotice 4 | // 5 | // Created by qm on 2017/12/4. 6 | // Copyright © 2017年 qm. 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 | -------------------------------------------------------------------------------- /RollingNotice/DemoCodeAutoLayout.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCodeAutoLayout.h 3 | // RollingNotice 4 | // 5 | // Created by zgy on 2020/4/15. 6 | // Copyright © 2020 qm. All rights reserved. 7 | // 8 | 9 | #import "GYNoticeViewCell.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DemoCodeAutoLayout : GYNoticeViewCell 14 | 15 | 16 | 17 | @property (nonatomic, strong) UILabel *customLab; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /RollingNotice/Assets.xcassets/tb_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "tb_icon@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /RollingNotice/Assets.xcassets/tb_icon2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "tb_icon2@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /RollingNotice/Assets.xcassets/tb_icon3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "tb_icon3@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /RollingNotice/Assets.xcassets/tb_icon5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "tb_icon5@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /RollingNotice/Assets.xcassets/tb_icon6.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "tb_icon6@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /RollingNotice/Assets.xcassets/tb_icon7.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "tb_icon7@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /RollingNotice/DemoCell3.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCell3.m 3 | // RollingNotice 4 | // 5 | // Created by qm on 2017/12/13. 6 | // Copyright © 2017年 qm. All rights reserved. 7 | // 8 | 9 | #import "DemoCell3.h" 10 | 11 | @implementation DemoCell3 12 | 13 | /* 14 | // Only override drawRect: if you perform custom drawing. 15 | // An empty implementation adversely affects performance during animation. 16 | - (void)drawRect:(CGRect)rect { 17 | // Drawing code 18 | } 19 | */ 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /RollingNotice.xcodeproj/xcuserdata/qm.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | RollingNotice.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 91FFD8761FD52A36004A1A27 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /RollingNotice/GYRollingNoticeView/GYNoticeViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // GYNoticeViewCell.h 3 | // RollingNotice 4 | // 5 | // Created by qm on 2017/12/4. 6 | // Copyright © 2017年 qm. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | // 调试cell内存地址log 12 | static BOOL GYRollingDebugLog = NO; 13 | 14 | @interface GYNoticeViewCell : UIView 15 | 16 | @property (nonatomic, readonly, strong) UIView *contentView; 17 | @property (nonatomic, readonly, strong) UILabel *textLabel; 18 | @property (nonatomic, readonly, copy) NSString *reuseIdentifier; 19 | 20 | 21 | /// 普通用法label,左右间距, 必须>=0, 默认10 22 | @property (nonatomic, assign) CGFloat textLabelLeading; 23 | @property (nonatomic, assign) CGFloat textLabelTrailing; 24 | 25 | 26 | - (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier NS_DESIGNATED_INITIALIZER; 27 | - (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; 28 | @end 29 | -------------------------------------------------------------------------------- /RollingNotice/DemoCell2.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCell2.m 3 | // RollingNotice 4 | // 5 | // Created by qm on 2017/12/13. 6 | // Copyright © 2017年 qm. All rights reserved. 7 | // 8 | 9 | #import "DemoCell2.h" 10 | 11 | @interface DemoCell2 () 12 | 13 | @property (nonatomic, strong) UIButton *testBtn; 14 | 15 | 16 | 17 | @end 18 | 19 | @implementation DemoCell2 20 | 21 | - (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier 22 | { 23 | self = [super initWithReuseIdentifier:reuseIdentifier]; 24 | if (self) { 25 | [self setupUI]; 26 | } 27 | return self; 28 | } 29 | 30 | // cell 高度30 31 | - (void)setupUI 32 | { 33 | UIButton *testBtn = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; 34 | [self.contentView addSubview:testBtn]; 35 | testBtn.frame = CGRectMake(10, 5, 20, 20); 36 | 37 | _customLab = [[UILabel alloc]initWithFrame:CGRectMake(30+10, 5, 200, 20)]; 38 | _customLab.textColor = [UIColor redColor]; 39 | _customLab.backgroundColor = [UIColor lightGrayColor]; 40 | [self.contentView addSubview:_customLab]; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 maltsugar <173678978@qq.com> 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 | 23 | -------------------------------------------------------------------------------- /RollingNotice/CustomNoticeCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // CustomNoticeCell.m 3 | // RollingNotice 4 | // 5 | // Created by qm on 2017/12/8. 6 | // Copyright © 2017年 qm. All rights reserved. 7 | // 8 | 9 | #import "CustomNoticeCell.h" 10 | @interface CustomNoticeCell () 11 | 12 | @property (weak, nonatomic) IBOutlet UIImageView *trailIconImgView; 13 | 14 | @property (weak, nonatomic) IBOutlet UILabel *tagLab0; 15 | @property (weak, nonatomic) IBOutlet UILabel *titleLab0; 16 | 17 | @property (weak, nonatomic) IBOutlet UILabel *tagLab1; 18 | @property (weak, nonatomic) IBOutlet UILabel *titleLab1; 19 | 20 | 21 | @end 22 | @implementation CustomNoticeCell 23 | 24 | 25 | - (void)awakeFromNib 26 | { 27 | [super awakeFromNib]; 28 | 29 | _tagLab0.layer.borderColor = [UIColor orangeColor].CGColor; 30 | _tagLab0.layer.borderWidth = 0.5; 31 | _tagLab0.layer.cornerRadius = 3; 32 | 33 | _tagLab1.layer.borderColor = [UIColor orangeColor].CGColor; 34 | _tagLab1.layer.borderWidth = 0.5; 35 | _tagLab1.layer.cornerRadius = 3; 36 | } 37 | 38 | 39 | - (void)noticeCellWithArr:(NSArray *)arr forIndex:(NSUInteger)index 40 | { 41 | NSDictionary *dic = arr[index]; 42 | _trailIconImgView.image = [UIImage imageNamed:dic[@"img"]]; 43 | 44 | _tagLab0.text = [dic[@"arr"] firstObject][@"tag"]; 45 | _titleLab0.text = [dic[@"arr"] firstObject][@"title"]; 46 | 47 | _tagLab1.text = [dic[@"arr"] lastObject][@"tag"]; 48 | _titleLab1.text = [dic[@"arr"] lastObject][@"title"]; 49 | 50 | } 51 | 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /RollingNotice/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /README_en.md: -------------------------------------------------------------------------------- 1 | # Rolling Notice、Rolling Advertisement 2 | ![](https://img.shields.io/badge/platform-iOS-red.svg) ![](https://img.shields.io/badge/language-Objective--C-orange.svg) [![CocoaPods](http://img.shields.io/cocoapods/v/RollingNotice.svg?style=flat)](http://cocoapods.org/pods/RollingNotice) ![](https://img.shields.io/badge/license-MIT%20License-brightgreen.svg) 3 | 4 | ##### [Swift Version](https://github.com/maltsugar/RollingNotice-Swift) 5 | ### Introduce 6 | This library can scroll any view, scroll up and down the notice, advertising. It can be very flexible, similar to UITableViewCell. 7 | You only need to customize the view and assin value according to the index, roll will be done by it! 8 | 9 | 10 | ### Features 11 | - According to the UITableView design concept, developers only need to customize their own view (no matter how complicated it is) and assign value according to the index, roll will be done by it! 12 | - A simple use for one line label roll, its own cell will be OK. For complicated cell you can customize view. 13 | - All cells support reuse, same kind of cell will be allocted up to 2 14 | - Support dynamic refresh data source, multi type cell mix 15 | - Almost the same as UITableView usage 16 | 17 | Issues are welcome, hope you like it! 18 | ### Usage 19 | - manual: drag `GYRollingNoticeView` in your project 20 | - Cocoapods: `pod 'RollingNotice'` 21 | 22 | **customized cell must inherit `GYNoticeViewCell`.** 23 | 24 | For more details, see the demo project. Just similar as UITableView. 25 | 26 | 27 | ![](http://wx3.sinaimg.cn/mw690/72aba7efgy1fmdy022ow6g20bn08g0xn.gif) 28 | ### License 29 | GYRollingNoticeView is provided under the MIT license. See LICENSE file for details. 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /RollingNotice/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /RollingNotice/GYRollingNoticeView/GYRollingNoticeView.h: -------------------------------------------------------------------------------- 1 | // 2 | // GYRollingNoticeView.h 3 | // RollingNotice 4 | // 5 | // Created by qm on 2017/12/4. 6 | // Copyright © 2017年 qm. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "GYNoticeViewCell.h" 11 | 12 | @class GYRollingNoticeView; 13 | @protocol GYRollingNoticeViewDataSource 14 | @required 15 | - (NSInteger)numberOfRowsForRollingNoticeView:(GYRollingNoticeView *)rollingView; 16 | - (GYNoticeViewCell *)rollingNoticeView:(GYRollingNoticeView *)rollingView cellAtIndex:(NSUInteger)index; 17 | @end 18 | 19 | @protocol GYRollingNoticeViewDelegate 20 | @optional 21 | - (void)didClickRollingNoticeView:(GYRollingNoticeView *)rollingView forIndex:(NSUInteger)index; 22 | 23 | @end 24 | 25 | typedef NS_ENUM(NSUInteger, GYRollingNoticeViewStatus) { 26 | GYRollingNoticeViewStatusIdle, 27 | GYRollingNoticeViewStatusWorking, 28 | GYRollingNoticeViewStatusPause, 29 | }; 30 | 31 | @interface GYRollingNoticeView : UIView 32 | 33 | 34 | @property (nonatomic, weak) id dataSource; 35 | @property (nonatomic, weak) id delegate; 36 | @property (nonatomic, assign) NSTimeInterval stayInterval; // 停留时间 默认2秒 37 | @property (nonatomic, assign, readonly) int currentIndex; 38 | @property (nonatomic, assign, readonly) GYRollingNoticeViewStatus status; 39 | 40 | 41 | - (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier; 42 | - (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier; 43 | - (__kindof GYNoticeViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier; 44 | 45 | - (void)reloadDataAndStartRoll; 46 | - (void)stopRoll; // 如果想要释放,请在合适的地方停止timer。 If you want to release, please stop the timer in the right place,for example '-viewDidDismiss' 47 | 48 | - (void)pause; 49 | - (void)resume; 50 | 51 | 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /RollingNotice/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 滚动公告、广告 2 | ![](https://img.shields.io/badge/platform-iOS-red.svg) ![](https://img.shields.io/badge/language-Objective--C-orange.svg) [![CocoaPods](http://img.shields.io/cocoapods/v/RollingNotice.svg?style=flat)](http://cocoapods.org/pods/RollingNotice) ![](https://img.shields.io/badge/license-MIT%20License-brightgreen.svg) 3 | 4 | ##### [English](https://github.com/maltsugar/RollingNotice/blob/master/README_en.md) 5 | ##### [Swift 版本](https://github.com/maltsugar/RollingNotice-Swift) 6 | 7 | 8 | ### 版本记录 9 | 10 | - 1.1.1 修复[#16](https://github.com/maltsugar/RollingNotice/issues/16)、[#17](https://github.com/maltsugar/RollingNotice/issues/17),感谢[@xygkevin](https://github.com/xygkevin) 11 | - 1.1.0 新增暂停/恢复功能 12 | - 1.0.9 数据源返回数量为0时,不再显示cell 13 | - 1.0.8 普通用法textLabel支持左右间距设置 14 | - 1.0.6 delegate和dataSource使用weak修饰,更加安全合理,代理、数据源释放时属性自动置nil 15 | - 1.0.5 小更新,修改readme里一个单词拼写错误,去掉动画block里self强引用提示 16 | - 1.0.4 支持xib创建滚动视图[#9](https://github.com/maltsugar/RollingNotice/issues/9) 17 | - 1.0.3 修复极少数情况下,动画过程退到后台,可能出现残影的bug,感谢[@pcjbird](https://github.com/pcjbird)指出并帮忙修复 18 | 19 | 20 | ### 经历 21 | 前一段时间遇到了滚动公告的需求,搜了好多天,发现没有简单明了的库可用。大神们写的都太复杂了,star比较高的两个,一个不支持动态刷新标题,一个甚至写了循环scrollView的功能,功能太过强大,我认为比较庞大,就没有用了(我本人喜欢简洁一点的库)。后来找了一个简单的[WCScrollLabelView](https://github.com/Verchen/WCScrollLabelView),算是符合我的预期,然鹅我又给他改[两个bug](https://github.com/Verchen/WCScrollLabelView/issues/1),一个是timer不释放,一个是只有一个label时有问题。😅 22 | 23 | --- 24 | 于是就有了这个开源库,很曲折啊。闲暇时间写了一个,非常灵活。 25 | 26 | ### 特点: 27 | 28 | - UITableView设计理念, 开发者只需要自定义自己的view(想要多复杂的View都行) 并根据index赋值,轮播交给它。 29 | - 简单一行文字轮播用自带的cell, 复杂的自定义cell 30 | - cell 支持重用,目前一种cell最多创建2个 31 | - 支持动态刷新数据源,多种cell混用 32 | - 用法几乎和UITableView一样 33 | 34 | 35 | 希望大家共同进步,有问题欢迎issue 36 | ### 用法 37 | 几乎和UITableView一样的体验,自定义cell的话`必须`继承`GYNoticeViewCell`,你只管自定义你的View,并根据index赋值,轮播交给它。 38 | 具体用法demo 里有的! 39 | 40 | - 手动下载: `GYRollingNoticeView`拖进去 41 | - Cocoapods: `pod 'RollingNotice'` 42 | 43 | 44 | ![](http://wx3.sinaimg.cn/mw690/72aba7efgy1fmdy022ow6g20bn08g0xn.gif) 45 | 46 | ### 许可证 47 | 转载请注明出处,谢谢 48 | 49 | GYRollingNoticeView 使用 MIT 许可证,详情见 LICENSE 文件。 50 | 51 | 52 | -------------------------------------------------------------------------------- /RollingNotice/DemoCodeAutoLayout.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCodeAutoLayout.m 3 | // RollingNotice 4 | // 5 | // Created by zgy on 2020/4/15. 6 | // Copyright © 2020 qm. All rights reserved. 7 | // 8 | 9 | #import "DemoCodeAutoLayout.h" 10 | 11 | @implementation DemoCodeAutoLayout 12 | 13 | - (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier 14 | { 15 | self = [super initWithReuseIdentifier:reuseIdentifier]; 16 | if (self) { 17 | [self setupUI]; 18 | } 19 | return self; 20 | } 21 | 22 | // cell 高度30 23 | - (void)setupUI 24 | { 25 | UIButton *testBtn = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; 26 | [self.contentView addSubview:testBtn]; 27 | // testBtn.frame = CGRectMake(10, 5, 20, 20); 28 | testBtn.translatesAutoresizingMaskIntoConstraints = NO; 29 | [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[v]" options:0 metrics:nil views:@{@"v": testBtn}]]; 30 | [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[v]" options:0 metrics:nil views:@{@"v": testBtn}]]; 31 | 32 | [testBtn addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[v(30)]" options:0 metrics:nil views:@{@"v": testBtn}]]; 33 | [testBtn addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[v(60)]" options:0 metrics:nil views:@{@"v": testBtn}]]; 34 | 35 | 36 | 37 | _customLab = [[UILabel alloc]init]; 38 | _customLab.textColor = [UIColor redColor]; 39 | _customLab.backgroundColor = [UIColor lightGrayColor]; 40 | [self.contentView addSubview:_customLab]; 41 | 42 | _customLab.translatesAutoresizingMaskIntoConstraints = NO; 43 | [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[v]|" options:0 metrics:nil views:@{@"v": _customLab}]]; 44 | [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-80-[v]" options:0 metrics:nil views:@{@"v": _customLab}]]; 45 | [_customLab addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[v(160)]" options:0 metrics:nil views:@{@"v": _customLab}]]; 46 | 47 | 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /RollingNotice/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // RollingNotice 4 | // 5 | // Created by qm on 2017/12/4. 6 | // Copyright © 2017年 qm. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // 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. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // 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. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // 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. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /RollingNotice/GYRollingNoticeView/GYNoticeViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // GYNoticeViewCell.m 3 | // RollingNotice 4 | // 5 | // Created by qm on 2017/12/4. 6 | // Copyright © 2017年 qm. All rights reserved. 7 | // 8 | 9 | #import "GYNoticeViewCell.h" 10 | 11 | @implementation GYNoticeViewCell 12 | 13 | - (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier 14 | { 15 | self = [super initWithFrame:CGRectZero]; 16 | if (self) { 17 | if (GYRollingDebugLog) { 18 | NSLog(@"init a cell from code: %p", self); 19 | } 20 | _textLabelLeading = 10; 21 | _textLabelTrailing = 10; 22 | _reuseIdentifier = reuseIdentifier; 23 | [self setupInitialUI]; 24 | } 25 | return self; 26 | } 27 | 28 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 29 | { 30 | self = [super initWithCoder:aDecoder]; 31 | if (self) { 32 | 33 | if (GYRollingDebugLog) { 34 | NSLog(@"init a cell from xib"); 35 | } 36 | } 37 | return self; 38 | } 39 | - (instancetype)initWithFrame:(CGRect)frame 40 | { 41 | return [self initWithReuseIdentifier:@""]; 42 | } 43 | 44 | - (void)setupInitialUI 45 | { 46 | self.backgroundColor = [UIColor whiteColor]; 47 | _contentView = [[UIView alloc] init]; 48 | [self addSubview:_contentView]; 49 | 50 | _textLabel = [[UILabel alloc]init]; 51 | [_contentView addSubview:_textLabel]; 52 | } 53 | 54 | 55 | - (void)layoutSubviews 56 | { 57 | [super layoutSubviews]; 58 | 59 | _contentView.frame = self.bounds; 60 | 61 | if (nil != _textLabel) { 62 | CGFloat lead = _textLabelLeading; 63 | if (lead < 0) { 64 | NSLog(@"⚠️⚠️textLabelLeading must >= 0⚠️⚠️"); 65 | lead = 0; 66 | } 67 | CGFloat trai = _textLabelTrailing; 68 | if (trai < 0) { 69 | NSLog(@"⚠️⚠️textLabelTrailing must >= 0⚠️⚠️"); 70 | trai = 0; 71 | } 72 | CGFloat width = self.frame.size.width - lead - trai; 73 | if (width < 0) { 74 | NSLog(@"⚠️⚠️width must >= 0⚠️⚠️"); 75 | width = 0; 76 | } 77 | _textLabel.frame = CGRectMake(lead, 0, width, self.frame.size.height); 78 | } 79 | 80 | 81 | } 82 | 83 | - (void)dealloc 84 | { 85 | if (GYRollingDebugLog) { 86 | NSLog(@"%p, %s", self, __func__); 87 | } 88 | 89 | } 90 | 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /RollingNotice/SecondViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SecondViewController.m 3 | // RollingNotice 4 | // 5 | // Created by qm on 2018/8/7. 6 | // Copyright © 2018年 qm. All rights reserved. 7 | // 8 | 9 | #import "SecondViewController.h" 10 | #import "GYRollingNoticeView.h" 11 | 12 | @interface SecondViewController () 13 | 14 | { 15 | NSArray *_arr; 16 | 17 | } 18 | 19 | @property (weak, nonatomic) IBOutlet GYRollingNoticeView *noticeView; 20 | 21 | 22 | @end 23 | 24 | @implementation SecondViewController 25 | 26 | - (void)viewDidLoad { 27 | [super viewDidLoad]; 28 | // Do any additional setup after loading the view from its nib. 29 | 30 | _arr = @[@"小米千元全面屏:抱歉,久等!625献上", 31 | @"可怜狗狗被抛弃,苦苦等候主人半年", 32 | @"三星中端新机改名,全面屏火力全开", 33 | @"学会这些,这5种花不用去花店买了", 34 | @"华为nova2S发布,剧透了荣耀10?" 35 | ]; 36 | 37 | _noticeView.delegate = self; 38 | _noticeView.dataSource = self; 39 | [_noticeView registerClass:[GYNoticeViewCell class] forCellReuseIdentifier:@"GYNoticeViewCell"]; 40 | 41 | [_noticeView reloadDataAndStartRoll]; 42 | } 43 | 44 | - (void)viewWillDisappear:(BOOL)animated 45 | { 46 | [super viewWillDisappear:animated]; 47 | [_noticeView stopRoll]; 48 | } 49 | 50 | 51 | #pragma mark- 52 | - (NSInteger)numberOfRowsForRollingNoticeView:(GYRollingNoticeView *)rollingView 53 | { 54 | return _arr.count; 55 | } 56 | - (__kindof GYNoticeViewCell *)rollingNoticeView:(GYRollingNoticeView *)rollingView cellAtIndex:(NSUInteger)index 57 | { 58 | GYNoticeViewCell *cell = [rollingView dequeueReusableCellWithIdentifier:@"GYNoticeViewCell"]; 59 | cell.textLabel.text = [NSString stringWithFormat:@"index %d ,%@", (int)index, _arr[index]]; 60 | cell.contentView.backgroundColor = [UIColor orangeColor]; 61 | cell.textLabelLeading = 100; 62 | cell.textLabelTrailing = 80; 63 | if (index % 2 == 0) { 64 | cell.contentView.backgroundColor = [UIColor greenColor]; 65 | cell.textLabelLeading = 0; 66 | } 67 | return cell; 68 | 69 | } 70 | 71 | - (void)didClickRollingNoticeView:(GYRollingNoticeView *)rollingView forIndex:(NSUInteger)index 72 | { 73 | NSLog(@"点击的index: %d", rollingView.currentIndex); 74 | } 75 | 76 | 77 | 78 | - (IBAction)handleBtnAction:(UIButton *)sender { 79 | if (_noticeView.status == GYRollingNoticeViewStatusWorking) { 80 | [_noticeView pause]; 81 | [sender setTitle:@"resume" forState:UIControlStateNormal]; 82 | 83 | }else if (_noticeView.status != GYRollingNoticeViewStatusWorking) { 84 | [_noticeView resume]; 85 | [sender setTitle:@"pause" forState:UIControlStateNormal]; 86 | } 87 | } 88 | 89 | 90 | 91 | 92 | - (void)dealloc 93 | { 94 | NSLog(@"%s", __func__); 95 | } 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /RollingNotice/ThirdViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ThirdViewController.m 3 | // RollingNotice 4 | // 5 | // Created by zgy on 2020/4/15. 6 | // Copyright © 2020 qm. All rights reserved. 7 | // 8 | 9 | #import "ThirdViewController.h" 10 | #import "DemoCodeAutoLayout.h" 11 | #import "GYRollingNoticeView.h" 12 | 13 | @interface ThirdViewController () 14 | 15 | { 16 | NSArray *_arr; 17 | 18 | } 19 | @property (nonatomic, strong) GYRollingNoticeView *noticeView; 20 | @end 21 | 22 | @implementation ThirdViewController 23 | 24 | - (instancetype)init 25 | { 26 | self = [super init]; 27 | if (self) { 28 | 29 | _arr = @[@"小米千元全面屏:抱歉,久等!625献上", 30 | // @"可怜狗狗被抛弃,苦苦等候主人半年", 31 | // @"三星中端新机改名,全面屏火力全开", 32 | // @"学会这些,这5种花不用去花店买了", 33 | // @"华为nova2S发布,剧透了荣耀10?" 34 | ]; 35 | 36 | 37 | _noticeView = [[GYRollingNoticeView alloc] init]; 38 | _noticeView.delegate = self; 39 | _noticeView.dataSource = self; 40 | 41 | [self.view addSubview:_noticeView]; 42 | 43 | 44 | [_noticeView registerClass:[DemoCodeAutoLayout class] forCellReuseIdentifier:@"DemoCodeAutoLayout"]; 45 | 46 | [_noticeView reloadDataAndStartRoll]; 47 | 48 | _noticeView.translatesAutoresizingMaskIntoConstraints = NO; 49 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-160-[v]" options:0 metrics:nil views:@{@"v": _noticeView}]]; 50 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[v]-20-|" options:0 metrics:nil views:@{@"v": _noticeView}]]; 51 | 52 | [_noticeView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[v(30)]" options:0 metrics:nil views:@{@"v": _noticeView}]]; 53 | 54 | } 55 | return self; 56 | } 57 | 58 | 59 | - (void)viewDidLoad { 60 | [super viewDidLoad]; 61 | self.view.backgroundColor = [UIColor whiteColor]; 62 | } 63 | 64 | 65 | - (void)viewWillDisappear:(BOOL)animated 66 | { 67 | [super viewWillDisappear:animated]; 68 | [_noticeView stopRoll]; 69 | } 70 | 71 | 72 | #pragma mark- 73 | - (NSInteger)numberOfRowsForRollingNoticeView:(GYRollingNoticeView *)rollingView 74 | { 75 | return _arr.count; 76 | } 77 | - (__kindof GYNoticeViewCell *)rollingNoticeView:(GYRollingNoticeView *)rollingView cellAtIndex:(NSUInteger)index 78 | { 79 | DemoCodeAutoLayout *cell = [rollingView dequeueReusableCellWithIdentifier:@"DemoCodeAutoLayout"]; 80 | cell.customLab.text = _arr[index]; 81 | return cell; 82 | 83 | } 84 | 85 | - (void)didClickRollingNoticeView:(GYRollingNoticeView *)rollingView forIndex:(NSUInteger)index 86 | { 87 | NSLog(@"点击的index: %d", rollingView.currentIndex); 88 | } 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /RollingNotice.xcodeproj/xcshareddata/xcschemes/RollingNotice.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /RollingNotice.xcodeproj/xcuserdata/qm.xcuserdatad/xcschemes/RollingNotice.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /RollingNotice/SecondViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /RollingNotice/DemoCell3.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /RollingNotice/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /RollingNotice.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint RollingNotice.podspec' to ensure this is a 3 | # valid spec and to remove all comments including this before submitting the spec. 4 | # 5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html 6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | 11 | # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 12 | # 13 | # These will help people to find your library, and whilst it 14 | # can feel like a chore to fill in it's definitely to your advantage. The 15 | # summary should be tweet-length, and the description more in depth. 16 | # 17 | 18 | s.name = "RollingNotice" 19 | s.version = "1.1.1" 20 | s.summary = "滚动公告、广告,支持灵活自定义cell。淘宝、口碑、京东、美团、天猫等等一切滚动广告 Roll Notice or Advertising. A rolling banner, custom cell like UITableViewCell supported" 21 | 22 | # This description is used to generate tags and improve search results. 23 | # * Think: What does it do? Why did you write it? What is the focus? 24 | # * Try to keep it short, snappy and to the point. 25 | # * Write the description between the DESC delimiters below. 26 | # * Finally, don't worry about the indent, CocoaPods strips it! 27 | s.description = <<-DESC 28 | 可以简单的滚动文本公告,也可以像淘宝头条那样很复杂。你自定义cell,根据index赋值,滚动交给它! 29 | 用法和UITableView几乎一样,也支持重用 30 | A rolling banner for iOS, you can custom cell for it. Just similar as UITableView 31 | DESC 32 | 33 | s.homepage = "https://github.com/maltsugar/RollingNotice" 34 | # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif" 35 | 36 | 37 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 38 | # 39 | # Licensing your code is important. See http://choosealicense.com for more info. 40 | # CocoaPods will detect a license file if there is a named LICENSE* 41 | # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'. 42 | # 43 | 44 | s.license = { :type => "MIT", :file => "LICENSE" } 45 | 46 | 47 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 48 | # 49 | # Specify the authors of the library, with email addresses. Email addresses 50 | # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also 51 | # accepts just a name if you'd rather not provide an email address. 52 | # 53 | # Specify a social_media_url where others can refer to, for example a twitter 54 | # profile URL. 55 | # 56 | 57 | s.author = { "zgy" => "173678978@qq.com" } 58 | # Or just: s.author = "zgy" 59 | # s.authors = { "zgy" => "173678978@qq.com" } 60 | # s.social_media_url = "http://twitter.com/zgy" 61 | 62 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 63 | # 64 | # If this Pod runs only on iOS or OS X, then specify the platform and 65 | # the deployment target. You can optionally include the target after the platform. 66 | # 67 | 68 | 69 | s.platform = :ios, "5.0" 70 | 71 | # When using multiple platforms 72 | s.ios.deployment_target = "5.0" 73 | # s.osx.deployment_target = "10.7" 74 | # s.watchos.deployment_target = "2.0" 75 | # s.tvos.deployment_target = "9.0" 76 | 77 | 78 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 79 | # 80 | # Specify the location from where the source should be retrieved. 81 | # Supports git, hg, bzr, svn and HTTP. 82 | # 83 | 84 | s.source = { :git => "https://github.com/maltsugar/RollingNotice.git", :tag => "#{s.version}" } 85 | 86 | 87 | # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 88 | # 89 | # CocoaPods is smart about how it includes source code. For source files 90 | # giving a folder will include any swift, h, m, mm, c & cpp files. 91 | # For header files it will include any header in the folder. 92 | # Not including the public_header_files will make all headers public. 93 | # 94 | 95 | s.source_files = "GYRollingNoticeView", "RollingNotice/GYRollingNoticeView/*.{h,m}" 96 | s.framework = "UIKit" 97 | 98 | # s.public_header_files = "Classes/**/*.h" 99 | 100 | 101 | # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 102 | # 103 | # A list of resources included with the Pod. These are copied into the 104 | # target bundle with a build phase script. Anything else will be cleaned. 105 | # You can preserve files from being cleaned, please don't preserve 106 | # non-essential files like tests, examples and documentation. 107 | # 108 | 109 | # s.resource = "icon.png" 110 | # s.resources = "Resources/*.png" 111 | 112 | # s.preserve_paths = "FilesToSave", "MoreFilesToSave" 113 | 114 | 115 | # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 116 | # 117 | # Link your library with frameworks, or libraries. Libraries do not include 118 | # the lib prefix of their name. 119 | # 120 | 121 | # s.framework = "SomeFramework" 122 | # s.frameworks = "SomeFramework", "AnotherFramework" 123 | 124 | # s.library = "iconv" 125 | # s.libraries = "iconv", "xml2" 126 | 127 | 128 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 129 | # 130 | # If your library depends on compiler flags you can set them in the xcconfig hash 131 | # where they will only apply to your library. If you depend on other Podspecs 132 | # you can include multiple dependencies to ensure it works. 133 | 134 | # s.requires_arc = true 135 | 136 | # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } 137 | # s.dependency "JSONKit", "~> 1.4" 138 | 139 | end 140 | -------------------------------------------------------------------------------- /RollingNotice/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // RollingNotice 4 | // 5 | // Created by qm on 2017/12/4. 6 | // Copyright © 2017年 qm. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "GYRollingNoticeView.h" 11 | #import "CustomNoticeCell.h" 12 | #import "DemoCell2.h" 13 | #import "DemoCell3.h" 14 | #import "SecondViewController.h" 15 | #import "ThirdViewController.h" 16 | 17 | @interface ViewController () 18 | { 19 | NSArray *_arr0; 20 | NSArray *_arr1; 21 | 22 | GYRollingNoticeView *_noticeView0; 23 | GYRollingNoticeView *_noticeView1; 24 | 25 | } 26 | @end 27 | 28 | @implementation ViewController 29 | 30 | - (void)viewDidLoad { 31 | [super viewDidLoad]; 32 | float w = [[UIScreen mainScreen] bounds].size.width; 33 | UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(0, 80, w, 100)]; 34 | lab.numberOfLines = 0; 35 | lab.text = @"滚动公告、广告,支持自定义cell,模仿淘宝头条等等。 \nUITableViewCell重用理念,支持请Star!"; 36 | [self.view addSubview:lab]; 37 | 38 | 39 | 40 | _arr0 = @[ 41 | @{@"arr": @[@{@"tag": @"手机", @"title": @"小米千元全面屏:抱歉,久等!625献上"}, @{@"tag": @"萌宠", @"title": @"可怜狗狗被抛弃,苦苦等候主人半年"}], @"img": @"tb_icon2"}, 42 | @{@"arr": @[@{@"tag": @"手机", @"title": @"三星中端新机改名,全面屏火力全开"}, @{@"tag": @"围观", @"title": @"主人假装离去,狗狗直接把孩子推回去了"}], @"img": @"tb_icon3"}, 43 | @{@"arr": @[@{@"tag": @"园艺", @"title": @"学会这些,这5种花不用去花店买了"}, @{@"tag": @"手机", @"title": @"华为nova2S发布,剧透了荣耀10?"}], @"img": @"tb_icon5"}, 44 | @{@"arr": @[@{@"tag": @"开发", @"title": @"iOS 内购最新讲解"}, @{@"tag": @"博客", @"title": @"技术博客那些事儿"}], @"img": @"tb_icon6"}, 45 | @{@"arr": @[@{@"tag": @"招聘", @"title": @"招聘XX高级开发工程师"}, @{@"tag": @"资讯", @"title": @"如何写一篇好的技术博客"}], @"img": @"tb_icon7"} 46 | ]; 47 | _arr1 = @[@"小米千元全面屏:抱歉,久等!625献上", 48 | @"可怜狗狗被抛弃,苦苦等候主人半年", 49 | @"三星中端新机改名,全面屏火力全开", 50 | @"学会这些,这5种花不用去花店买了", 51 | @"华为nova2S发布,剧透了荣耀10?" 52 | ]; 53 | 54 | [self creatRollingViewWithArray:_arr0 isFirst:YES]; 55 | [self creatRollingViewWithArray:_arr1 isFirst:NO]; 56 | 57 | 58 | // 刷新数据源 reload datasource test ok 59 | // dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 60 | // _arr1 = @[@"0", @"1", @"2", @"3", @"4", @"5"]; 61 | //// _arr1 = @[@"0"]; 62 | // [_noticeView1 reloadDataAndStartRoll]; 63 | // }); 64 | 65 | } 66 | 67 | // 请在合适的时机 停止 68 | - (void)viewDidDisappear:(BOOL)animated 69 | { 70 | [super viewDidDisappear:animated]; 71 | [_noticeView0 stopRoll]; 72 | [_noticeView1 stopRoll]; 73 | } 74 | 75 | - (void)viewWillAppear:(BOOL)animated 76 | { 77 | [super viewWillAppear:animated]; 78 | [_noticeView0 reloadDataAndStartRoll]; 79 | } 80 | 81 | 82 | - (void)creatRollingViewWithArray:(NSArray *)arr isFirst:(BOOL)isFirst 83 | { 84 | float w = [[UIScreen mainScreen] bounds].size.width; 85 | CGRect frame = CGRectMake(0, 190, w, 50); 86 | if (!isFirst) { 87 | frame = CGRectMake(0, 290, w, 30); 88 | } 89 | 90 | GYRollingNoticeView *noticeView = [[GYRollingNoticeView alloc]initWithFrame:frame]; 91 | noticeView.dataSource = self; 92 | noticeView.delegate = self; 93 | [self.view addSubview:noticeView]; 94 | noticeView.backgroundColor = [UIColor lightGrayColor]; 95 | 96 | if (isFirst) { 97 | _noticeView0 = noticeView; 98 | [noticeView registerNib:[UINib nibWithNibName:@"CustomNoticeCell" bundle:nil] forCellReuseIdentifier:@"CustomNoticeCell"]; 99 | [noticeView registerNib:[UINib nibWithNibName:@"DemoCell3" bundle:nil] forCellReuseIdentifier:@"DemoCell3"]; 100 | 101 | }else{ 102 | _noticeView1 = noticeView; 103 | [noticeView registerClass:[GYNoticeViewCell class] forCellReuseIdentifier:@"GYNoticeViewCell"]; 104 | [noticeView registerClass:[DemoCell2 class] forCellReuseIdentifier:@"DemoCell2"]; 105 | } 106 | 107 | [noticeView reloadDataAndStartRoll]; 108 | } 109 | 110 | 111 | 112 | - (NSInteger)numberOfRowsForRollingNoticeView:(GYRollingNoticeView *)rollingView 113 | { 114 | if (rollingView == _noticeView0) { 115 | return _arr0.count; 116 | } 117 | 118 | if (rollingView == _noticeView1) { 119 | return _arr1.count; 120 | } 121 | 122 | return 0; 123 | } 124 | - (__kindof GYNoticeViewCell *)rollingNoticeView:(GYRollingNoticeView *)rollingView cellAtIndex:(NSUInteger)index 125 | { 126 | if (rollingView == _noticeView0) { 127 | 128 | if (index < 3) { 129 | CustomNoticeCell *cell = [rollingView dequeueReusableCellWithIdentifier:@"CustomNoticeCell"]; 130 | [cell noticeCellWithArr:_arr0 forIndex:index]; 131 | return cell; 132 | }else 133 | { 134 | DemoCell3 *cell = [rollingView dequeueReusableCellWithIdentifier:@"DemoCell3"]; 135 | NSDictionary *dic = _arr0[index]; 136 | cell.lab0.text = [dic[@"arr"] firstObject][@"title"]; 137 | cell.lab1.text = [dic[@"arr"] lastObject][@"title"]; 138 | return cell; 139 | } 140 | 141 | 142 | 143 | } 144 | 145 | // 普通用法,只有一行label滚动显示文字 146 | // normal use, only one line label rolling 147 | if (rollingView == _noticeView1) { 148 | if (index < 3) { 149 | GYNoticeViewCell *cell = [rollingView dequeueReusableCellWithIdentifier:@"GYNoticeViewCell"]; 150 | cell.textLabel.text = [NSString stringWithFormat:@"第1种cell %@", _arr1[index]]; 151 | cell.contentView.backgroundColor = [UIColor orangeColor]; 152 | if (index % 2 == 0) { 153 | cell.contentView.backgroundColor = [UIColor greenColor]; 154 | } 155 | return cell; 156 | }else { 157 | 158 | DemoCell2 *cell = [rollingView dequeueReusableCellWithIdentifier:@"DemoCell2"]; 159 | cell.customLab.text = [NSString stringWithFormat:@"第2种cell %@", _arr1[index]]; 160 | cell.contentView.backgroundColor = [UIColor purpleColor]; 161 | return cell; 162 | } 163 | 164 | 165 | } 166 | 167 | 168 | return nil; 169 | } 170 | 171 | - (void)didClickRollingNoticeView:(GYRollingNoticeView *)rollingView forIndex:(NSUInteger)index 172 | { 173 | NSLog(@"点击的index: %lu", (unsigned long)index); 174 | } 175 | 176 | #pragma mark- IBActions 177 | 178 | - (IBAction)handleRightAction:(UIBarButtonItem *)sender 179 | { 180 | // SecondViewController *vc = [SecondViewController new]; 181 | ThirdViewController *vc = [ThirdViewController new]; 182 | [self.navigationController pushViewController:vc animated:YES]; 183 | } 184 | 185 | 186 | - (IBAction)handlePauseResumeAction:(UIButton *)sender { 187 | if (_noticeView0.status == GYRollingNoticeViewStatusWorking) { 188 | [_noticeView0 pause]; 189 | 190 | }else if (_noticeView0.status != GYRollingNoticeViewStatusWorking) { 191 | [_noticeView0 resume]; 192 | } 193 | } 194 | 195 | @end 196 | -------------------------------------------------------------------------------- /RollingNotice/CustomNoticeCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 40 | 46 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /RollingNotice/GYRollingNoticeView/GYRollingNoticeView.m: -------------------------------------------------------------------------------- 1 | // 2 | // GYRollingNoticeView.m 3 | // RollingNotice 4 | // 5 | // Created by qm on 2017/12/4. 6 | // Copyright © 2017年 qm. All rights reserved. 7 | // 8 | 9 | #import "GYRollingNoticeView.h" 10 | #import "GYNoticeViewCell.h" 11 | 12 | 13 | #define kGYNotiWeakSelf(type) __weak typeof(type) weak##type = type; 14 | #define kGYNotiStrongSelf(type) __strong typeof(type) type = weak##type; 15 | 16 | @interface GYRollingNoticeView () 17 | 18 | { 19 | int _cIdx; 20 | BOOL _needTryRoll; 21 | } 22 | 23 | @property (nonatomic, strong) NSMutableDictionary *cellClsDict; 24 | @property (nonatomic, strong) NSMutableArray *reuseCells; 25 | 26 | @property (nonatomic, strong) NSTimer *timer; 27 | @property (nonatomic, strong) GYNoticeViewCell *currentCell; 28 | @property (nonatomic, strong) GYNoticeViewCell *willShowCell; 29 | @property (nonatomic, assign) BOOL isAnimating; 30 | 31 | 32 | @end 33 | 34 | @implementation GYRollingNoticeView 35 | @dynamic currentIndex; 36 | 37 | - (instancetype)init 38 | { 39 | self = [super init]; 40 | if (self) { 41 | [self setupNoticeViews]; 42 | } 43 | return self; 44 | } 45 | 46 | - (instancetype)initWithFrame:(CGRect)frame 47 | { 48 | self = [super initWithFrame:frame]; 49 | if (self) { 50 | [self setupNoticeViews]; 51 | } 52 | return self; 53 | } 54 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 55 | { 56 | self = [super initWithCoder:aDecoder]; 57 | if (self) { 58 | [self setupNoticeViews]; 59 | } 60 | return self; 61 | } 62 | 63 | - (void)setupNoticeViews 64 | { 65 | self.clipsToBounds = YES; 66 | _stayInterval = 2; 67 | [self addGestureRecognizer:[self createTapGesture]]; 68 | } 69 | 70 | - (void)layoutSubviews 71 | { 72 | [super layoutSubviews]; 73 | if (_needTryRoll) { 74 | [self reloadDataAndStartRoll]; 75 | _needTryRoll = NO; 76 | } 77 | 78 | } 79 | 80 | 81 | 82 | - (void)registerClass:(nullable Class)cellClass forCellReuseIdentifier:(NSString *)identifier 83 | { 84 | [self.cellClsDict setObject:NSStringFromClass(cellClass) forKey:identifier]; 85 | } 86 | 87 | - (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier 88 | { 89 | [self.cellClsDict setObject:nib forKey:identifier]; 90 | } 91 | 92 | - (__kindof GYNoticeViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier 93 | { 94 | for (GYNoticeViewCell *cell in self.reuseCells) { 95 | 96 | if ([cell.reuseIdentifier isEqualToString:identifier]) { 97 | // NSLog(@"finded reuse cell: %p", cell); 98 | return cell; 99 | } 100 | } 101 | 102 | id cellClass = self.cellClsDict[identifier]; 103 | if ([cellClass isKindOfClass:[UINib class]]) { 104 | UINib *nib = (UINib *)cellClass; 105 | 106 | NSArray *arr = [nib instantiateWithOwner:nil options:nil]; 107 | GYNoticeViewCell *cell = [arr firstObject]; 108 | [cell setValue:identifier forKeyPath:@"reuseIdentifier"]; 109 | return cell; 110 | }else 111 | { 112 | Class cellCls = NSClassFromString(self.cellClsDict[identifier]); 113 | GYNoticeViewCell *cell = [[cellCls alloc] initWithReuseIdentifier:identifier]; 114 | return cell; 115 | } 116 | 117 | } 118 | 119 | 120 | #pragma mark- rolling 121 | - (void)layoutCurrentCellAndWillShowCell 122 | { 123 | int count = (int)[self.dataSource numberOfRowsForRollingNoticeView:self]; 124 | if (_cIdx > count - 1) { 125 | _cIdx = 0; 126 | } 127 | 128 | int willShowIndex = _cIdx + 1; 129 | if (willShowIndex > count - 1) { 130 | willShowIndex = 0; 131 | } 132 | // NSLog(@">>>>%d", _cIdx); 133 | 134 | float w = self.frame.size.width; 135 | float h = self.frame.size.height; 136 | 137 | // NSLog(@"count: %d, _cIdx:%d willShowIndex: %d", count, _cIdx, willShowIndex); 138 | 139 | if (!(w > 0 && h > 0)) { 140 | _needTryRoll = YES; 141 | return; 142 | } 143 | if (!_currentCell) { 144 | // 第一次没有currentcell 145 | // currentcell is null at first time 146 | _currentCell = [self.dataSource rollingNoticeView:self cellAtIndex:_cIdx]; 147 | _currentCell.frame = CGRectMake(0, 0, w, h); 148 | [self addSubview:_currentCell]; 149 | return; 150 | } 151 | 152 | 153 | 154 | _willShowCell = [self.dataSource rollingNoticeView:self cellAtIndex:willShowIndex]; 155 | _willShowCell.frame = CGRectMake(0, h, w, h); 156 | [self addSubview:_willShowCell]; 157 | 158 | 159 | if (GYRollingDebugLog) { 160 | NSLog(@"_currentCell %p", _currentCell); 161 | NSLog(@"_willShowCell %p", _willShowCell); 162 | } 163 | 164 | [self.reuseCells removeObject:_currentCell]; 165 | [self.reuseCells removeObject:_willShowCell]; 166 | 167 | 168 | } 169 | 170 | - (void)reloadDataAndStartRoll 171 | { 172 | [self stopRoll]; 173 | 174 | NSInteger count = [self.dataSource numberOfRowsForRollingNoticeView:self]; 175 | if (count < 1) { 176 | return; 177 | } 178 | 179 | [self layoutCurrentCellAndWillShowCell]; 180 | 181 | if (count && count < 2) { 182 | return; 183 | } 184 | 185 | 186 | _timer = [NSTimer scheduledTimerWithTimeInterval:_stayInterval target:self selector:@selector(timerHandle) userInfo:nil repeats:YES]; 187 | NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; 188 | [runLoop addTimer:_timer forMode:NSRunLoopCommonModes]; 189 | [self resume]; 190 | } 191 | 192 | - (void)stopRoll 193 | { 194 | if (_timer) { 195 | [_timer invalidate]; 196 | _timer = nil; 197 | } 198 | 199 | _status = GYRollingNoticeViewStatusIdle; 200 | _isAnimating = NO; 201 | _cIdx = 0; 202 | [_currentCell removeFromSuperview]; 203 | [_willShowCell removeFromSuperview]; 204 | _currentCell = nil; 205 | _willShowCell = nil; 206 | [self.reuseCells removeAllObjects]; 207 | } 208 | 209 | - (void)pause 210 | { 211 | if (_timer) { 212 | [_timer setFireDate:[NSDate distantFuture]]; 213 | _status = GYRollingNoticeViewStatusPause; 214 | } 215 | } 216 | - (void)resume 217 | { 218 | if (_timer) { 219 | [_timer setFireDate:[NSDate distantPast]]; 220 | _status = GYRollingNoticeViewStatusWorking; 221 | } 222 | } 223 | 224 | - (void)timerHandle 225 | { 226 | // NSLog(@"-----------------------------------"); 227 | 228 | if (self.isAnimating) return; 229 | 230 | [self layoutCurrentCellAndWillShowCell]; 231 | 232 | 233 | float w = self.frame.size.width; 234 | float h = self.frame.size.height; 235 | 236 | self.isAnimating = YES; 237 | 238 | kGYNotiWeakSelf(self); 239 | [UIView animateWithDuration:0.5 animations:^{ 240 | kGYNotiStrongSelf(self); 241 | 242 | self.currentCell.frame = CGRectMake(0, -h, w, h); 243 | self.willShowCell.frame = CGRectMake(0, 0, w, h); 244 | } completion:^(BOOL finished) { 245 | kGYNotiStrongSelf(self); 246 | 247 | // fixed bug: reload data when animate running 248 | if (self.currentCell && self.willShowCell) { 249 | [self.reuseCells addObject:self.currentCell]; 250 | [self.currentCell removeFromSuperview]; 251 | self.currentCell = self.willShowCell; 252 | } 253 | self.isAnimating = NO; 254 | 255 | self -> _cIdx ++; 256 | }]; 257 | } 258 | 259 | 260 | - (void)handleCellTapAction 261 | { 262 | if ([self.delegate respondsToSelector:@selector(didClickRollingNoticeView:forIndex:)]) { 263 | [self.delegate didClickRollingNoticeView:self forIndex:self.currentIndex]; 264 | } 265 | } 266 | 267 | - (UITapGestureRecognizer *)createTapGesture 268 | { 269 | return [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleCellTapAction)]; 270 | } 271 | 272 | - (void)touchesBegan:(NSSet *)touches withEvent:(nullable UIEvent *)event{} 273 | 274 | 275 | #pragma mark- 276 | 277 | - (int)currentIndex { 278 | int count = (int)[self.dataSource numberOfRowsForRollingNoticeView:self]; 279 | if (_cIdx > count - 1) { 280 | _cIdx = 0; 281 | } 282 | return _cIdx; 283 | } 284 | 285 | 286 | #pragma mark- lazy 287 | - (NSMutableDictionary *)cellClsDict 288 | { 289 | if (nil == _cellClsDict) { 290 | _cellClsDict = [[NSMutableDictionary alloc]init]; 291 | } 292 | return _cellClsDict; 293 | } 294 | 295 | - (NSMutableArray *)reuseCells 296 | { 297 | if (nil == _reuseCells) { 298 | _reuseCells = [[NSMutableArray alloc]init]; 299 | } 300 | return _reuseCells; 301 | } 302 | 303 | 304 | @end 305 | -------------------------------------------------------------------------------- /RollingNotice.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 916CCC9E1FDA34330070CAF3 /* CustomNoticeCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 916CCC9D1FDA34330070CAF3 /* CustomNoticeCell.m */; }; 11 | 916CCCA01FDA343F0070CAF3 /* CustomNoticeCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 916CCC9F1FDA343F0070CAF3 /* CustomNoticeCell.xib */; }; 12 | 919DB80E1FE0F44600029F63 /* DemoCell2.m in Sources */ = {isa = PBXBuildFile; fileRef = 919DB80D1FE0F44600029F63 /* DemoCell2.m */; }; 13 | 919DB8111FE0F84400029F63 /* DemoCell3.m in Sources */ = {isa = PBXBuildFile; fileRef = 919DB8101FE0F84400029F63 /* DemoCell3.m */; }; 14 | 919DB8131FE0F84E00029F63 /* DemoCell3.xib in Resources */ = {isa = PBXBuildFile; fileRef = 919DB8121FE0F84E00029F63 /* DemoCell3.xib */; }; 15 | 91BA83E321194E8D002D2F85 /* SecondViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 91BA83E121194E8D002D2F85 /* SecondViewController.m */; }; 16 | 91BA83E421194E8D002D2F85 /* SecondViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 91BA83E221194E8D002D2F85 /* SecondViewController.xib */; }; 17 | 91FFD87C1FD52A36004A1A27 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 91FFD87B1FD52A36004A1A27 /* AppDelegate.m */; }; 18 | 91FFD87F1FD52A36004A1A27 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 91FFD87E1FD52A36004A1A27 /* ViewController.m */; }; 19 | 91FFD8821FD52A36004A1A27 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 91FFD8801FD52A36004A1A27 /* Main.storyboard */; }; 20 | 91FFD8841FD52A36004A1A27 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 91FFD8831FD52A36004A1A27 /* Assets.xcassets */; }; 21 | 91FFD8871FD52A36004A1A27 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 91FFD8851FD52A36004A1A27 /* LaunchScreen.storyboard */; }; 22 | 91FFD88A1FD52A36004A1A27 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 91FFD8891FD52A36004A1A27 /* main.m */; }; 23 | 91FFD8931FD52A6F004A1A27 /* GYRollingNoticeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 91FFD8921FD52A6F004A1A27 /* GYRollingNoticeView.m */; }; 24 | 91FFD8961FD52A96004A1A27 /* GYNoticeViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 91FFD8951FD52A96004A1A27 /* GYNoticeViewCell.m */; }; 25 | B911E5C92447331000A758F5 /* ThirdViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B911E5C82447331000A758F5 /* ThirdViewController.m */; }; 26 | B9C7FE0F2447121D0006323D /* DemoCodeAutoLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = B9C7FE0E2447121D0006323D /* DemoCodeAutoLayout.m */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXFileReference section */ 30 | 916CCC9C1FDA34330070CAF3 /* CustomNoticeCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CustomNoticeCell.h; sourceTree = ""; }; 31 | 916CCC9D1FDA34330070CAF3 /* CustomNoticeCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CustomNoticeCell.m; sourceTree = ""; }; 32 | 916CCC9F1FDA343F0070CAF3 /* CustomNoticeCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CustomNoticeCell.xib; sourceTree = ""; }; 33 | 919DB80C1FE0F44600029F63 /* DemoCell2.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DemoCell2.h; sourceTree = ""; }; 34 | 919DB80D1FE0F44600029F63 /* DemoCell2.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DemoCell2.m; sourceTree = ""; }; 35 | 919DB80F1FE0F84400029F63 /* DemoCell3.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DemoCell3.h; sourceTree = ""; }; 36 | 919DB8101FE0F84400029F63 /* DemoCell3.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DemoCell3.m; sourceTree = ""; }; 37 | 919DB8121FE0F84E00029F63 /* DemoCell3.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DemoCell3.xib; sourceTree = ""; }; 38 | 91BA83E021194E8D002D2F85 /* SecondViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecondViewController.h; sourceTree = ""; }; 39 | 91BA83E121194E8D002D2F85 /* SecondViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecondViewController.m; sourceTree = ""; }; 40 | 91BA83E221194E8D002D2F85 /* SecondViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SecondViewController.xib; sourceTree = ""; }; 41 | 91FFD8771FD52A36004A1A27 /* RollingNotice.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RollingNotice.app; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | 91FFD87A1FD52A36004A1A27 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 43 | 91FFD87B1FD52A36004A1A27 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 44 | 91FFD87D1FD52A36004A1A27 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 45 | 91FFD87E1FD52A36004A1A27 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 46 | 91FFD8811FD52A36004A1A27 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 47 | 91FFD8831FD52A36004A1A27 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 48 | 91FFD8861FD52A36004A1A27 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 49 | 91FFD8881FD52A36004A1A27 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 50 | 91FFD8891FD52A36004A1A27 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 51 | 91FFD8911FD52A6F004A1A27 /* GYRollingNoticeView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GYRollingNoticeView.h; sourceTree = ""; }; 52 | 91FFD8921FD52A6F004A1A27 /* GYRollingNoticeView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GYRollingNoticeView.m; sourceTree = ""; }; 53 | 91FFD8941FD52A96004A1A27 /* GYNoticeViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GYNoticeViewCell.h; sourceTree = ""; }; 54 | 91FFD8951FD52A96004A1A27 /* GYNoticeViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GYNoticeViewCell.m; sourceTree = ""; }; 55 | B911E5C72447331000A758F5 /* ThirdViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ThirdViewController.h; sourceTree = ""; }; 56 | B911E5C82447331000A758F5 /* ThirdViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ThirdViewController.m; sourceTree = ""; }; 57 | B9C7FE0D2447121D0006323D /* DemoCodeAutoLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DemoCodeAutoLayout.h; sourceTree = ""; }; 58 | B9C7FE0E2447121D0006323D /* DemoCodeAutoLayout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DemoCodeAutoLayout.m; sourceTree = ""; }; 59 | /* End PBXFileReference section */ 60 | 61 | /* Begin PBXFrameworksBuildPhase section */ 62 | 91FFD8741FD52A36004A1A27 /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | ); 67 | runOnlyForDeploymentPostprocessing = 0; 68 | }; 69 | /* End PBXFrameworksBuildPhase section */ 70 | 71 | /* Begin PBXGroup section */ 72 | 91FFD86E1FD52A36004A1A27 = { 73 | isa = PBXGroup; 74 | children = ( 75 | 91FFD8791FD52A36004A1A27 /* RollingNotice */, 76 | 91FFD8781FD52A36004A1A27 /* Products */, 77 | ); 78 | sourceTree = ""; 79 | }; 80 | 91FFD8781FD52A36004A1A27 /* Products */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 91FFD8771FD52A36004A1A27 /* RollingNotice.app */, 84 | ); 85 | name = Products; 86 | sourceTree = ""; 87 | }; 88 | 91FFD8791FD52A36004A1A27 /* RollingNotice */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 91FFD8901FD52A3F004A1A27 /* GYRollingNoticeView */, 92 | 91FFD87A1FD52A36004A1A27 /* AppDelegate.h */, 93 | 91FFD87B1FD52A36004A1A27 /* AppDelegate.m */, 94 | 91FFD87D1FD52A36004A1A27 /* ViewController.h */, 95 | 91FFD87E1FD52A36004A1A27 /* ViewController.m */, 96 | 91BA83E021194E8D002D2F85 /* SecondViewController.h */, 97 | 91BA83E121194E8D002D2F85 /* SecondViewController.m */, 98 | 91BA83E221194E8D002D2F85 /* SecondViewController.xib */, 99 | B911E5C72447331000A758F5 /* ThirdViewController.h */, 100 | B911E5C82447331000A758F5 /* ThirdViewController.m */, 101 | 916CCC9C1FDA34330070CAF3 /* CustomNoticeCell.h */, 102 | 916CCC9D1FDA34330070CAF3 /* CustomNoticeCell.m */, 103 | 916CCC9F1FDA343F0070CAF3 /* CustomNoticeCell.xib */, 104 | 919DB80C1FE0F44600029F63 /* DemoCell2.h */, 105 | 919DB80D1FE0F44600029F63 /* DemoCell2.m */, 106 | 919DB80F1FE0F84400029F63 /* DemoCell3.h */, 107 | 919DB8101FE0F84400029F63 /* DemoCell3.m */, 108 | 919DB8121FE0F84E00029F63 /* DemoCell3.xib */, 109 | B9C7FE0D2447121D0006323D /* DemoCodeAutoLayout.h */, 110 | B9C7FE0E2447121D0006323D /* DemoCodeAutoLayout.m */, 111 | 91FFD8801FD52A36004A1A27 /* Main.storyboard */, 112 | 91FFD8831FD52A36004A1A27 /* Assets.xcassets */, 113 | 91FFD8851FD52A36004A1A27 /* LaunchScreen.storyboard */, 114 | 91FFD8881FD52A36004A1A27 /* Info.plist */, 115 | 91FFD8891FD52A36004A1A27 /* main.m */, 116 | ); 117 | path = RollingNotice; 118 | sourceTree = ""; 119 | }; 120 | 91FFD8901FD52A3F004A1A27 /* GYRollingNoticeView */ = { 121 | isa = PBXGroup; 122 | children = ( 123 | 91FFD8911FD52A6F004A1A27 /* GYRollingNoticeView.h */, 124 | 91FFD8921FD52A6F004A1A27 /* GYRollingNoticeView.m */, 125 | 91FFD8941FD52A96004A1A27 /* GYNoticeViewCell.h */, 126 | 91FFD8951FD52A96004A1A27 /* GYNoticeViewCell.m */, 127 | ); 128 | path = GYRollingNoticeView; 129 | sourceTree = ""; 130 | }; 131 | /* End PBXGroup section */ 132 | 133 | /* Begin PBXNativeTarget section */ 134 | 91FFD8761FD52A36004A1A27 /* RollingNotice */ = { 135 | isa = PBXNativeTarget; 136 | buildConfigurationList = 91FFD88D1FD52A36004A1A27 /* Build configuration list for PBXNativeTarget "RollingNotice" */; 137 | buildPhases = ( 138 | 91FFD8731FD52A36004A1A27 /* Sources */, 139 | 91FFD8741FD52A36004A1A27 /* Frameworks */, 140 | 91FFD8751FD52A36004A1A27 /* Resources */, 141 | ); 142 | buildRules = ( 143 | ); 144 | dependencies = ( 145 | ); 146 | name = RollingNotice; 147 | productName = RollingNotice; 148 | productReference = 91FFD8771FD52A36004A1A27 /* RollingNotice.app */; 149 | productType = "com.apple.product-type.application"; 150 | }; 151 | /* End PBXNativeTarget section */ 152 | 153 | /* Begin PBXProject section */ 154 | 91FFD86F1FD52A36004A1A27 /* Project object */ = { 155 | isa = PBXProject; 156 | attributes = { 157 | LastUpgradeCheck = 0940; 158 | ORGANIZATIONNAME = qm; 159 | TargetAttributes = { 160 | 91FFD8761FD52A36004A1A27 = { 161 | CreatedOnToolsVersion = 9.1; 162 | ProvisioningStyle = Automatic; 163 | }; 164 | }; 165 | }; 166 | buildConfigurationList = 91FFD8721FD52A36004A1A27 /* Build configuration list for PBXProject "RollingNotice" */; 167 | compatibilityVersion = "Xcode 8.0"; 168 | developmentRegion = en; 169 | hasScannedForEncodings = 0; 170 | knownRegions = ( 171 | en, 172 | Base, 173 | ); 174 | mainGroup = 91FFD86E1FD52A36004A1A27; 175 | productRefGroup = 91FFD8781FD52A36004A1A27 /* Products */; 176 | projectDirPath = ""; 177 | projectRoot = ""; 178 | targets = ( 179 | 91FFD8761FD52A36004A1A27 /* RollingNotice */, 180 | ); 181 | }; 182 | /* End PBXProject section */ 183 | 184 | /* Begin PBXResourcesBuildPhase section */ 185 | 91FFD8751FD52A36004A1A27 /* Resources */ = { 186 | isa = PBXResourcesBuildPhase; 187 | buildActionMask = 2147483647; 188 | files = ( 189 | 919DB8131FE0F84E00029F63 /* DemoCell3.xib in Resources */, 190 | 91FFD8871FD52A36004A1A27 /* LaunchScreen.storyboard in Resources */, 191 | 91BA83E421194E8D002D2F85 /* SecondViewController.xib in Resources */, 192 | 91FFD8841FD52A36004A1A27 /* Assets.xcassets in Resources */, 193 | 916CCCA01FDA343F0070CAF3 /* CustomNoticeCell.xib in Resources */, 194 | 91FFD8821FD52A36004A1A27 /* Main.storyboard in Resources */, 195 | ); 196 | runOnlyForDeploymentPostprocessing = 0; 197 | }; 198 | /* End PBXResourcesBuildPhase section */ 199 | 200 | /* Begin PBXSourcesBuildPhase section */ 201 | 91FFD8731FD52A36004A1A27 /* Sources */ = { 202 | isa = PBXSourcesBuildPhase; 203 | buildActionMask = 2147483647; 204 | files = ( 205 | 91BA83E321194E8D002D2F85 /* SecondViewController.m in Sources */, 206 | 916CCC9E1FDA34330070CAF3 /* CustomNoticeCell.m in Sources */, 207 | B9C7FE0F2447121D0006323D /* DemoCodeAutoLayout.m in Sources */, 208 | 91FFD8961FD52A96004A1A27 /* GYNoticeViewCell.m in Sources */, 209 | 919DB80E1FE0F44600029F63 /* DemoCell2.m in Sources */, 210 | B911E5C92447331000A758F5 /* ThirdViewController.m in Sources */, 211 | 91FFD8931FD52A6F004A1A27 /* GYRollingNoticeView.m in Sources */, 212 | 91FFD87F1FD52A36004A1A27 /* ViewController.m in Sources */, 213 | 91FFD88A1FD52A36004A1A27 /* main.m in Sources */, 214 | 919DB8111FE0F84400029F63 /* DemoCell3.m in Sources */, 215 | 91FFD87C1FD52A36004A1A27 /* AppDelegate.m in Sources */, 216 | ); 217 | runOnlyForDeploymentPostprocessing = 0; 218 | }; 219 | /* End PBXSourcesBuildPhase section */ 220 | 221 | /* Begin PBXVariantGroup section */ 222 | 91FFD8801FD52A36004A1A27 /* Main.storyboard */ = { 223 | isa = PBXVariantGroup; 224 | children = ( 225 | 91FFD8811FD52A36004A1A27 /* Base */, 226 | ); 227 | name = Main.storyboard; 228 | sourceTree = ""; 229 | }; 230 | 91FFD8851FD52A36004A1A27 /* LaunchScreen.storyboard */ = { 231 | isa = PBXVariantGroup; 232 | children = ( 233 | 91FFD8861FD52A36004A1A27 /* Base */, 234 | ); 235 | name = LaunchScreen.storyboard; 236 | sourceTree = ""; 237 | }; 238 | /* End PBXVariantGroup section */ 239 | 240 | /* Begin XCBuildConfiguration section */ 241 | 91FFD88B1FD52A36004A1A27 /* Debug */ = { 242 | isa = XCBuildConfiguration; 243 | buildSettings = { 244 | ALWAYS_SEARCH_USER_PATHS = NO; 245 | CLANG_ANALYZER_NONNULL = YES; 246 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 247 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 248 | CLANG_CXX_LIBRARY = "libc++"; 249 | CLANG_ENABLE_MODULES = YES; 250 | CLANG_ENABLE_OBJC_ARC = YES; 251 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 252 | CLANG_WARN_BOOL_CONVERSION = YES; 253 | CLANG_WARN_COMMA = YES; 254 | CLANG_WARN_CONSTANT_CONVERSION = YES; 255 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 256 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 257 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 258 | CLANG_WARN_EMPTY_BODY = YES; 259 | CLANG_WARN_ENUM_CONVERSION = YES; 260 | CLANG_WARN_INFINITE_RECURSION = YES; 261 | CLANG_WARN_INT_CONVERSION = YES; 262 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 263 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 264 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 265 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 266 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 267 | CLANG_WARN_STRICT_PROTOTYPES = YES; 268 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 269 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 270 | CLANG_WARN_UNREACHABLE_CODE = YES; 271 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 272 | CODE_SIGN_IDENTITY = "iPhone Developer"; 273 | COPY_PHASE_STRIP = NO; 274 | DEBUG_INFORMATION_FORMAT = dwarf; 275 | ENABLE_STRICT_OBJC_MSGSEND = YES; 276 | ENABLE_TESTABILITY = YES; 277 | GCC_C_LANGUAGE_STANDARD = gnu11; 278 | GCC_DYNAMIC_NO_PIC = NO; 279 | GCC_NO_COMMON_BLOCKS = YES; 280 | GCC_OPTIMIZATION_LEVEL = 0; 281 | GCC_PREPROCESSOR_DEFINITIONS = ( 282 | "DEBUG=1", 283 | "$(inherited)", 284 | ); 285 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 286 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 287 | GCC_WARN_UNDECLARED_SELECTOR = YES; 288 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 289 | GCC_WARN_UNUSED_FUNCTION = YES; 290 | GCC_WARN_UNUSED_VARIABLE = YES; 291 | IPHONEOS_DEPLOYMENT_TARGET = 11.1; 292 | MTL_ENABLE_DEBUG_INFO = YES; 293 | ONLY_ACTIVE_ARCH = YES; 294 | SDKROOT = iphoneos; 295 | }; 296 | name = Debug; 297 | }; 298 | 91FFD88C1FD52A36004A1A27 /* Release */ = { 299 | isa = XCBuildConfiguration; 300 | buildSettings = { 301 | ALWAYS_SEARCH_USER_PATHS = NO; 302 | CLANG_ANALYZER_NONNULL = YES; 303 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 304 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 305 | CLANG_CXX_LIBRARY = "libc++"; 306 | CLANG_ENABLE_MODULES = YES; 307 | CLANG_ENABLE_OBJC_ARC = YES; 308 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 309 | CLANG_WARN_BOOL_CONVERSION = YES; 310 | CLANG_WARN_COMMA = YES; 311 | CLANG_WARN_CONSTANT_CONVERSION = YES; 312 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 313 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 314 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 315 | CLANG_WARN_EMPTY_BODY = YES; 316 | CLANG_WARN_ENUM_CONVERSION = YES; 317 | CLANG_WARN_INFINITE_RECURSION = YES; 318 | CLANG_WARN_INT_CONVERSION = YES; 319 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 320 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 321 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 322 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 323 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 324 | CLANG_WARN_STRICT_PROTOTYPES = YES; 325 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 326 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 327 | CLANG_WARN_UNREACHABLE_CODE = YES; 328 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 329 | CODE_SIGN_IDENTITY = "iPhone Developer"; 330 | COPY_PHASE_STRIP = NO; 331 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 332 | ENABLE_NS_ASSERTIONS = NO; 333 | ENABLE_STRICT_OBJC_MSGSEND = YES; 334 | GCC_C_LANGUAGE_STANDARD = gnu11; 335 | GCC_NO_COMMON_BLOCKS = YES; 336 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 337 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 338 | GCC_WARN_UNDECLARED_SELECTOR = YES; 339 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 340 | GCC_WARN_UNUSED_FUNCTION = YES; 341 | GCC_WARN_UNUSED_VARIABLE = YES; 342 | IPHONEOS_DEPLOYMENT_TARGET = 11.1; 343 | MTL_ENABLE_DEBUG_INFO = NO; 344 | SDKROOT = iphoneos; 345 | VALIDATE_PRODUCT = YES; 346 | }; 347 | name = Release; 348 | }; 349 | 91FFD88E1FD52A36004A1A27 /* Debug */ = { 350 | isa = XCBuildConfiguration; 351 | buildSettings = { 352 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 353 | CODE_SIGN_STYLE = Automatic; 354 | DEVELOPMENT_TEAM = 27LXXFK99P; 355 | INFOPLIST_FILE = RollingNotice/Info.plist; 356 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 357 | PRODUCT_BUNDLE_IDENTIFIER = com.qmcaifu.RollingNotice; 358 | PRODUCT_NAME = "$(TARGET_NAME)"; 359 | TARGETED_DEVICE_FAMILY = "1,2"; 360 | }; 361 | name = Debug; 362 | }; 363 | 91FFD88F1FD52A36004A1A27 /* Release */ = { 364 | isa = XCBuildConfiguration; 365 | buildSettings = { 366 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 367 | CODE_SIGN_STYLE = Automatic; 368 | DEVELOPMENT_TEAM = 27LXXFK99P; 369 | INFOPLIST_FILE = RollingNotice/Info.plist; 370 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 371 | PRODUCT_BUNDLE_IDENTIFIER = com.qmcaifu.RollingNotice; 372 | PRODUCT_NAME = "$(TARGET_NAME)"; 373 | TARGETED_DEVICE_FAMILY = "1,2"; 374 | }; 375 | name = Release; 376 | }; 377 | /* End XCBuildConfiguration section */ 378 | 379 | /* Begin XCConfigurationList section */ 380 | 91FFD8721FD52A36004A1A27 /* Build configuration list for PBXProject "RollingNotice" */ = { 381 | isa = XCConfigurationList; 382 | buildConfigurations = ( 383 | 91FFD88B1FD52A36004A1A27 /* Debug */, 384 | 91FFD88C1FD52A36004A1A27 /* Release */, 385 | ); 386 | defaultConfigurationIsVisible = 0; 387 | defaultConfigurationName = Release; 388 | }; 389 | 91FFD88D1FD52A36004A1A27 /* Build configuration list for PBXNativeTarget "RollingNotice" */ = { 390 | isa = XCConfigurationList; 391 | buildConfigurations = ( 392 | 91FFD88E1FD52A36004A1A27 /* Debug */, 393 | 91FFD88F1FD52A36004A1A27 /* Release */, 394 | ); 395 | defaultConfigurationIsVisible = 0; 396 | defaultConfigurationName = Release; 397 | }; 398 | /* End XCConfigurationList section */ 399 | }; 400 | rootObject = 91FFD86F1FD52A36004A1A27 /* Project object */; 401 | } 402 | --------------------------------------------------------------------------------