├── BarrageDemo ├── BarrageDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── BarrageDemo.xccheckout │ │ └── xcuserdata │ │ │ └── sunli.xcuserdatad │ │ │ ├── UserInterfaceState.xcuserstate │ │ │ └── WorkspaceSettings.xcsettings │ └── xcuserdata │ │ └── sunli.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── BarrageDemo.xcscheme │ │ └── xcschememanagement.plist ├── BarrageDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Barrage │ │ └── View │ │ │ ├── BarrageItemView.h │ │ │ ├── BarrageItemView.m │ │ │ ├── BarrageProtocol.h │ │ │ ├── BarrageView.h │ │ │ └── BarrageView.m │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ ├── main.m │ └── public │ │ ├── UIColor+Addition.h │ │ ├── UIColor+Addition.m │ │ ├── UIView+Metrics.h │ │ └── UIView+Metrics.m └── BarrageDemoTests │ ├── BarrageDemoTests.m │ └── Info.plist ├── GuideDemo ├── GuideDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── GuideDemo.xccheckout │ │ └── xcuserdata │ │ │ └── sunli.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── sunli.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── GuideDemo.xcscheme │ │ └── xcschememanagement.plist ├── GuideDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── GuideView.h │ ├── GuideView.m │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── arrowDown.imageset │ │ │ ├── Contents.json │ │ │ └── fx_guide_arrow_down@2x.png │ │ ├── btnMask.imageset │ │ │ ├── Contents.json │ │ │ └── fx_livRm_guide_moreItm_mask@2x.png │ │ ├── fx_my_attention_guide_arrow.imageset │ │ │ ├── Contents.json │ │ │ └── fx_my_attention_guide_arrow@2x.png │ │ ├── okBtn.imageset │ │ │ ├── Contents.json │ │ │ └── fx_livRm_guide_ok@2x.png │ │ └── whiteMask.imageset │ │ │ ├── Contents.json │ │ │ └── whiteMask@2x.png │ ├── Info.plist │ ├── UIImage+Mask.h │ ├── UIImage+Mask.m │ ├── UIView+Layout.h │ ├── UIView+Layout.m │ ├── ViewController.h │ ├── ViewController.m │ └── main.m └── GuideDemoTests │ ├── GuideDemoTests.m │ └── Info.plist ├── Socket ├── SocketApp │ ├── SocketApp.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcuserdata │ │ │ │ └── sunli.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── xcuserdata │ │ │ └── sunli.xcuserdatad │ │ │ ├── xcdebugger │ │ │ └── Breakpoints_v2.xcbkptlist │ │ │ └── xcschemes │ │ │ ├── SocketApp.xcscheme │ │ │ └── xcschememanagement.plist │ ├── SocketApp │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.xib │ │ │ └── Main.storyboard │ │ ├── Images.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── Info.plist │ │ ├── SocketHandle.h │ │ ├── SocketHandle.m │ │ ├── ViewController.h │ │ ├── ViewController.m │ │ ├── en.lproj │ │ │ └── Main.strings │ │ ├── ip │ │ │ ├── GetIpAddress.h │ │ │ ├── GetIpAddress.m │ │ │ ├── IpAddress.c │ │ │ └── IpAddress.h │ │ └── main.m │ └── SocketAppTests │ │ ├── Info.plist │ │ └── SocketAppTests.m └── SocketServer │ ├── SocketServer.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── sunli.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── sunli.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── SocketServer.xcscheme │ │ └── xcschememanagement.plist │ ├── SocketServer │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ ├── MyServer.h │ ├── MyServer.m │ ├── ViewController.h │ ├── ViewController.m │ ├── ip │ │ ├── GetIpAddress.h │ │ ├── GetIpAddress.m │ │ ├── IpAddress.c │ │ └── IpAddress.h │ └── main.m │ └── SocketServerTests │ ├── Info.plist │ └── SocketServerTests.m ├── SpringAnimation ├── SpringAnimation.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── sunli.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── sunli.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── SpringAnimation.xcscheme │ │ └── xcschememanagement.plist └── SpringAnimation │ ├── AppDelegate.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ └── ViewController.swift ├── WatchDemo ├── WatchApp Extension │ ├── Assets.xcassets │ │ └── Complication.complicationset │ │ │ ├── Circular.imageset │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ ├── Modular.imageset │ │ │ └── Contents.json │ │ │ └── Utilitarian.imageset │ │ │ └── Contents.json │ ├── ComplicationController.swift │ ├── ExtensionDelegate.swift │ ├── GlanceController.swift │ ├── ImageInterfaceController.swift │ ├── Info.plist │ ├── InterfaceController.swift │ ├── NotificationController.swift │ └── PushNotificationPayload.apns ├── WatchApp │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ └── Interface.storyboard │ ├── Info.plist │ ├── dragon-0.png │ ├── dragon-1.png │ ├── dragon-2.png │ ├── dragon-3.png │ ├── dragon-4.png │ └── dragon-5.png ├── WatchDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── sunli.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── sunli.xcuserdatad │ │ └── xcschemes │ │ ├── Complication - WatchApp.xcscheme │ │ ├── Glance - WatchApp.xcscheme │ │ ├── Notification - WatchApp.xcscheme │ │ ├── WatchApp.xcscheme │ │ ├── WatchDemo.xcscheme │ │ └── xcschememanagement.plist └── WatchDemo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ └── ViewController.swift └── iOS9 └── UITestDemo ├── UITestDemo UI Tests ├── Info.plist └── UITestDemo_UI_Tests.swift ├── UITestDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── sunli.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── sunli.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── UITestDemo.xcscheme │ └── xcschememanagement.plist └── UITestDemo ├── AppDelegate.swift ├── Assets.xcassets └── AppIcon.appiconset │ └── Contents.json ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── HomeViewController.swift ├── Info.plist ├── InfoViewController.swift ├── MessageViewController.swift └── SButton.swift /BarrageDemo/BarrageDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo.xcodeproj/project.xcworkspace/xcshareddata/BarrageDemo.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 3691C495-A016-43EB-BB0E-C773B077DCB7 9 | IDESourceControlProjectName 10 | BarrageDemo 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | AAF28B3800AAC178FEB0040B6DA855348904E4DE 14 | https://github.com/sunGd/demo 15 | 16 | IDESourceControlProjectPath 17 | BarrageDemo/BarrageDemo.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | AAF28B3800AAC178FEB0040B6DA855348904E4DE 21 | ../../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/sunGd/demo 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | AAF28B3800AAC178FEB0040B6DA855348904E4DE 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | AAF28B3800AAC178FEB0040B6DA855348904E4DE 36 | IDESourceControlWCCName 37 | demo 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo.xcodeproj/project.xcworkspace/xcuserdata/sunli.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunljz/demo/518258a6335ff8886f8c78edec5760a31204b72e/BarrageDemo/BarrageDemo.xcodeproj/project.xcworkspace/xcuserdata/sunli.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo.xcodeproj/project.xcworkspace/xcuserdata/sunli.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo.xcodeproj/xcuserdata/sunli.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo.xcodeproj/xcuserdata/sunli.xcuserdatad/xcschemes/BarrageDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo.xcodeproj/xcuserdata/sunli.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | BarrageDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | A13B92181B451234005C6645 16 | 17 | primary 18 | 19 | 20 | A13B92311B451234005C6645 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // BarrageDemo 4 | // 5 | // Created by 李剑钊 on 15/7/2. 6 | // Copyright (c) 2015年 sunli. 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 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // BarrageDemo 4 | // 5 | // Created by 李剑钊 on 15/7/2. 6 | // Copyright (c) 2015年 sunli. 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 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // 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. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo/Barrage/View/BarrageItemView.h: -------------------------------------------------------------------------------- 1 | // 2 | // BarrageItemView.h 3 | // BarrageDemo 4 | // 5 | // Created by 李剑钊 on 15/7/2. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BarrageProtocol.h" 11 | #import "UIView+Metrics.h" 12 | 13 | @interface BarrageItemView : UIView 14 | 15 | /// default = 360 16 | @property (nonatomic, assign) NSInteger maxWidth; 17 | @property (nonatomic, strong) NSString *detail; 18 | @property (nonatomic, strong) UIColor *detailColor; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo/Barrage/View/BarrageItemView.m: -------------------------------------------------------------------------------- 1 | // 2 | // BarrageItemView.m 3 | // BarrageDemo 4 | // 5 | // Created by 李剑钊 on 15/7/2. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import "BarrageItemView.h" 10 | #import "UIColor+Addition.h" 11 | 12 | @interface BarrageItemView () { 13 | CGFloat mySpeed; 14 | CGFloat myCurDistance; 15 | } 16 | 17 | @property (nonatomic, strong) UILabel *detailLabel; 18 | 19 | @end 20 | 21 | 22 | @implementation BarrageItemView 23 | 24 | #pragma mark - life cycle 25 | 26 | - (instancetype)initWithFrame:(CGRect)frame { 27 | self = [super initWithFrame:frame]; 28 | if (self) { 29 | self.maxWidth = 360; 30 | [self addSubview:self.detailLabel]; 31 | 32 | } 33 | return self; 34 | } 35 | 36 | - (void)layoutSubviews { 37 | [super layoutSubviews]; 38 | _detailLabel.frame = self.bounds; 39 | } 40 | 41 | - (void)dealloc { 42 | 43 | } 44 | 45 | #pragma mark - setter and getter 46 | 47 | - (void)setDetail:(NSString *)detail { 48 | if ([_detail isEqualToString:detail] == NO) { 49 | _detail = detail; 50 | _detailLabel.text = detail; 51 | CGSize size = [_detailLabel sizeThatFits:CGSizeMake(_maxWidth, 20)]; 52 | self.bounds = CGRectMake(0, 0, size.width, size.height); 53 | } 54 | } 55 | 56 | - (UILabel *)detailLabel { 57 | if (!_detailLabel) { 58 | UILabel *label = [[UILabel alloc] init]; 59 | label.textAlignment = NSTextAlignmentLeft; 60 | label.backgroundColor = [UIColor clearColor]; 61 | label.textColor = [UIColor colorWithHexString:@"ffffff"]; 62 | label.font = [UIFont systemFontOfSize:15]; 63 | _detailLabel = label; 64 | } 65 | return _detailLabel; 66 | } 67 | 68 | - (void)setDetailColor:(UIColor *)detailColor { 69 | _detailColor = detailColor; 70 | _detailLabel.textColor = detailColor; 71 | } 72 | 73 | - (void)setSpeed:(CGFloat)speed { 74 | mySpeed = speed; 75 | } 76 | 77 | - (CGFloat)speed { 78 | return mySpeed; 79 | } 80 | 81 | - (void)setCurDistance:(CGFloat)curDistance { 82 | myCurDistance = curDistance; 83 | } 84 | 85 | - (CGFloat)curDistance { 86 | return myCurDistance; 87 | } 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo/Barrage/View/BarrageProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // BarrageProtocol.h 3 | // BarrageDemo 4 | // 5 | // Created by 李剑钊 on 15/7/2. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #ifndef BarrageDemo_BarrageProtocol_h 10 | #define BarrageDemo_BarrageProtocol_h 11 | 12 | #import 13 | 14 | @protocol BarrageItemProtocol 15 | 16 | /// 速度 point per second 17 | @property (nonatomic, readwrite) CGFloat speed; 18 | 19 | /// 当前路程,即弹幕跑了多长 20 | @property (nonatomic, assign) CGFloat curDistance; 21 | 22 | @end 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo/Barrage/View/BarrageView.h: -------------------------------------------------------------------------------- 1 | // 2 | // BarrageAnimation.h 3 | // BarrageDemo 4 | // 5 | // Created by 李剑钊 on 15/7/2. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "BarrageProtocol.h" 12 | @class UIView; 13 | 14 | typedef NS_ENUM(NSUInteger, BarrageAnimationState) { 15 | BarrageAnimationState_stop, 16 | BarrageAnimationState_playing, 17 | BarrageAnimationState_pause, 18 | }; 19 | 20 | @class BarrageView; 21 | 22 | @protocol BarrageViewDataSource 23 | @required 24 | /// 提供弹幕视图源 25 | - (UIView *)itemForBarrage:(BarrageView *)barrage; 26 | 27 | @end 28 | 29 | @interface BarrageView : UIView 30 | 31 | /// 弹幕的行数,默认为1,开始以后,数量可以增加,但不能减少 32 | @property (nonatomic, assign) NSUInteger playSubQueueMaxCount; 33 | 34 | /// 弹幕的距离 default=16 35 | @property (nonatomic, assign) NSUInteger barrageDistance; 36 | 37 | /// 弹幕的平均速度,当旋转屏幕时,所有的正在播放的弹幕会设置成这个速度,避免出现重叠 38 | @property (nonatomic, assign) CGFloat barrageAverageSpeed; 39 | 40 | @property (nonatomic, weak) NSObject *dataSource; 41 | 42 | #pragma mark play control 43 | 44 | /// 弹幕播放状态 45 | @property (nonatomic, readonly) BarrageAnimationState state; 46 | 47 | - (BOOL)startBarrage; 48 | 49 | - (BOOL)pauseBarrage; 50 | 51 | - (BOOL)resumeBarrage; 52 | 53 | - (BOOL)stopBarrage; 54 | 55 | #pragma mark - item control 56 | 57 | /// 获取可重用的弹幕 58 | - (UIView *)dequeueReusableItem; 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.sunli.$(PRODUCT_NAME:rfc1034identifier) 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 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // BarrageDemo 4 | // 5 | // Created by 李剑钊 on 15/7/2. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // BarrageDemo 4 | // 5 | // Created by 李剑钊 on 15/7/2. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "BarrageView.h" 11 | #import "UIView+Metrics.h" 12 | #import "BarrageItemView.h" 13 | 14 | @interface ViewController () 15 | 16 | @property (nonatomic, strong) BarrageView *barrageView; 17 | @property (nonatomic, strong) UIView *parentView; 18 | 19 | @property (nonatomic, strong) NSMutableArray *messagePool; 20 | 21 | @end 22 | 23 | @implementation ViewController 24 | 25 | - (void)viewDidLoad { 26 | [super viewDidLoad]; 27 | // Do any additional setup after loading the view, typically from a nib. 28 | 29 | self.view.backgroundColor = [UIColor whiteColor]; 30 | self.messagePool = [NSMutableArray array]; 31 | 32 | _parentView = [[UIView alloc] initWithFrame:CGRectMake(0, 20, self.view.width, 150)]; 33 | [self.view insertSubview:_parentView atIndex:0]; 34 | 35 | BarrageView *barrage = [[BarrageView alloc] initWithFrame:_parentView.bounds]; 36 | barrage.dataSource = self; 37 | barrage.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 38 | barrage.playSubQueueMaxCount = 3; 39 | barrage.backgroundColor = [UIColor blackColor]; 40 | barrage.barrageAverageSpeed = 80; 41 | [_parentView addSubview:barrage]; 42 | _barrageView = barrage; 43 | } 44 | 45 | - (void)didReceiveMemoryWarning { 46 | [super didReceiveMemoryWarning]; 47 | // Dispose of any resources that can be recreated. 48 | } 49 | 50 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 51 | static NSInteger type = 0; 52 | for (NSInteger i = 0; i < 50; i ++) { 53 | NSString *title = nil; 54 | if (type == 0) { 55 | type = 1; 56 | title = @"1shihiaognaihoi"; 57 | } else if (type == 1) { 58 | type = 2; 59 | title = @"HenHenH"; 60 | } else if (type == 2) { 61 | type = 3; 62 | title = @"_@#!+-"; 63 | } else if (type == 3) { 64 | type = 4; 65 | title = @"嘻嘻呵呵哈哈嘎嘎"; 66 | } else { 67 | type = 0; 68 | title = @"10759651235215662164322346321523512"; 69 | } 70 | 71 | [_messagePool addObject:title]; 72 | } 73 | } 74 | 75 | - (IBAction)sendBtnTouch:(id)sender { 76 | [_messagePool addObject:@"我的消息"]; 77 | } 78 | 79 | - (IBAction)buttonTouched:(id)sender { 80 | static BOOL rotate = NO; 81 | [UIView animateWithDuration:0.2 animations:^{ 82 | if (rotate == NO) { 83 | rotate = YES; 84 | _parentView.size = CGSizeMake(self.view.height, 100); 85 | _parentView.center = CGPointMake(self.view.width/2, self.view.height/2); 86 | _parentView.transform = CGAffineTransformMakeRotation(M_PI/2); 87 | } else { 88 | rotate = NO; 89 | _parentView.transform = CGAffineTransformIdentity; 90 | _parentView.size = CGSizeMake(self.view.width, 150); 91 | _parentView.origin = CGPointMake(0, 20); 92 | } 93 | } completion:nil]; 94 | } 95 | 96 | - (IBAction)pauseBtnTouch:(id)sender { 97 | [_barrageView pauseBarrage]; 98 | } 99 | - (IBAction)resumeBtnTouch:(id)sender { 100 | [_barrageView resumeBarrage]; 101 | } 102 | 103 | - (IBAction)startBtnTouch:(id)sender { 104 | [_barrageView startBarrage]; 105 | } 106 | 107 | - (IBAction)stopBtnTouch:(id)sender { 108 | [_barrageView stopBarrage]; 109 | [_messagePool removeAllObjects]; 110 | } 111 | 112 | - (IBAction)removeBtnTouch:(id)sender { 113 | [_barrageView stopBarrage]; 114 | _barrageView.dataSource = nil; 115 | [_barrageView removeFromSuperview]; 116 | self.barrageView = nil; 117 | [_messagePool removeAllObjects]; 118 | } 119 | 120 | #pragma mark - BarrageViewDataSource 121 | 122 | - (UIView *)itemForBarrage:(BarrageView *)barrage { 123 | NSString *title = [_messagePool firstObject]; 124 | if (title) { 125 | [_messagePool removeObjectAtIndex:0]; 126 | 127 | BarrageItemView *item = (BarrageItemView *)[barrage dequeueReusableItem]; 128 | if (!item) { 129 | item = [BarrageItemView new]; 130 | } 131 | item.speed = 80; 132 | BOOL highSpeed = (arc4random_uniform((int32_t)time(NULL)) % 100) < 10; 133 | if (highSpeed) { 134 | item.speed = 120; 135 | } 136 | 137 | item.detail = title; 138 | return item; 139 | } 140 | return nil; 141 | } 142 | 143 | @end 144 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // BarrageDemo 4 | // 5 | // Created by 李剑钊 on 15/7/2. 6 | // Copyright (c) 2015年 sunli. 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 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo/public/UIColor+Addition.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+Addition.h 3 | // QiaoQiaoMovie 4 | // 5 | // Created by zelong zou on 13-3-17. 6 | // Copyright (c) 2013年 prdoor. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | #define RGBACOLOR(r,g,b,a) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:(a)] 13 | 14 | @interface UIColor (Addition) 15 | + (UIColor *) colorWithHexString: (NSString *) stringToConvert; 16 | + (UIColor *) colorWithHexString: (NSString *) stringToConvert alpha:(float) alpha; 17 | //颜色转字符串 18 | - (NSString *) changeUIColorToRGB; 19 | @end 20 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo/public/UIColor+Addition.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+Addition.m 3 | // QiaoQiaoMovie 4 | // 5 | // Created by zelong zou on 13-3-17. 6 | // Copyright (c) 2013年 prdoor. All rights reserved. 7 | // 8 | 9 | #import "UIColor+Addition.h" 10 | #define DEFAULT_VOID_COLOR [UIColor clearColor] 11 | @implementation UIColor (Addition) 12 | 13 | + (UIColor *) colorWithHexString: (NSString *) stringToConvert 14 | { 15 | NSString *cString = [[stringToConvert stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString]; 16 | 17 | // String should be 6 or 8 characters 18 | if ([cString length] < 6) return DEFAULT_VOID_COLOR; 19 | 20 | // strip 0X if it appears 21 | if ([cString hasPrefix:@"0X"]) cString = [cString substringFromIndex:2]; 22 | if ([cString hasPrefix:@"#"]) cString = [cString substringFromIndex:1]; 23 | if ([cString length] != 6) return DEFAULT_VOID_COLOR; 24 | // Separate into r, g, b substrings 25 | NSRange range; 26 | range.location = 0; 27 | range.length = 2; 28 | NSString *rString = [cString substringWithRange:range]; 29 | 30 | range.location = 2; 31 | NSString *gString = [cString substringWithRange:range]; 32 | 33 | range.location = 4; 34 | NSString *bString = [cString substringWithRange:range]; 35 | 36 | // Scan values 37 | unsigned int r, g, b; 38 | [[NSScanner scannerWithString:rString] scanHexInt:&r]; 39 | [[NSScanner scannerWithString:gString] scanHexInt:&g]; 40 | [[NSScanner scannerWithString:bString] scanHexInt:&b]; 41 | 42 | return [UIColor colorWithRed:((float) r / 255.0f) 43 | green:((float) g / 255.0f) 44 | blue:((float) b / 255.0f) 45 | alpha:1.0f]; 46 | } 47 | 48 | + (UIColor *) colorWithHexString: (NSString *) stringToConvert alpha:(float) alpha 49 | { 50 | NSString *cString = [[stringToConvert stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString]; 51 | 52 | // String should be 6 or 8 characters 53 | if ([cString length] < 6) return DEFAULT_VOID_COLOR; 54 | 55 | // strip 0X if it appears 56 | if ([cString hasPrefix:@"0X"]) cString = [cString substringFromIndex:2]; 57 | if ([cString hasPrefix:@"#"]) cString = [cString substringFromIndex:1]; 58 | if ([cString length] != 6) return DEFAULT_VOID_COLOR; 59 | // Separate into r, g, b substrings 60 | NSRange range; 61 | range.location = 0; 62 | range.length = 2; 63 | NSString *rString = [cString substringWithRange:range]; 64 | 65 | range.location = 2; 66 | NSString *gString = [cString substringWithRange:range]; 67 | 68 | range.location = 4; 69 | NSString *bString = [cString substringWithRange:range]; 70 | 71 | // Scan values 72 | unsigned int r, g, b; 73 | [[NSScanner scannerWithString:rString] scanHexInt:&r]; 74 | [[NSScanner scannerWithString:gString] scanHexInt:&g]; 75 | [[NSScanner scannerWithString:bString] scanHexInt:&b]; 76 | 77 | return [UIColor colorWithRed:((float) r / 255.0f) 78 | green:((float) g / 255.0f) 79 | blue:((float) b / 255.0f) 80 | alpha:alpha]; 81 | } 82 | 83 | //颜色转字符串 84 | - (NSString *) changeUIColorToRGB{ 85 | 86 | 87 | const CGFloat *cs=CGColorGetComponents(self.CGColor); 88 | 89 | 90 | NSString *r = [NSString stringWithFormat:@"%@",[self ToHex:cs[0]*255]]; 91 | NSString *g = [NSString stringWithFormat:@"%@",[self ToHex:cs[1]*255]]; 92 | NSString *b = [NSString stringWithFormat:@"%@",[self ToHex:cs[2]*255]]; 93 | return [NSString stringWithFormat:@"#%@%@%@",r,g,b]; 94 | } 95 | 96 | 97 | //十进制转十六进制 98 | -(NSString *)ToHex:(int)tmpid 99 | { 100 | NSString *endtmp=@""; 101 | NSString *nLetterValue; 102 | NSString *nStrat; 103 | int ttmpig=tmpid%16; 104 | int tmp=tmpid/16; 105 | switch (ttmpig) 106 | { 107 | case 10: 108 | nLetterValue =@"A";break; 109 | case 11: 110 | nLetterValue =@"B";break; 111 | case 12: 112 | nLetterValue =@"C";break; 113 | case 13: 114 | nLetterValue =@"D";break; 115 | case 14: 116 | nLetterValue =@"E";break; 117 | case 15: 118 | nLetterValue =@"F";break; 119 | default:nLetterValue=[[NSString alloc]initWithFormat:@"%i",ttmpig]; 120 | 121 | } 122 | switch (tmp) 123 | { 124 | case 10: 125 | nStrat =@"A";break; 126 | case 11: 127 | nStrat =@"B";break; 128 | case 12: 129 | nStrat =@"C";break; 130 | case 13: 131 | nStrat =@"D";break; 132 | case 14: 133 | nStrat =@"E";break; 134 | case 15: 135 | nStrat =@"F";break; 136 | default:nStrat=[[NSString alloc]initWithFormat:@"%i",tmp]; 137 | 138 | } 139 | endtmp=[[NSString alloc]initWithFormat:@"%@%@",nStrat,nLetterValue]; 140 | return endtmp; 141 | } 142 | 143 | @end 144 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo/public/UIView+Metrics.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Metrics.h 3 | // NeeFrame 4 | // 5 | // Created by ganvin on 14-4-14. 6 | // Copyright (c) 2014年 ganvin. All rights reserved. 7 | // 8 | 9 | #import 10 | /** 11 | * 方便的访问和设置View的属性 12 | */ 13 | @interface UIView (Metrics) 14 | 15 | @property (assign, nonatomic) CGFloat top; 16 | @property (assign, nonatomic) CGFloat bottom; 17 | @property (assign, nonatomic) CGFloat left; 18 | @property (assign, nonatomic) CGFloat right; 19 | 20 | @property (assign, nonatomic) CGPoint offset; 21 | @property (assign, nonatomic) CGPoint position; 22 | 23 | @property (assign, nonatomic) CGFloat x; 24 | @property (assign, nonatomic) CGFloat y; 25 | @property (assign, nonatomic) CGFloat w; 26 | @property (assign, nonatomic) CGFloat h; 27 | 28 | @property (assign, nonatomic) CGFloat width; 29 | @property (assign, nonatomic) CGFloat height; 30 | @property (assign, nonatomic) CGSize size; 31 | 32 | @property (assign, nonatomic) CGFloat centerX; 33 | @property (assign, nonatomic) CGFloat centerY; 34 | @property (assign, nonatomic) CGPoint origin; 35 | @property (readonly, nonatomic) CGPoint boundsCenter; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemo/public/UIView+Metrics.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Metrics.m 3 | // NeeFrame 4 | // 5 | // Created by ganvin on 14-4-14. 6 | // Copyright (c) 2014年 ganvin. All rights reserved. 7 | // 8 | 9 | #import "UIView+Metrics.h" 10 | 11 | @implementation UIView (Metrics) 12 | 13 | @dynamic top; 14 | @dynamic bottom; 15 | @dynamic left; 16 | @dynamic right; 17 | 18 | @dynamic width; 19 | @dynamic height; 20 | 21 | @dynamic offset; 22 | @dynamic position; 23 | @dynamic size; 24 | 25 | @dynamic x; 26 | @dynamic y; 27 | @dynamic w; 28 | @dynamic h; 29 | 30 | - (CGFloat)top 31 | { 32 | return self.frame.origin.y; 33 | } 34 | 35 | - (void)setTop:(CGFloat)top 36 | { 37 | CGRect frame = self.frame; 38 | frame.origin.y = top; 39 | self.frame = frame; 40 | } 41 | 42 | - (CGFloat)left 43 | { 44 | return self.frame.origin.x; 45 | } 46 | 47 | - (void)setLeft:(CGFloat)left 48 | { 49 | CGRect frame = self.frame; 50 | frame.origin.x = left; 51 | self.frame = frame; 52 | } 53 | 54 | - (CGFloat)width 55 | { 56 | return self.frame.size.width; 57 | } 58 | 59 | - (void)setWidth:(CGFloat)width 60 | { 61 | CGRect frame = self.frame; 62 | frame.size.width = width; 63 | self.frame = frame; 64 | } 65 | 66 | - (CGFloat)height 67 | { 68 | return self.frame.size.height; 69 | } 70 | 71 | - (void)setHeight:(CGFloat)height 72 | { 73 | CGRect frame = self.frame; 74 | frame.size.height = height; 75 | self.frame = frame; 76 | } 77 | 78 | - (CGFloat)bottom 79 | { 80 | return self.frame.size.height + self.frame.origin.y; 81 | } 82 | 83 | - (void)setBottom:(CGFloat)bottom 84 | { 85 | CGRect frame = self.frame; 86 | frame.origin.y = bottom - frame.size.height; 87 | self.frame = frame; 88 | } 89 | 90 | - (CGFloat)right 91 | { 92 | return self.frame.size.width + self.frame.origin.x; 93 | } 94 | 95 | - (void)setRight:(CGFloat)right 96 | { 97 | CGRect frame = self.frame; 98 | frame.origin.x = right - frame.size.width; 99 | self.frame = frame; 100 | } 101 | 102 | - (CGFloat)x 103 | { 104 | return self.frame.origin.x; 105 | } 106 | 107 | - (void)setX:(CGFloat)value 108 | { 109 | CGRect frame = self.frame; 110 | frame.origin.x = value; 111 | self.frame = frame; 112 | } 113 | 114 | - (CGFloat)y 115 | { 116 | return self.frame.origin.y; 117 | } 118 | 119 | - (void)setY:(CGFloat)value 120 | { 121 | CGRect frame = self.frame; 122 | frame.origin.y = value; 123 | self.frame = frame; 124 | } 125 | 126 | - (CGFloat)w 127 | { 128 | return self.frame.size.width; 129 | } 130 | 131 | - (void)setW:(CGFloat)width 132 | { 133 | CGRect frame = self.frame; 134 | frame.size.width = width; 135 | self.frame = frame; 136 | } 137 | 138 | - (CGFloat)h 139 | { 140 | return self.frame.size.height; 141 | } 142 | 143 | - (void)setH:(CGFloat)height 144 | { 145 | CGRect frame = self.frame; 146 | frame.size.height = height; 147 | self.frame = frame; 148 | } 149 | 150 | - (CGPoint)offset 151 | { 152 | CGPoint point = CGPointZero; 153 | UIView * view = self; 154 | 155 | while ( view ) 156 | { 157 | point.x += view.frame.origin.x; 158 | point.y += view.frame.origin.y; 159 | 160 | view = view.superview; 161 | } 162 | 163 | return point; 164 | } 165 | 166 | - (void)setOffset:(CGPoint)offset 167 | { 168 | UIView * view = self; 169 | if ( nil == view ) 170 | return; 171 | 172 | CGPoint point = offset; 173 | 174 | while ( view ) 175 | { 176 | point.x += view.superview.frame.origin.x; 177 | point.y += view.superview.frame.origin.y; 178 | 179 | view = view.superview; 180 | } 181 | 182 | CGRect frame = self.frame; 183 | frame.origin = point; 184 | self.frame = frame; 185 | } 186 | 187 | - (CGPoint)position 188 | { 189 | return self.frame.origin; 190 | } 191 | 192 | - (void)setPosition:(CGPoint)pos 193 | { 194 | CGRect frame = self.frame; 195 | frame.origin = pos; 196 | self.frame = frame; 197 | } 198 | 199 | - (CGSize)size 200 | { 201 | return self.frame.size; 202 | } 203 | 204 | - (void)setSize:(CGSize)size 205 | { 206 | CGRect frame = self.frame; 207 | frame.size = size; 208 | self.frame = frame; 209 | } 210 | 211 | - (CGFloat)centerX 212 | { 213 | return self.center.x; 214 | } 215 | 216 | - (void)setCenterX:(CGFloat)centerX 217 | { 218 | CGPoint center = self.center; 219 | center.x = centerX; 220 | self.center = center; 221 | } 222 | 223 | - (CGFloat)centerY 224 | { 225 | return self.center.y; 226 | } 227 | 228 | - (void)setCenterY:(CGFloat)centerY 229 | { 230 | CGPoint center = self.center; 231 | center.y = centerY; 232 | self.center = center; 233 | } 234 | 235 | - (CGPoint)origin 236 | { 237 | return self.frame.origin; 238 | } 239 | 240 | - (void)setOrigin:(CGPoint)origin 241 | { 242 | CGRect frame = self.frame; 243 | frame.origin = origin; 244 | self.frame = frame; 245 | } 246 | 247 | - (CGPoint)boundsCenter 248 | { 249 | return CGPointMake( CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds) ); 250 | } 251 | 252 | @end 253 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemoTests/BarrageDemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // BarrageDemoTests.m 3 | // BarrageDemoTests 4 | // 5 | // Created by 李剑钊 on 15/7/2. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface BarrageDemoTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation BarrageDemoTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /BarrageDemo/BarrageDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.sunli.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemo.xcodeproj/project.xcworkspace/xcshareddata/GuideDemo.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | D88DF8DD-7A75-4FD6-9645-E0C3716C090E 9 | IDESourceControlProjectName 10 | GuideDemo 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | AAF28B3800AAC178FEB0040B6DA855348904E4DE 14 | https://github.com/sunljz/demo 15 | 16 | IDESourceControlProjectPath 17 | GuideDemo/GuideDemo.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | AAF28B3800AAC178FEB0040B6DA855348904E4DE 21 | ../../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/sunljz/demo 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | AAF28B3800AAC178FEB0040B6DA855348904E4DE 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | AAF28B3800AAC178FEB0040B6DA855348904E4DE 36 | IDESourceControlWCCName 37 | demo 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemo.xcodeproj/project.xcworkspace/xcuserdata/sunli.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunljz/demo/518258a6335ff8886f8c78edec5760a31204b72e/GuideDemo/GuideDemo.xcodeproj/project.xcworkspace/xcuserdata/sunli.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /GuideDemo/GuideDemo.xcodeproj/xcuserdata/sunli.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemo.xcodeproj/xcuserdata/sunli.xcuserdatad/xcschemes/GuideDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemo.xcodeproj/xcuserdata/sunli.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | GuideDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | A10662F01B60C98D00B32E9E 16 | 17 | primary 18 | 19 | 20 | A10663091B60C98E00B32E9E 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // GuideDemo 4 | // 5 | // Created by 李剑钊 on 15/7/23. 6 | // Copyright (c) 2015年 sunli. 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 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // GuideDemo 4 | // 5 | // Created by 李剑钊 on 15/7/23. 6 | // Copyright (c) 2015年 sunli. 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 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // 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. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 21 | 22 | 23 | 24 | 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 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/GuideView.h: -------------------------------------------------------------------------------- 1 | // 2 | // GuideView.h 3 | // GuideDemo 4 | // 5 | // Created by 李剑钊 on 15/7/23. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface GuideView : UIView 12 | 13 | - (void)showInView:(UIView *)view maskBtn:(UIButton *)btn; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/Images.xcassets/arrowDown.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "fx_guide_arrow_down@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/Images.xcassets/arrowDown.imageset/fx_guide_arrow_down@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunljz/demo/518258a6335ff8886f8c78edec5760a31204b72e/GuideDemo/GuideDemo/Images.xcassets/arrowDown.imageset/fx_guide_arrow_down@2x.png -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/Images.xcassets/btnMask.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "fx_livRm_guide_moreItm_mask@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/Images.xcassets/btnMask.imageset/fx_livRm_guide_moreItm_mask@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunljz/demo/518258a6335ff8886f8c78edec5760a31204b72e/GuideDemo/GuideDemo/Images.xcassets/btnMask.imageset/fx_livRm_guide_moreItm_mask@2x.png -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/Images.xcassets/fx_my_attention_guide_arrow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "fx_my_attention_guide_arrow@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/Images.xcassets/fx_my_attention_guide_arrow.imageset/fx_my_attention_guide_arrow@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunljz/demo/518258a6335ff8886f8c78edec5760a31204b72e/GuideDemo/GuideDemo/Images.xcassets/fx_my_attention_guide_arrow.imageset/fx_my_attention_guide_arrow@2x.png -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/Images.xcassets/okBtn.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "fx_livRm_guide_ok@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/Images.xcassets/okBtn.imageset/fx_livRm_guide_ok@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunljz/demo/518258a6335ff8886f8c78edec5760a31204b72e/GuideDemo/GuideDemo/Images.xcassets/okBtn.imageset/fx_livRm_guide_ok@2x.png -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/Images.xcassets/whiteMask.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "whiteMask@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/Images.xcassets/whiteMask.imageset/whiteMask@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunljz/demo/518258a6335ff8886f8c78edec5760a31204b72e/GuideDemo/GuideDemo/Images.xcassets/whiteMask.imageset/whiteMask@2x.png -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.sunli.$(PRODUCT_NAME:rfc1034identifier) 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 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/UIImage+Mask.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Mask.h 3 | // GuideDemo 4 | // 5 | // Created by 李剑钊 on 15/7/24. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImage (Mask) 12 | 13 | - (UIImage *)maskImage:(UIColor *)maskColor; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/UIImage+Mask.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Mask.m 3 | // GuideDemo 4 | // 5 | // Created by 李剑钊 on 15/7/24. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import "UIImage+Mask.h" 10 | 11 | @implementation UIImage (Mask) 12 | 13 | - (UIImage *)maskImage:(UIColor *)maskColor 14 | { 15 | CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height); 16 | 17 | UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0); 18 | 19 | CGContextRef context = UIGraphicsGetCurrentContext(); 20 | CGContextTranslateCTM(context, 0, rect.size.height); 21 | CGContextScaleCTM(context, 1.0, -1.0); 22 | CGContextClipToMask(context, rect, self.CGImage); 23 | CGContextSetFillColorWithColor(context, maskColor.CGColor); 24 | CGContextFillRect(context, rect); 25 | 26 | UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext(); 27 | 28 | UIGraphicsEndImageContext(); 29 | 30 | return smallImage; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/UIView+Layout.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Metrics.h 3 | // NeeFrame 4 | // 5 | // Created by 李剑钊 on 15/7/24. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import 10 | /** 11 | * 方便的访问和设置View的属性 12 | */ 13 | @interface UIView (Layout) 14 | 15 | @property (assign, nonatomic) CGFloat top; 16 | @property (assign, nonatomic) CGFloat bottom; 17 | @property (assign, nonatomic) CGFloat left; 18 | @property (assign, nonatomic) CGFloat right; 19 | 20 | @property (assign, nonatomic) CGFloat x; 21 | @property (assign, nonatomic) CGFloat y; 22 | @property (assign, nonatomic) CGPoint origin; 23 | 24 | @property (assign, nonatomic) CGFloat centerX; 25 | @property (assign, nonatomic) CGFloat centerY; 26 | 27 | @property (assign, nonatomic) CGFloat width; 28 | @property (assign, nonatomic) CGFloat height; 29 | @property (assign, nonatomic) CGSize size; 30 | 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/UIView+Layout.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Metrics.m 3 | // NeeFrame 4 | // 5 | // Created by 李剑钊 on 15/7/24. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import "UIView+Layout.h" 10 | 11 | @implementation UIView (Layout) 12 | 13 | @dynamic top; 14 | @dynamic bottom; 15 | @dynamic left; 16 | @dynamic right; 17 | 18 | @dynamic width; 19 | @dynamic height; 20 | 21 | @dynamic size; 22 | 23 | @dynamic x; 24 | @dynamic y; 25 | 26 | - (CGFloat)top 27 | { 28 | return self.frame.origin.y; 29 | } 30 | 31 | - (void)setTop:(CGFloat)top 32 | { 33 | CGRect frame = self.frame; 34 | frame.origin.y = top; 35 | self.frame = frame; 36 | } 37 | 38 | - (CGFloat)left 39 | { 40 | return self.frame.origin.x; 41 | } 42 | 43 | - (void)setLeft:(CGFloat)left 44 | { 45 | CGRect frame = self.frame; 46 | frame.origin.x = left; 47 | self.frame = frame; 48 | } 49 | 50 | - (CGFloat)bottom 51 | { 52 | return self.frame.size.height + self.frame.origin.y; 53 | } 54 | 55 | - (void)setBottom:(CGFloat)bottom 56 | { 57 | CGRect frame = self.frame; 58 | frame.origin.y = bottom - frame.size.height; 59 | self.frame = frame; 60 | } 61 | 62 | - (CGFloat)right 63 | { 64 | return self.frame.size.width + self.frame.origin.x; 65 | } 66 | 67 | - (void)setRight:(CGFloat)right 68 | { 69 | CGRect frame = self.frame; 70 | frame.origin.x = right - frame.size.width; 71 | self.frame = frame; 72 | } 73 | 74 | - (CGFloat)x 75 | { 76 | return self.frame.origin.x; 77 | } 78 | 79 | - (void)setX:(CGFloat)value 80 | { 81 | CGRect frame = self.frame; 82 | frame.origin.x = value; 83 | self.frame = frame; 84 | } 85 | 86 | - (CGFloat)y 87 | { 88 | return self.frame.origin.y; 89 | } 90 | 91 | - (void)setY:(CGFloat)value 92 | { 93 | CGRect frame = self.frame; 94 | frame.origin.y = value; 95 | self.frame = frame; 96 | } 97 | 98 | - (CGPoint)origin 99 | { 100 | return self.frame.origin; 101 | } 102 | 103 | - (void)setOrigin:(CGPoint)origin 104 | { 105 | CGRect frame = self.frame; 106 | frame.origin = origin; 107 | self.frame = frame; 108 | } 109 | 110 | - (CGFloat)centerX 111 | { 112 | return self.center.x; 113 | } 114 | 115 | - (void)setCenterX:(CGFloat)centerX 116 | { 117 | CGPoint center = self.center; 118 | center.x = centerX; 119 | self.center = center; 120 | } 121 | 122 | - (CGFloat)centerY 123 | { 124 | return self.center.y; 125 | } 126 | 127 | - (void)setCenterY:(CGFloat)centerY 128 | { 129 | CGPoint center = self.center; 130 | center.y = centerY; 131 | self.center = center; 132 | } 133 | 134 | - (CGFloat)width 135 | { 136 | return self.frame.size.width; 137 | } 138 | 139 | - (void)setWidth:(CGFloat)width 140 | { 141 | CGRect frame = self.frame; 142 | frame.size.width = width; 143 | self.frame = frame; 144 | } 145 | 146 | - (CGFloat)height 147 | { 148 | return self.frame.size.height; 149 | } 150 | 151 | - (void)setHeight:(CGFloat)height 152 | { 153 | CGRect frame = self.frame; 154 | frame.size.height = height; 155 | self.frame = frame; 156 | } 157 | 158 | - (CGSize)size 159 | { 160 | return self.frame.size; 161 | } 162 | 163 | - (void)setSize:(CGSize)size 164 | { 165 | CGRect frame = self.frame; 166 | frame.size = size; 167 | self.frame = frame; 168 | } 169 | 170 | @end 171 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // GuideDemo 4 | // 5 | // Created by 李剑钊 on 15/7/23. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // GuideDemo 4 | // 5 | // Created by 李剑钊 on 15/7/23. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "UIView+Layout.h" 11 | #import "GuideView.h" 12 | 13 | @interface ViewController () 14 | 15 | @property (weak, nonatomic) IBOutlet UITextView *textView; 16 | @property (weak, nonatomic) IBOutlet UIButton *button; 17 | 18 | @end 19 | 20 | @implementation ViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | // Do any additional setup after loading the view, typically from a nib. 25 | } 26 | 27 | - (void)didReceiveMemoryWarning { 28 | [super didReceiveMemoryWarning]; 29 | // Dispose of any resources that can be recreated. 30 | } 31 | 32 | - (void)viewDidAppear:(BOOL)animated { 33 | GuideView *guide = [GuideView new]; 34 | [guide showInView:self.view maskBtn:self.button]; 35 | } 36 | 37 | - (void)viewWillLayoutSubviews { 38 | _textView.left = 8; 39 | _textView.top = 60; 40 | _textView.width = self.view.width - 16; 41 | _textView.height = self.view.height - 210; 42 | 43 | _button.centerX = self.view.width/2; 44 | _button.top = _textView.bottom + 16; 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // GuideDemo 4 | // 5 | // Created by 李剑钊 on 15/7/23. 6 | // Copyright (c) 2015年 sunli. 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 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemoTests/GuideDemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // GuideDemoTests.m 3 | // GuideDemoTests 4 | // 5 | // Created by 李剑钊 on 15/7/23. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface GuideDemoTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation GuideDemoTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /GuideDemo/GuideDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.sunli.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Socket/SocketApp/SocketApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Socket/SocketApp/SocketApp.xcodeproj/project.xcworkspace/xcuserdata/sunli.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunljz/demo/518258a6335ff8886f8c78edec5760a31204b72e/Socket/SocketApp/SocketApp.xcodeproj/project.xcworkspace/xcuserdata/sunli.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Socket/SocketApp/SocketApp.xcodeproj/xcuserdata/sunli.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /Socket/SocketApp/SocketApp.xcodeproj/xcuserdata/sunli.xcuserdatad/xcschemes/SocketApp.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /Socket/SocketApp/SocketApp.xcodeproj/xcuserdata/sunli.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SocketApp.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | A1D39B901B2EE46400B56E57 16 | 17 | primary 18 | 19 | 20 | A1D39BA91B2EE46400B56E57 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Socket/SocketApp/SocketApp/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // SocketApp 4 | // 5 | // Created by 李剑钊 on 15/6/15. 6 | // Copyright (c) 2015年 sunli. 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 | -------------------------------------------------------------------------------- /Socket/SocketApp/SocketApp/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // SocketApp 4 | // 5 | // Created by 李剑钊 on 15/6/15. 6 | // Copyright (c) 2015年 sunli. 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 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // 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. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Socket/SocketApp/SocketApp/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Socket/SocketApp/SocketApp/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /Socket/SocketApp/SocketApp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.kugou.$(PRODUCT_NAME:rfc1034identifier) 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 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Socket/SocketApp/SocketApp/SocketHandle.h: -------------------------------------------------------------------------------- 1 | // 2 | // SocketHandle.h 3 | // SocketApp 4 | // 5 | // Created by 李剑钊 on 15/6/15. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol SocketDelegate 12 | @optional 13 | - (void)socketDidReceiveText:(NSString *)text; 14 | 15 | @end 16 | 17 | @interface SocketHandle : NSObject 18 | 19 | @property (nonatomic, assign, readonly) BOOL isSocketOpened; 20 | @property (nonatomic, weak) iddelegate; 21 | 22 | - (void)initSocket:(NSString *)serverIp; 23 | 24 | - (void)sendData:(NSString *)str; 25 | 26 | - (void)closeSocket; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Socket/SocketApp/SocketApp/SocketHandle.m: -------------------------------------------------------------------------------- 1 | // 2 | // SocketHandle.m 3 | // SocketApp 4 | // 5 | // Created by 李剑钊 on 15/6/15. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import "SocketHandle.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define PORT 6677 19 | 20 | @interface SocketHandle () { 21 | 22 | } 23 | 24 | @property (nonatomic, assign) BOOL isIniting; 25 | @property (nonatomic, assign) int app_socket; 26 | 27 | @end 28 | 29 | @implementation SocketHandle 30 | 31 | - (instancetype)init 32 | { 33 | self = [super init]; 34 | if (self) { 35 | 36 | } 37 | return self; 38 | } 39 | 40 | - (void)initSocket:(NSString *)serverIp { 41 | if (_isIniting) { 42 | return; 43 | } else if (_isSocketOpened) { 44 | return; 45 | } 46 | 47 | self.isIniting = YES; 48 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 49 | NSString *host = serverIp; 50 | 51 | // 创建socket 52 | int app_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 53 | if (app_socket < 0) { 54 | NSLog(@"create socket failed"); 55 | return; 56 | } 57 | self.app_socket = app_socket; 58 | 59 | struct hostent *remoteHostEnt = gethostbyname([host UTF8String]); 60 | if (remoteHostEnt == NULL) { 61 | NSLog(@"host name is error"); 62 | return; 63 | } 64 | struct in_addr *remoteInAddr = (struct in_addr *)remoteHostEnt->h_addr_list[0]; 65 | // 服务器socket地址结构 66 | struct sockaddr_in server_addr; 67 | bzero(&server_addr, sizeof(server_addr)); 68 | server_addr.sin_family = AF_INET; 69 | server_addr.sin_addr.s_addr = remoteInAddr->s_addr; 70 | server_addr.sin_port = htons(PORT); 71 | int connect_result = connect(app_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)); 72 | if (connect_result < 0) { 73 | NSLog(@"connect error"); 74 | return; 75 | } 76 | 77 | _isSocketOpened = YES; 78 | _isIniting = NO; 79 | 80 | while (_isSocketOpened) { 81 | char buffer[30000]; 82 | int lenght = sizeof(buffer); 83 | 84 | ssize_t result = recv(app_socket, buffer, 30000, 0); 85 | if (result > 0) { 86 | [self didReceiveBuffer:(const char *)buffer]; 87 | NSLog(@"receive data:%s",buffer); 88 | } else { 89 | NSLog(@"receive data failed"); 90 | } 91 | } 92 | [self closeSocket]; 93 | }); 94 | } 95 | 96 | - (void)sendData:(NSString *)str { 97 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 98 | const char *buffer = [str UTF8String]; 99 | ssize_t result = send(_app_socket, buffer, strlen(buffer), 0); 100 | if (result > 0) { 101 | NSLog(@"send data success"); 102 | } else { 103 | NSLog(@"send data failed"); 104 | } 105 | }); 106 | } 107 | 108 | - (void)didReceiveBuffer:(const char *)buffer { 109 | NSString *text = [NSString stringWithCString:buffer encoding:NSUTF8StringEncoding]; 110 | if ([_delegate respondsToSelector:@selector(socketDidReceiveText:)]) { 111 | if ([NSThread isMainThread]) { 112 | [_delegate socketDidReceiveText:text]; 113 | } else { 114 | dispatch_async(dispatch_get_main_queue(), ^{ 115 | [_delegate socketDidReceiveText:text]; 116 | }); 117 | } 118 | } 119 | } 120 | 121 | - (void)closeSocket { 122 | if (_isSocketOpened) { 123 | close(_app_socket); 124 | _isSocketOpened = NO; 125 | _isIniting = NO; 126 | } 127 | } 128 | 129 | @end 130 | -------------------------------------------------------------------------------- /Socket/SocketApp/SocketApp/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // SocketApp 4 | // 5 | // Created by 李剑钊 on 15/6/15. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Socket/SocketApp/SocketApp/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // SocketApp 4 | // 5 | // Created by 李剑钊 on 15/6/15. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "SocketHandle.h" 11 | #import "GetIpAddress.h" 12 | 13 | @interface ViewController () 14 | 15 | @property (nonatomic, strong) SocketHandle *socketHan; 16 | @property (weak, nonatomic) IBOutlet UITextField *ipTextField; 17 | @property (weak, nonatomic) IBOutlet UITextField *inputTextField; 18 | @property (weak, nonatomic) IBOutlet UITextView *outputTextField; 19 | 20 | @end 21 | 22 | @implementation ViewController 23 | 24 | - (void)viewDidLoad { 25 | [super viewDidLoad]; 26 | // Do any additional setup after loading the view, typically from a nib. 27 | } 28 | 29 | - (void)didReceiveMemoryWarning { 30 | [super didReceiveMemoryWarning]; 31 | // Dispose of any resources that can be recreated. 32 | } 33 | 34 | #pragma mark - event 35 | 36 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 37 | [_inputTextField resignFirstResponder]; 38 | [_ipTextField resignFirstResponder]; 39 | } 40 | 41 | - (IBAction)connectBtnTouch:(id)sender { 42 | [self.socketHan initSocket:_ipTextField.text]; 43 | } 44 | 45 | - (IBAction)closeBtnTouch:(id)sender { 46 | [_socketHan closeSocket]; 47 | } 48 | 49 | - (IBAction)sendBtnTouch:(id)sender { 50 | NSString *text = [NSString stringWithFormat:@"App: %@",_inputTextField.text]; 51 | [_socketHan sendData:text]; 52 | [_inputTextField resignFirstResponder]; 53 | } 54 | 55 | #pragma mark - socket delegate 56 | 57 | - (void)socketDidReceiveText:(NSString *)text { 58 | NSString *string = _outputTextField.text; 59 | if (!string) { 60 | string = @""; 61 | } 62 | if (string.length > 0) { 63 | string = [string stringByAppendingString:@"\n"]; 64 | } 65 | string = [string stringByAppendingString:text]; 66 | _outputTextField.text = string; 67 | } 68 | 69 | #pragma mark - getter and setter 70 | 71 | - (SocketHandle *)socketHan { 72 | if (!_socketHan) { 73 | _socketHan = [SocketHandle new]; 74 | _socketHan.delegate = self; 75 | } 76 | return _socketHan; 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /Socket/SocketApp/SocketApp/en.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "UIButton"; normalTitle = "Close"; ObjectID = "6Dy-XF-tgl"; */ 3 | "6Dy-XF-tgl.normalTitle" = "Close"; 4 | 5 | /* Class = "UILabel"; text = "Server Ip:"; ObjectID = "BTf-aT-EzF"; */ 6 | "BTf-aT-EzF.text" = "Server Ip:"; 7 | 8 | /* Class = "UIButton"; normalTitle = "Send"; ObjectID = "aTJ-bZ-DLQ"; */ 9 | "aTJ-bZ-DLQ.normalTitle" = "Send"; 10 | 11 | /* Class = "UIButton"; normalTitle = "Connect"; ObjectID = "foa-2F-67g"; */ 12 | "foa-2F-67g.normalTitle" = "Connect"; 13 | -------------------------------------------------------------------------------- /Socket/SocketApp/SocketApp/ip/GetIpAddress.h: -------------------------------------------------------------------------------- 1 | // 2 | // GetIpAddress.h 3 | // SocketServer 4 | // 5 | // Created by 李剑钊 on 15/6/16. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface GetIpAddress : NSObject 12 | 13 | + (NSString *)getDeviceIpAddress; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Socket/SocketApp/SocketApp/ip/GetIpAddress.m: -------------------------------------------------------------------------------- 1 | // 2 | // GetIpAddress.m 3 | // SocketServer 4 | // 5 | // Created by 李剑钊 on 15/6/16. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import "GetIpAddress.h" 10 | #import "IpAddress.h" 11 | 12 | @implementation GetIpAddress 13 | 14 | + (NSString *)getDeviceIpAddress { 15 | InitAddresses(); 16 | GetIPAddresses(); 17 | GetHWAddresses(); 18 | NSString *ip = [NSString stringWithFormat:@"%s", ip_names[1]]; 19 | FreeAddresses(); 20 | return ip; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Socket/SocketApp/SocketApp/ip/IpAddress.h: -------------------------------------------------------------------------------- 1 | // 2 | // IpAddress.h 3 | // SocketServer 4 | // 5 | // Created by 李剑钊 on 15/6/16. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #ifndef __SocketServer__IpAddress__ 10 | #define __SocketServer__IpAddress__ 11 | 12 | #include 13 | 14 | #define MAXADDRS 32 15 | extern char *if_names[MAXADDRS]; 16 | extern char *ip_names[MAXADDRS]; 17 | extern char *hw_addrs[MAXADDRS]; 18 | extern unsigned long ip_addrs[MAXADDRS]; 19 | // Function prototypes 20 | void InitAddresses(); 21 | void FreeAddresses(); 22 | void GetIPAddresses(); 23 | void GetHWAddresses(); 24 | 25 | #endif /* defined(__SocketServer__IpAddress__) */ 26 | -------------------------------------------------------------------------------- /Socket/SocketApp/SocketApp/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SocketApp 4 | // 5 | // Created by 李剑钊 on 15/6/15. 6 | // Copyright (c) 2015年 sunli. 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 | -------------------------------------------------------------------------------- /Socket/SocketApp/SocketAppTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.kugou.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Socket/SocketApp/SocketAppTests/SocketAppTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SocketAppTests.m 3 | // SocketAppTests 4 | // 5 | // Created by 李剑钊 on 15/6/15. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface SocketAppTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation SocketAppTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServer.xcodeproj/project.xcworkspace/xcuserdata/sunli.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunljz/demo/518258a6335ff8886f8c78edec5760a31204b72e/Socket/SocketServer/SocketServer.xcodeproj/project.xcworkspace/xcuserdata/sunli.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServer.xcodeproj/xcuserdata/sunli.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServer.xcodeproj/xcuserdata/sunli.xcuserdatad/xcschemes/SocketServer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServer.xcodeproj/xcuserdata/sunli.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SocketServer.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | A1D39B5B1B2EC90900B56E57 16 | 17 | primary 18 | 19 | 20 | A1D39B741B2EC90900B56E57 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServer/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // SocketServer 4 | // 5 | // Created by 李剑钊 on 15/6/15. 6 | // Copyright (c) 2015年 sunli. 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 | -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServer/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // SocketServer 4 | // 5 | // Created by 李剑钊 on 15/6/15. 6 | // Copyright (c) 2015年 sunli. 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 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // 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. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServer/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServer/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServer/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.kugou.$(PRODUCT_NAME:rfc1034identifier) 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 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServer/MyServer.h: -------------------------------------------------------------------------------- 1 | // 2 | // MyServer.h 3 | // SocketServer 4 | // 5 | // Created by 李剑钊 on 15/6/15. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol SocketDelegate 12 | @optional 13 | - (void)socketDidReceiveText:(NSString *)text; 14 | 15 | @end 16 | 17 | @interface MyServer : NSObject 18 | 19 | @property (nonatomic, assign, readonly) BOOL isSocketOpened; 20 | @property (nonatomic, weak) iddelegate; 21 | 22 | - (void)initSocket; 23 | 24 | - (void)sendData:(NSString *)text; 25 | 26 | - (void)closeSocket; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServer/MyServer.m: -------------------------------------------------------------------------------- 1 | // 2 | // MyServer.m 3 | // SocketServer 4 | // 5 | // Created by 李剑钊 on 15/6/15. 6 | // Copyright (c) 2015年 ;. All rights reserved. 7 | // 8 | 9 | #import "MyServer.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #define PORT 6677 18 | #define MAXDATASIZE 100 19 | #define LENGTH_OF_LISTEN_QUEUE 20 20 | #define BUFFER_SIZE 30000 21 | #define THREAD_MAX 5 22 | 23 | @interface MyServer () 24 | 25 | @property (nonatomic, assign) BOOL isIniting; 26 | @property (atomic, assign) int server_socket; 27 | @property (nonatomic, assign) int client_socket; 28 | 29 | @end 30 | 31 | @implementation MyServer 32 | 33 | - (instancetype)init 34 | { 35 | self = [super init]; 36 | if (self) { 37 | 38 | } 39 | return self; 40 | } 41 | 42 | - (void)initSocket { 43 | if (_isIniting) { 44 | return; 45 | } else if (_isSocketOpened) { 46 | return; 47 | } 48 | 49 | self.isIniting = YES; 50 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 51 | // 服务器socket地址结构 52 | struct sockaddr_in server_addr; 53 | bzero(&server_addr, sizeof(server_addr)); 54 | server_addr.sin_family = AF_INET; 55 | server_addr.sin_addr.s_addr = htons(INADDR_ANY); 56 | server_addr.sin_port = htons(PORT); 57 | 58 | // 创建socket 59 | int server_socket = socket(server_addr.sin_family, SOCK_STREAM, IPPROTO_TCP); 60 | if (server_socket < 0) { 61 | NSLog(@"create socket failed"); 62 | return; 63 | } 64 | self.server_socket = server_socket; 65 | 66 | // 绑定socket 67 | int bind_socker = bind(server_socket, (const struct sockaddr *)&server_addr, sizeof(server_addr)); 68 | if (bind_socker) { 69 | NSLog(@"bind socket failed"); 70 | return; 71 | } 72 | 73 | int listen_socker = listen(server_socket, LENGTH_OF_LISTEN_QUEUE); 74 | if (listen_socker) { 75 | NSLog(@"listen socket failed"); 76 | return; 77 | } 78 | 79 | _isSocketOpened = YES; 80 | _isIniting = NO; 81 | 82 | while (_isSocketOpened) { 83 | NSLog(@"socket star"); 84 | struct sockaddr_in client_addr; 85 | socklen_t lenght = sizeof(client_addr); 86 | 87 | int new_client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &lenght); 88 | if (new_client_socket < 0) { 89 | NSLog(@"server accept failed"); 90 | break; 91 | } 92 | self.client_socket = new_client_socket; 93 | 94 | NSLog(@"once client connected"); 95 | [self readSocket:new_client_socket]; 96 | } 97 | 98 | [self closeSocket]; 99 | }); 100 | } 101 | 102 | - (void)readSocket:(int)clientSocket { 103 | char buffer[BUFFER_SIZE]; 104 | buffer[0] = ' '; 105 | 106 | while (buffer[0] != '\0') { 107 | bzero(buffer, BUFFER_SIZE); 108 | // 接收客户端的信息到buffer中 109 | recv(clientSocket, buffer, BUFFER_SIZE, 0); 110 | NSLog(@"client buffer:%s",buffer); 111 | NSString *text = [NSString stringWithCString:buffer encoding:NSUTF8StringEncoding]; 112 | if ([_delegate respondsToSelector:@selector(socketDidReceiveText:)]) { 113 | if ([NSThread isMainThread]) { 114 | [_delegate socketDidReceiveText:text]; 115 | } else { 116 | dispatch_async(dispatch_get_main_queue(), ^{ 117 | [_delegate socketDidReceiveText:text]; 118 | }); 119 | } 120 | } 121 | } 122 | 123 | // NSLog(@"client close"); 124 | // close(clientSocket); 125 | } 126 | 127 | - (void)sendData:(NSString *)text { 128 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 129 | const char *buffer = [text UTF8String]; 130 | ssize_t result = send(_client_socket, buffer, strlen(buffer), 0); 131 | if (result < 0) { 132 | NSLog(@"send data failed"); 133 | } 134 | }); 135 | } 136 | 137 | - (void)closeSocket { 138 | if (_isSocketOpened) { 139 | close(_server_socket); 140 | _isSocketOpened = NO; 141 | _isIniting = NO; 142 | } 143 | } 144 | 145 | @end 146 | -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServer/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // SocketServer 4 | // 5 | // Created by 李剑钊 on 15/6/15. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServer/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // SocketServer 4 | // 5 | // Created by 李剑钊 on 15/6/15. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "MyServer.h" 11 | #import "GetIpAddress.h" 12 | 13 | @interface ViewController () 14 | 15 | @property (nonatomic, strong) MyServer *server; 16 | @property (weak, nonatomic) IBOutlet UILabel *ipLabel; 17 | @property (weak, nonatomic) IBOutlet UITextField *inputTextField; 18 | @property (weak, nonatomic) IBOutlet UITextView *outputTextView; 19 | 20 | @end 21 | 22 | @implementation ViewController 23 | 24 | - (void)viewDidLoad { 25 | [super viewDidLoad]; 26 | // Do any additional setup after loading the view, typically from a nib. 27 | _ipLabel.text = [GetIpAddress getDeviceIpAddress]; 28 | } 29 | 30 | - (void)didReceiveMemoryWarning { 31 | [super didReceiveMemoryWarning]; 32 | // Dispose of any resources that can be recreated. 33 | } 34 | 35 | #pragma mark - event 36 | 37 | - (IBAction)initSocketBtnTouch:(id)sender { 38 | [self.server initSocket]; 39 | } 40 | 41 | - (IBAction)closeBtnTouch:(id)sender { 42 | [_server closeSocket]; 43 | } 44 | - (IBAction)sendBtnTouch:(id)sender { 45 | NSString *text = [NSString stringWithFormat:@"Server: %@",_inputTextField.text]; 46 | [_server sendData:text]; 47 | [_inputTextField resignFirstResponder]; 48 | } 49 | 50 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 51 | [_inputTextField resignFirstResponder]; 52 | } 53 | 54 | #pragma mark - socket delegate 55 | 56 | - (void)socketDidReceiveText:(NSString *)text { 57 | NSString *string = _outputTextView.text; 58 | if (!string) { 59 | string = @""; 60 | } 61 | if (string.length > 0) { 62 | string = [string stringByAppendingString:@"\n"]; 63 | } 64 | string = [string stringByAppendingString:text]; 65 | _outputTextView.text = string; 66 | } 67 | 68 | #pragma mark - getter and setter 69 | 70 | - (MyServer *)server { 71 | if (!_server) { 72 | _server = [MyServer new]; 73 | _server.delegate = self; 74 | } 75 | return _server; 76 | } 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServer/ip/GetIpAddress.h: -------------------------------------------------------------------------------- 1 | // 2 | // GetIpAddress.h 3 | // SocketServer 4 | // 5 | // Created by 李剑钊 on 15/6/16. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface GetIpAddress : NSObject 12 | 13 | + (NSString *)getDeviceIpAddress; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServer/ip/GetIpAddress.m: -------------------------------------------------------------------------------- 1 | // 2 | // GetIpAddress.m 3 | // SocketServer 4 | // 5 | // Created by 李剑钊 on 15/6/16. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import "GetIpAddress.h" 10 | #import "IpAddress.h" 11 | 12 | @implementation GetIpAddress 13 | 14 | + (NSString *)getDeviceIpAddress { 15 | InitAddresses(); 16 | GetIPAddresses(); 17 | GetHWAddresses(); 18 | NSString *ip = [NSString stringWithFormat:@"%s", ip_names[1]]; 19 | FreeAddresses(); 20 | return ip; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServer/ip/IpAddress.h: -------------------------------------------------------------------------------- 1 | // 2 | // IpAddress.h 3 | // SocketServer 4 | // 5 | // Created by 李剑钊 on 15/6/16. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #ifndef __SocketServer__IpAddress__ 10 | #define __SocketServer__IpAddress__ 11 | 12 | #include 13 | 14 | #define MAXADDRS 32 15 | extern char *if_names[MAXADDRS]; 16 | extern char *ip_names[MAXADDRS]; 17 | extern char *hw_addrs[MAXADDRS]; 18 | extern unsigned long ip_addrs[MAXADDRS]; 19 | // Function prototypes 20 | void InitAddresses(); 21 | void FreeAddresses(); 22 | void GetIPAddresses(); 23 | void GetHWAddresses(); 24 | 25 | #endif /* defined(__SocketServer__IpAddress__) */ 26 | -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SocketServer 4 | // 5 | // Created by 李剑钊 on 15/6/15. 6 | // Copyright (c) 2015年 sunli. 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 | -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServerTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.kugou.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Socket/SocketServer/SocketServerTests/SocketServerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SocketServerTests.m 3 | // SocketServerTests 4 | // 5 | // Created by 李剑钊 on 15/6/15. 6 | // Copyright (c) 2015年 sunli. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface SocketServerTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation SocketServerTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /SpringAnimation/SpringAnimation.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SpringAnimation/SpringAnimation.xcodeproj/project.xcworkspace/xcuserdata/sunli.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunljz/demo/518258a6335ff8886f8c78edec5760a31204b72e/SpringAnimation/SpringAnimation.xcodeproj/project.xcworkspace/xcuserdata/sunli.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /SpringAnimation/SpringAnimation.xcodeproj/xcuserdata/sunli.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /SpringAnimation/SpringAnimation.xcodeproj/xcuserdata/sunli.xcuserdatad/xcschemes/SpringAnimation.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 | -------------------------------------------------------------------------------- /SpringAnimation/SpringAnimation.xcodeproj/xcuserdata/sunli.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SpringAnimation.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | A15005071B6737F800B9A7B1 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /SpringAnimation/SpringAnimation/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SpringAnimation 4 | // 5 | // Created by 李剑钊 on 15/7/28. 6 | // Copyright © 2015年 sunli. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(application: UIApplication) { 23 | // 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. 24 | // 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. 25 | } 26 | 27 | func applicationDidEnterBackground(application: UIApplication) { 28 | // 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. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(application: UIApplication) { 33 | // 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. 34 | } 35 | 36 | func applicationDidBecomeActive(application: UIApplication) { 37 | // 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. 38 | } 39 | 40 | func applicationWillTerminate(application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /SpringAnimation/SpringAnimation/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /SpringAnimation/SpringAnimation/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 26 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /SpringAnimation/SpringAnimation/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /SpringAnimation/SpringAnimation/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 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /SpringAnimation/SpringAnimation/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SpringAnimation 4 | // 5 | // Created by 李剑钊 on 15/7/28. 6 | // Copyright © 2015年 sunli. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import QuartzCore 11 | 12 | class ViewController: UIViewController { 13 | 14 | @IBOutlet weak var label: UILabel! 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | // Do any additional setup after loading the view, typically from a nib. 19 | } 20 | 21 | override func didReceiveMemoryWarning() { 22 | super.didReceiveMemoryWarning() 23 | // Dispose of any resources that can be recreated. 24 | } 25 | 26 | override func touchesEnded(touches: Set, withEvent event: UIEvent?) { 27 | let spring = CASpringAnimation(keyPath: "position.x") 28 | spring.damping = 5; 29 | spring.stiffness = 100; 30 | spring.mass = 1; 31 | spring.initialVelocity = -30; 32 | spring.fromValue = label.layer.position.x; 33 | spring.toValue = label.layer.position.x + 50; 34 | spring.duration = spring.settlingDuration; 35 | label.layer.addAnimation(spring, forKey: spring.keyPath); 36 | } 37 | /* 38 | mass 质量,影响图层运动时的弹簧惯性,质量越大,弹簧拉伸和压缩的幅度越大 39 | stiffness 刚度系数(劲度系数/弹性系数),刚度系数越大,形变产生的力就越大,运动越快 40 | damping 阻尼系数,阻止弹簧伸缩的系数,阻尼系数越大,停止越快 41 | initialVelocity 初始速率 42 | settlingDuration 结算时间 返回弹簧动画到停止时的估算时间,根据当前的动画参数估算 43 | */ 44 | } 45 | 46 | -------------------------------------------------------------------------------- /WatchDemo/WatchApp Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "screenWidth" : "{130,145}", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "watch", 10 | "screenWidth" : "{146,165}", 11 | "scale" : "2x" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /WatchDemo/WatchApp Extension/Assets.xcassets/Complication.complicationset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "assets" : [ 3 | { 4 | "idiom" : "watch", 5 | "filename" : "Circular.imageset", 6 | "role" : "circular" 7 | }, 8 | { 9 | "idiom" : "watch", 10 | "filename" : "Modular.imageset", 11 | "role" : "modular" 12 | }, 13 | { 14 | "idiom" : "watch", 15 | "filename" : "Utilitarian.imageset", 16 | "role" : "utilitarian" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /WatchDemo/WatchApp Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "screenWidth" : "{130,145}", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "watch", 10 | "screenWidth" : "{146,165}", 11 | "scale" : "2x" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /WatchDemo/WatchApp Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "screenWidth" : "{130,145}", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "watch", 10 | "screenWidth" : "{146,165}", 11 | "scale" : "2x" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /WatchDemo/WatchApp Extension/ComplicationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ComplicationController.swift 3 | // WatchApp Extension 4 | // 5 | // Created by 李剑钊 on 15/7/30. 6 | // Copyright © 2015年 sunli. All rights reserved. 7 | // 8 | 9 | import ClockKit 10 | 11 | 12 | class ComplicationController: NSObject, CLKComplicationDataSource { 13 | 14 | // MARK: - Timeline Configuration 15 | 16 | func getSupportedTimeTravelDirectionsForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimeTravelDirections) -> Void) { 17 | handler([.Forward, .Backward]) 18 | } 19 | 20 | func getTimelineStartDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) { 21 | handler(nil) 22 | } 23 | 24 | func getTimelineEndDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) { 25 | handler(nil) 26 | } 27 | 28 | func getPrivacyBehaviorForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationPrivacyBehavior) -> Void) { 29 | handler(.ShowOnLockScreen) 30 | } 31 | 32 | // MARK: - Timeline Population 33 | 34 | func getCurrentTimelineEntryForComplication(complication: CLKComplication, withHandler handler: ((CLKComplicationTimelineEntry?) -> Void)) { 35 | // Call the handler with the current timeline entry 36 | handler(nil) 37 | } 38 | 39 | func getTimelineEntriesForComplication(complication: CLKComplication, beforeDate date: NSDate, limit: Int, withHandler handler: (([CLKComplicationTimelineEntry]?) -> Void)) { 40 | // Call the handler with the timeline entries prior to the given date 41 | handler(nil) 42 | } 43 | 44 | func getTimelineEntriesForComplication(complication: CLKComplication, afterDate date: NSDate, limit: Int, withHandler handler: (([CLKComplicationTimelineEntry]?) -> Void)) { 45 | // Call the handler with the timeline entries after to the given date 46 | handler(nil) 47 | } 48 | 49 | // MARK: - Update Scheduling 50 | 51 | func getNextRequestedUpdateDateWithHandler(handler: (NSDate?) -> Void) { 52 | // Call the handler with the date when you would next like to be given the opportunity to update your complication content 53 | handler(nil); 54 | } 55 | 56 | // MARK: - Placeholder Templates 57 | 58 | func getPlaceholderTemplateForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTemplate?) -> Void) { 59 | // This method will be called once per supported complication, and the results will be cached 60 | handler(nil) 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /WatchDemo/WatchApp Extension/ExtensionDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExtensionDelegate.swift 3 | // WatchApp Extension 4 | // 5 | // Created by 李剑钊 on 15/7/30. 6 | // Copyright © 2015年 sunli. All rights reserved. 7 | // 8 | 9 | import WatchKit 10 | 11 | class ExtensionDelegate: NSObject, WKExtensionDelegate { 12 | 13 | func applicationDidFinishLaunching() { 14 | // Perform any final initialization of your application. 15 | } 16 | 17 | func applicationDidBecomeActive() { 18 | // 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. 19 | } 20 | 21 | func applicationWillResignActive() { 22 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 23 | // Use this method to pause ongoing tasks, disable timers, etc. 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /WatchDemo/WatchApp Extension/GlanceController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GlanceController.swift 3 | // WatchApp Extension 4 | // 5 | // Created by 李剑钊 on 15/7/30. 6 | // Copyright © 2015年 sunli. All rights reserved. 7 | // 8 | 9 | import WatchKit 10 | import Foundation 11 | 12 | 13 | class GlanceController: WKInterfaceController { 14 | 15 | override func awakeWithContext(context: AnyObject?) { 16 | super.awakeWithContext(context) 17 | 18 | // Configure interface objects here. 19 | } 20 | 21 | override func willActivate() { 22 | // This method is called when watch view controller is about to be visible to user 23 | super.willActivate() 24 | } 25 | 26 | override func didDeactivate() { 27 | // This method is called when watch view controller is no longer visible 28 | super.didDeactivate() 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /WatchDemo/WatchApp Extension/ImageInterfaceController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageInterfaceController.swift 3 | // WatchDemo 4 | // 5 | // Created by 李剑钊 on 15/8/4. 6 | // Copyright © 2015年 sunli. All rights reserved. 7 | // 8 | 9 | import WatchKit 10 | import Foundation 11 | 12 | 13 | class ImageInterfaceController: WKInterfaceController { 14 | 15 | @IBOutlet var imageView: WKInterfaceImage! 16 | override func awakeWithContext(context: AnyObject?) { 17 | super.awakeWithContext(context) 18 | 19 | // Configure interface objects here. 20 | } 21 | 22 | override func willActivate() { 23 | // This method is called when watch view controller is about to be visible to user 24 | super.willActivate() 25 | 26 | } 27 | 28 | override func didDeactivate() { 29 | // This method is called when watch view controller is no longer visible 30 | super.didDeactivate() 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /WatchDemo/WatchApp Extension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | WatchApp Extension 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | XPC! 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | CLKComplicationPrincipalClass 26 | $(PRODUCT_MODULE_NAME).ComplicationController 27 | CLKComplicationSupportedFamilies 28 | 29 | CLKComplicationFamilyModularSmall 30 | CLKComplicationFamilyModularLarge 31 | CLKComplicationFamilyUtilitarianSmall 32 | CLKComplicationFamilyUtilitarianLarge 33 | CLKComplicationFamilyCircularSmall 34 | 35 | NSExtension 36 | 37 | NSExtensionAttributes 38 | 39 | WKAppBundleIdentifier 40 | com.sunli.WatchDemo.watchkitapp 41 | 42 | NSExtensionPointIdentifier 43 | com.apple.watchkit 44 | 45 | RemoteInterfacePrincipalClass 46 | $(PRODUCT_MODULE_NAME).InterfaceController 47 | WKExtensionDelegateClassName 48 | $(PRODUCT_MODULE_NAME).ExtensionDelegate 49 | 50 | 51 | -------------------------------------------------------------------------------- /WatchDemo/WatchApp Extension/InterfaceController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InterfaceController.swift 3 | // WatchApp Extension 4 | // 5 | // Created by 李剑钊 on 15/7/30. 6 | // Copyright © 2015年 sunli. All rights reserved. 7 | // 8 | 9 | import WatchKit 10 | import Foundation 11 | 12 | 13 | class InterfaceController: WKInterfaceController { 14 | 15 | @IBOutlet var tipsLabel: WKInterfaceLabel! 16 | @IBOutlet var colorBtn: WKInterfaceButton! 17 | var colorStyle = 0; 18 | 19 | override func awakeWithContext(context: AnyObject?) { 20 | super.awakeWithContext(context) 21 | 22 | // Configure interface objects here. 23 | } 24 | 25 | override func willActivate() { 26 | // This method is called when watch view controller is about to be visible to user 27 | super.willActivate() 28 | 29 | self.configTipsLabel() 30 | } 31 | 32 | override func didDeactivate() { 33 | // This method is called when watch view controller is no longer visible 34 | super.didDeactivate() 35 | } 36 | 37 | func configTipsLabel() { 38 | let font = UIFont.systemFontOfSize(16) 39 | let helloDic = [NSFontAttributeName:font,NSForegroundColorAttributeName:UIColor.whiteColor()] 40 | 41 | let mAttr = NSMutableAttributedString(string: "Hello World!", attributes: helloDic) 42 | 43 | let nameDic = [NSFontAttributeName:font,NSForegroundColorAttributeName:UIColor.yellowColor()] 44 | let nameAttr = NSAttributedString(string: " I'm a Developer", attributes: nameDic) 45 | 46 | mAttr.appendAttributedString(nameAttr) 47 | tipsLabel.setAttributedText(mAttr) 48 | } 49 | 50 | @IBAction func buttonTouched() { 51 | if colorStyle == 0 { 52 | colorStyle = 1; 53 | colorBtn.setBackgroundColor(UIColor.grayColor()) 54 | } else { 55 | colorStyle = 0; 56 | colorBtn.setBackgroundColor(UIColor.clearColor()) 57 | } 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /WatchDemo/WatchApp Extension/NotificationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationController.swift 3 | // WatchApp Extension 4 | // 5 | // Created by 李剑钊 on 15/7/30. 6 | // Copyright © 2015年 sunli. All rights reserved. 7 | // 8 | 9 | import WatchKit 10 | import Foundation 11 | 12 | 13 | class NotificationController: WKUserNotificationInterfaceController { 14 | 15 | override init() { 16 | // Initialize variables here. 17 | super.init() 18 | 19 | // Configure interface objects here. 20 | } 21 | 22 | override func willActivate() { 23 | // This method is called when watch view controller is about to be visible to user 24 | super.willActivate() 25 | } 26 | 27 | override func didDeactivate() { 28 | // This method is called when watch view controller is no longer visible 29 | super.didDeactivate() 30 | } 31 | 32 | /* 33 | override func didReceiveLocalNotification(localNotification: UILocalNotification, withCompletion completionHandler: ((WKUserNotificationInterfaceType) -> Void)) { 34 | // This method is called when a local notification needs to be presented. 35 | // Implement it if you use a dynamic notification interface. 36 | // Populate your dynamic notification interface as quickly as possible. 37 | // 38 | // After populating your dynamic notification interface call the completion block. 39 | completionHandler(.Custom) 40 | } 41 | */ 42 | 43 | /* 44 | override func didReceiveRemoteNotification(remoteNotification: [NSObject : AnyObject], withCompletion completionHandler: ((WKUserNotificationInterfaceType) -> Void)) { 45 | // This method is called when a remote notification needs to be presented. 46 | // Implement it if you use a dynamic notification interface. 47 | // Populate your dynamic notification interface as quickly as possible. 48 | // 49 | // After populating your dynamic notification interface call the completion block. 50 | completionHandler(.Custom) 51 | } 52 | */ 53 | } 54 | -------------------------------------------------------------------------------- /WatchDemo/WatchApp Extension/PushNotificationPayload.apns: -------------------------------------------------------------------------------- 1 | { 2 | "aps": { 3 | "alert": { 4 | "body": "Test message", 5 | "title": "Optional title" 6 | }, 7 | "category": "myCategory" 8 | }, 9 | 10 | "WatchKit Simulator Actions": [ 11 | { 12 | "title": "First Button", 13 | "identifier": "firstButtonAction" 14 | } 15 | ], 16 | 17 | "customKey": "Use this file to define a testing payload for your notifications. The aps dictionary specifies the category, alert text and title. The WatchKit Simulator Actions array can provide info for one or more action buttons in addition to the standard Dismiss button. Any other top level keys are custom payload. If you have multiple such JSON files in your project, you'll be able to select them when choosing to debug the notification interface of your Watch App." 18 | } 19 | -------------------------------------------------------------------------------- /WatchDemo/WatchApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "24x24", 5 | "idiom" : "watch", 6 | "scale" : "2x", 7 | "role" : "notificationCenter", 8 | "subtype" : "38mm" 9 | }, 10 | { 11 | "size" : "27.5x27.5", 12 | "idiom" : "watch", 13 | "scale" : "2x", 14 | "role" : "notificationCenter", 15 | "subtype" : "42mm" 16 | }, 17 | { 18 | "size" : "29x29", 19 | "idiom" : "watch", 20 | "role" : "companionSettings", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "size" : "29x29", 25 | "idiom" : "watch", 26 | "role" : "companionSettings", 27 | "scale" : "3x" 28 | }, 29 | { 30 | "size" : "40x40", 31 | "idiom" : "watch", 32 | "scale" : "2x", 33 | "role" : "appLauncher", 34 | "subtype" : "38mm" 35 | }, 36 | { 37 | "size" : "44x44", 38 | "idiom" : "watch", 39 | "scale" : "2x", 40 | "role" : "longLook", 41 | "subtype" : "42mm" 42 | }, 43 | { 44 | "size" : "86x86", 45 | "idiom" : "watch", 46 | "scale" : "2x", 47 | "role" : "quickLook", 48 | "subtype" : "38mm" 49 | }, 50 | { 51 | "size" : "98x98", 52 | "idiom" : "watch", 53 | "scale" : "2x", 54 | "role" : "quickLook", 55 | "subtype" : "42mm" 56 | } 57 | ], 58 | "info" : { 59 | "version" : 1, 60 | "author" : "xcode" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /WatchDemo/WatchApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /WatchDemo/WatchApp/Base.lproj/Interface.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 21 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /WatchDemo/WatchApp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | WatchDemo 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | UISupportedInterfaceOrientations 26 | 27 | UIInterfaceOrientationPortrait 28 | UIInterfaceOrientationPortraitUpsideDown 29 | 30 | WKCompanionAppBundleIdentifier 31 | com.sunli.WatchDemo 32 | WKWatchKitApp 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /WatchDemo/WatchApp/dragon-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunljz/demo/518258a6335ff8886f8c78edec5760a31204b72e/WatchDemo/WatchApp/dragon-0.png -------------------------------------------------------------------------------- /WatchDemo/WatchApp/dragon-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunljz/demo/518258a6335ff8886f8c78edec5760a31204b72e/WatchDemo/WatchApp/dragon-1.png -------------------------------------------------------------------------------- /WatchDemo/WatchApp/dragon-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunljz/demo/518258a6335ff8886f8c78edec5760a31204b72e/WatchDemo/WatchApp/dragon-2.png -------------------------------------------------------------------------------- /WatchDemo/WatchApp/dragon-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunljz/demo/518258a6335ff8886f8c78edec5760a31204b72e/WatchDemo/WatchApp/dragon-3.png -------------------------------------------------------------------------------- /WatchDemo/WatchApp/dragon-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunljz/demo/518258a6335ff8886f8c78edec5760a31204b72e/WatchDemo/WatchApp/dragon-4.png -------------------------------------------------------------------------------- /WatchDemo/WatchApp/dragon-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunljz/demo/518258a6335ff8886f8c78edec5760a31204b72e/WatchDemo/WatchApp/dragon-5.png -------------------------------------------------------------------------------- /WatchDemo/WatchDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WatchDemo/WatchDemo.xcodeproj/project.xcworkspace/xcuserdata/sunli.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunljz/demo/518258a6335ff8886f8c78edec5760a31204b72e/WatchDemo/WatchDemo.xcodeproj/project.xcworkspace/xcuserdata/sunli.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /WatchDemo/WatchDemo.xcodeproj/xcuserdata/sunli.xcuserdatad/xcschemes/WatchDemo.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 | -------------------------------------------------------------------------------- /WatchDemo/WatchDemo.xcodeproj/xcuserdata/sunli.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Complication - WatchApp.xcscheme 8 | 9 | orderHint 10 | 4 11 | 12 | Glance - WatchApp.xcscheme 13 | 14 | orderHint 15 | 3 16 | 17 | Notification - WatchApp.xcscheme 18 | 19 | orderHint 20 | 2 21 | 22 | WatchApp.xcscheme 23 | 24 | orderHint 25 | 1 26 | 27 | WatchDemo.xcscheme 28 | 29 | orderHint 30 | 0 31 | 32 | 33 | SuppressBuildableAutocreation 34 | 35 | A1F60A221B6A0F1F001C6348 36 | 37 | primary 38 | 39 | 40 | A1F60A391B6A0FBF001C6348 41 | 42 | primary 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /WatchDemo/WatchDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // WatchDemo 4 | // 5 | // Created by 李剑钊 on 15/7/30. 6 | // Copyright © 2015年 sunli. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(application: UIApplication) { 23 | // 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. 24 | // 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. 25 | } 26 | 27 | func applicationDidEnterBackground(application: UIApplication) { 28 | // 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. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(application: UIApplication) { 33 | // 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. 34 | } 35 | 36 | func applicationDidBecomeActive(application: UIApplication) { 37 | // 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. 38 | } 39 | 40 | func applicationWillTerminate(application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /WatchDemo/WatchDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /WatchDemo/WatchDemo/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 | 27 | 28 | -------------------------------------------------------------------------------- /WatchDemo/WatchDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /WatchDemo/WatchDemo/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 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /WatchDemo/WatchDemo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // WatchDemo 4 | // 5 | // Created by 李剑钊 on 15/7/30. 6 | // Copyright © 2015年 sunli. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | override func didReceiveMemoryWarning() { 19 | super.didReceiveMemoryWarning() 20 | // Dispose of any resources that can be recreated. 21 | } 22 | 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /iOS9/UITestDemo/UITestDemo UI Tests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /iOS9/UITestDemo/UITestDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /iOS9/UITestDemo/UITestDemo.xcodeproj/project.xcworkspace/xcuserdata/sunli.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunljz/demo/518258a6335ff8886f8c78edec5760a31204b72e/iOS9/UITestDemo/UITestDemo.xcodeproj/project.xcworkspace/xcuserdata/sunli.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /iOS9/UITestDemo/UITestDemo.xcodeproj/xcuserdata/sunli.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /iOS9/UITestDemo/UITestDemo.xcodeproj/xcuserdata/sunli.xcuserdatad/xcschemes/UITestDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /iOS9/UITestDemo/UITestDemo.xcodeproj/xcuserdata/sunli.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | UITestDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | A13871361B318E690067A3D2 16 | 17 | primary 18 | 19 | 20 | A138714F1B31942F0067A3D2 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /iOS9/UITestDemo/UITestDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // UITestDemo 4 | // 5 | // Created by 李剑钊 on 15/6/17. 6 | // Copyright © 2015年 sunli. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(application: UIApplication) { 23 | // 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. 24 | // 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. 25 | } 26 | 27 | func applicationDidEnterBackground(application: UIApplication) { 28 | // 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. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(application: UIApplication) { 33 | // 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. 34 | } 35 | 36 | func applicationDidBecomeActive(application: UIApplication) { 37 | // 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. 38 | } 39 | 40 | func applicationWillTerminate(application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /iOS9/UITestDemo/UITestDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /iOS9/UITestDemo/UITestDemo/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 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /iOS9/UITestDemo/UITestDemo/HomeViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // UITestDemo 4 | // 5 | // Created by 李剑钊 on 15/6/17. 6 | // Copyright © 2015年 sunli. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | let name = "sun" 12 | let psd = "111111" 13 | 14 | let myTitle = "登录" 15 | let loadingText = "登录中.." 16 | 17 | var firstAppear = true; 18 | 19 | class HomeViewController: UIViewController { 20 | @IBOutlet weak var nameField: UITextField! 21 | @IBOutlet weak var psdField: UITextField! 22 | 23 | 24 | 25 | override func viewDidLoad() { 26 | super.viewDidLoad() 27 | // Do any additional setup after loading the view, typically from a nib. 28 | self.title = myTitle; 29 | } 30 | 31 | override func didReceiveMemoryWarning() { 32 | super.didReceiveMemoryWarning() 33 | // Dispose of any resources that can be recreated. 34 | } 35 | 36 | @IBAction func loginBtnTouch(sender: UIButton) { 37 | self.nameField.resignFirstResponder(); 38 | self.psdField.resignFirstResponder(); 39 | self.title = loadingText; 40 | sender.enabled = false 41 | let queue = NSOperationQueue.init(); 42 | queue.addOperationWithBlock { () -> Void in 43 | // 模拟验证的过程 44 | NSThread.sleepForTimeInterval(2) 45 | NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in 46 | self.title = myTitle; 47 | sender.enabled = true 48 | if self.nameField.text == name && self.psdField.text == psd { 49 | let userDef = NSUserDefaults.standardUserDefaults() 50 | userDef.setObject(self.nameField.text!, forKey: "name"); 51 | let sb = UIStoryboard.init(name:"Main",bundle:NSBundle.mainBundle()) 52 | let viewCro = sb.instantiateViewControllerWithIdentifier("InfoViewController") 53 | self.navigationController!.pushViewController(viewCro, animated: true) 54 | } else { 55 | let alert = UIAlertView.init(title:"",message:"登录失败",delegate:nil,cancelButtonTitle:"确定") 56 | alert.accessibilityIdentifier = "loginAlert" 57 | alert.accessibilityLabel = "loginAlert" 58 | alert.show() 59 | } 60 | }) 61 | } 62 | } 63 | 64 | @IBAction func clearBtnTouch(sender: UIButton) { 65 | self.nameField.text = nil; 66 | self.psdField.text = nil; 67 | self.nameField.resignFirstResponder(); 68 | self.psdField.resignFirstResponder(); 69 | } 70 | 71 | func alertView(alertView: UIAlertView, didDismissWithButtonIndex buttonIndex: Int) { 72 | 73 | } 74 | 75 | override func touchesEnded(touches: Set, withEvent event: UIEvent?) { 76 | self.nameField.resignFirstResponder(); 77 | self.psdField.resignFirstResponder(); 78 | } 79 | 80 | override func viewDidAppear(animated: Bool) { 81 | 82 | } 83 | } 84 | 85 | extension HomeViewController: UIAlertViewDelegate { 86 | 87 | } -------------------------------------------------------------------------------- /iOS9/UITestDemo/UITestDemo/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 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /iOS9/UITestDemo/UITestDemo/InfoViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InfoViewController.swift 3 | // UITestDemo 4 | // 5 | // Created by 李剑钊 on 15/6/17. 6 | // Copyright © 2015年 sunli. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | let sexKey = "sex" 12 | let agekey = "age" 13 | let feelingKey = "feeling" 14 | 15 | class InfoViewController: UIViewController { 16 | @IBOutlet weak var sexSwitch: UISwitch! 17 | @IBOutlet weak var ageLabel: UILabel! 18 | @IBOutlet weak var ageStep: UIStepper! 19 | @IBOutlet weak var feelingTxtView: UITextView! 20 | @IBOutlet weak var modifyBtn: UIButton! 21 | 22 | var isChangingInfo = false 23 | 24 | override func viewDidLoad() { 25 | super.viewDidLoad() 26 | 27 | // Do any additional setup after loading the view. 28 | self.ageStep.accessibilityIdentifier = "ageStep" 29 | self.ageStep.minimumValue = 0 30 | self.ageStep.maximumValue = 100 31 | self.sexSwitch.enabled = false; 32 | self.ageStep.enabled = false; 33 | self.feelingTxtView.userInteractionEnabled = false; 34 | 35 | self.title = "读取中.." 36 | let queue = NSOperationQueue.init(); 37 | queue.addOperationWithBlock { () -> Void in 38 | // 模拟读取数据的过程 39 | NSThread.sleepForTimeInterval(2) 40 | NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in 41 | self.configInfoView() 42 | }) 43 | } 44 | } 45 | 46 | override func didReceiveMemoryWarning() { 47 | super.didReceiveMemoryWarning() 48 | // Dispose of any resources that can be recreated. 49 | } 50 | 51 | 52 | func configInfoView() { 53 | let userDef = NSUserDefaults.standardUserDefaults() 54 | self.title = userDef.stringForKey("name") 55 | self.sexSwitch.on = userDef.boolForKey(sexKey) 56 | let age = userDef.stringForKey(agekey) 57 | self.ageLabel.text = age; 58 | if age != nil { 59 | self.ageStep.value = Double(age!)! 60 | } 61 | self.feelingTxtView.text = userDef.stringForKey(feelingKey) 62 | } 63 | 64 | @IBAction func modifyBtnTouch(sender: UIButton) { 65 | if self.isChangingInfo { 66 | self.toSaveInfo() 67 | } else { 68 | self.toModifyInfo() 69 | } 70 | } 71 | 72 | func toModifyInfo() { 73 | self.isChangingInfo = true; 74 | self.modifyBtn.setTitle("完成", forState: UIControlState.Normal) 75 | self.sexSwitch.enabled = true; 76 | self.ageStep.enabled = true; 77 | self.feelingTxtView.userInteractionEnabled = true; 78 | } 79 | 80 | func toSaveInfo() { 81 | self.isChangingInfo = false; 82 | self.feelingTxtView.resignFirstResponder() 83 | self.modifyBtn.setTitle("修改", forState: UIControlState.Normal) 84 | self.sexSwitch.enabled = false; 85 | self.ageStep.enabled = false; 86 | self.feelingTxtView.userInteractionEnabled = false; 87 | 88 | let myTitle = self.title 89 | self.title = "保存中.." 90 | self.modifyBtn.enabled = false 91 | 92 | let queue = NSOperationQueue.init() 93 | queue.addOperationWithBlock { () -> Void in 94 | // 模拟网络请求过程 95 | NSThread.sleepForTimeInterval(2) 96 | NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in 97 | self.title = myTitle; 98 | self.modifyBtn.enabled = true 99 | 100 | let userDef = NSUserDefaults.standardUserDefaults() 101 | userDef.setBool(self.sexSwitch.on, forKey: sexKey) 102 | let age = String(Int(self.ageStep.value)) 103 | userDef.setObject(age, forKey: agekey) 104 | let text = self.feelingTxtView.text; 105 | if text != nil { 106 | userDef.setObject(text, forKey: feelingKey) 107 | } else { 108 | userDef.removeObjectForKey(feelingKey) 109 | } 110 | }) 111 | } 112 | } 113 | 114 | @IBAction func ageStepValueChanged(sender: UIStepper) { 115 | let age = String(Int(self.ageStep.value)) 116 | self.ageLabel.text = age; 117 | } 118 | 119 | @IBAction func clearBtnTouch(sender: AnyObject) { 120 | self.feelingTxtView.resignFirstResponder() 121 | } 122 | 123 | override func touchesEnded(touches: Set, withEvent event: UIEvent?) { 124 | self.feelingTxtView.resignFirstResponder() 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /iOS9/UITestDemo/UITestDemo/MessageViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MessageViewController.swift 3 | // UITestDemo 4 | // 5 | // Created by 李剑钊 on 15/6/23. 6 | // Copyright © 2015年 sunli. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | let cellId = "cellId" 12 | 13 | class MessageViewController: UIViewController,UITableViewDelegate,UITableViewDataSource { 14 | @IBOutlet weak var tableView: UITableView! 15 | var dataList:[String]? = nil 16 | 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | 20 | // Do any additional setup after loading the view. 21 | self.title = "读取中.." 22 | // self.tableView.registerClass(MessageCell.classForCoder(), forCellReuseIdentifier: cellId) 23 | 24 | let queue = NSOperationQueue.init(); 25 | queue.addOperationWithBlock { () -> Void in 26 | // 模拟读取数据的过程 27 | NSThread.sleepForTimeInterval(2) 28 | NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in 29 | self.title = "我的消息" 30 | self.getData() 31 | self.tableView.reloadData() 32 | }) 33 | } 34 | } 35 | 36 | override func didReceiveMemoryWarning() { 37 | super.didReceiveMemoryWarning() 38 | // Dispose of any resources that can be recreated. 39 | } 40 | 41 | 42 | func getData() { 43 | self.dataList = ["Hello,sun。恭喜你注册成功!","你的密码即将过期,请及时修改,以保证账户安全","你的密码已修改,请注意","你获得VIP体验券一张,有效期是一个月,请尽快使用,谢谢!","ksngoa将你添加为好友","sibo将你添加为好友","min将你拉入黑名单","恭喜你获得了1000个积分奖励,积分可以兑换VIP体验券、动态表情等礼物,详情可留意积分兑换页面。","消息错误"] 44 | } 45 | 46 | func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 47 | if self.dataList != nil { 48 | return self.dataList!.count 49 | } else { 50 | return 0 51 | } 52 | } 53 | 54 | func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 55 | let cell:MessageCell = tableView.dequeueReusableCellWithIdentifier(cellId, forIndexPath: indexPath) as! MessageCell 56 | if self.dataList == nil { 57 | return cell 58 | } 59 | 60 | if indexPath.row >= self.dataList!.count { 61 | return cell 62 | } 63 | 64 | let msg:String = self.dataList![indexPath.row] 65 | let label = cell.msgLabel 66 | label.text = msg 67 | 68 | return cell 69 | } 70 | 71 | func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { 72 | return 80 73 | } 74 | 75 | func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 76 | tableView.deselectRowAtIndexPath(indexPath, animated: true) 77 | } 78 | } 79 | 80 | class MessageCell: UITableViewCell { 81 | @IBOutlet weak var msgLabel: UILabel! 82 | } -------------------------------------------------------------------------------- /iOS9/UITestDemo/UITestDemo/SButton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SButton.swift 3 | // UITestDemo 4 | // 5 | // Created by 李剑钊 on 15/6/19. 6 | // Copyright © 2015年 sunli. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// 仅仅是为了测试子类而创建的 12 | class SButton: UIButton { 13 | override func awakeFromNib() { 14 | self.layer.cornerRadius = 4; 15 | self.layer.borderColor = UIColor.grayColor().CGColor; 16 | self.layer.borderWidth = 1; 17 | } 18 | /* 19 | // Only override drawRect: if you perform custom drawing. 20 | // An empty implementation adversely affects performance during animation. 21 | override func drawRect(rect: CGRect) { 22 | // Drawing code 23 | } 24 | */ 25 | 26 | } 27 | --------------------------------------------------------------------------------